Limit block mass instead of merge set limit + Introduce SigOpCount to TransactionInput (#1790)

* Update constants

* Add to transaction SigOpCount

* Update mass calculation, and move it from InContext to InIsolation

* Update block validation accordingly

* Add SigOpCount validation during TransactionInContext

* Remove checking of mass vs maxMassAcceptedByBlock from consensusStateManager

* Update mining manager with latest changes

* Add SigOpCount to MsgTx.Copy()

* Fix initTestTransactionAcceptanceDataForClone

* Fix all tests in transaction_equal_clone_test.go

* Fix TestBlockMass

* Fix tests in transactionvalidator package

* Add SigOpCount to sighash

* Fix TestPruningDepth

* Fix problems in libkaspawalelt

* Fix integration tests

* Fix CalculateSignatureHash tests

* Remove remaining places talking about block size

* Add sanity check to checkBlockMass to make sure all transactions have their mass filled

* always add own sigOpCount to sigHash

* Update protowire/rpc.md

* Start working on removing any remaining reference to block/tx size

* Update rpc transaction verbose data to include mass rather then size

* Convert verboseData and block size check to mass

* Remove remaining usages of tx size in mempool

* Move transactionEstimatedSerializedSize to transactionvalidator

* Add PopulateMass to fakeRelayInvsContext

* Move PopulateMass to beggining of ValidateAndInsertTransaction + fix in it

* Assign mass a new number for backward-compatibility
This commit is contained in:
Svarog 2021-07-14 14:21:57 +03:00 committed by GitHub
parent 8022e4cbea
commit 369a3bac09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 590 additions and 414 deletions

View File

@ -2,6 +2,7 @@ package appmessage
import ( import (
"encoding/hex" "encoding/hex"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader" "github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes" "github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo" "github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
@ -100,6 +101,7 @@ func domainTransactionInputToTxIn(domainTransactionInput *externalapi.DomainTran
PreviousOutpoint: *domainOutpointToOutpoint(domainTransactionInput.PreviousOutpoint), PreviousOutpoint: *domainOutpointToOutpoint(domainTransactionInput.PreviousOutpoint),
SignatureScript: domainTransactionInput.SignatureScript, SignatureScript: domainTransactionInput.SignatureScript,
Sequence: domainTransactionInput.Sequence, Sequence: domainTransactionInput.Sequence,
SigOpCount: domainTransactionInput.SigOpCount,
} }
} }
@ -148,6 +150,7 @@ func txInToDomainTransactionInput(txIn *TxIn) *externalapi.DomainTransactionInpu
return &externalapi.DomainTransactionInput{ return &externalapi.DomainTransactionInput{
PreviousOutpoint: *outpointToDomainOutpoint(&txIn.PreviousOutpoint), //TODO PreviousOutpoint: *outpointToDomainOutpoint(&txIn.PreviousOutpoint), //TODO
SignatureScript: txIn.SignatureScript, SignatureScript: txIn.SignatureScript,
SigOpCount: txIn.SigOpCount,
Sequence: txIn.Sequence, Sequence: txIn.Sequence,
} }
} }
@ -175,6 +178,7 @@ func RPCTransactionToDomainTransaction(rpcTransaction *RPCTransaction) (*externa
PreviousOutpoint: *previousOutpoint, PreviousOutpoint: *previousOutpoint,
SignatureScript: signatureScript, SignatureScript: signatureScript,
Sequence: input.Sequence, Sequence: input.Sequence,
SigOpCount: input.SigOpCount,
} }
} }
outputs := make([]*externalapi.DomainTransactionOutput, len(rpcTransaction.Outputs)) outputs := make([]*externalapi.DomainTransactionOutput, len(rpcTransaction.Outputs))
@ -253,6 +257,7 @@ func DomainTransactionToRPCTransaction(transaction *externalapi.DomainTransactio
PreviousOutpoint: previousOutpoint, PreviousOutpoint: previousOutpoint,
SignatureScript: signatureScript, SignatureScript: signatureScript,
Sequence: input.Sequence, Sequence: input.Sequence,
SigOpCount: input.SigOpCount,
} }
} }
outputs := make([]*RPCTransactionOutput, len(transaction.Outputs)) outputs := make([]*RPCTransactionOutput, len(transaction.Outputs))

View File

@ -90,16 +90,18 @@ type TxIn struct {
PreviousOutpoint Outpoint PreviousOutpoint Outpoint
SignatureScript []byte SignatureScript []byte
Sequence uint64 Sequence uint64
SigOpCount byte
} }
// NewTxIn returns a new kaspa transaction input with the provided // NewTxIn returns a new kaspa transaction input with the provided
// previous outpoint point and signature script with a default sequence of // previous outpoint point and signature script with a default sequence of
// MaxTxInSequenceNum. // MaxTxInSequenceNum.
func NewTxIn(prevOut *Outpoint, signatureScript []byte, sequence uint64) *TxIn { func NewTxIn(prevOut *Outpoint, signatureScript []byte, sequence uint64, sigOpCount byte) *TxIn {
return &TxIn{ return &TxIn{
PreviousOutpoint: *prevOut, PreviousOutpoint: *prevOut,
SignatureScript: signatureScript, SignatureScript: signatureScript,
Sequence: sequence, Sequence: sequence,
SigOpCount: sigOpCount,
} }
} }
@ -206,6 +208,7 @@ func (msg *MsgTx) Copy() *MsgTx {
PreviousOutpoint: newOutpoint, PreviousOutpoint: newOutpoint,
SignatureScript: newScript, SignatureScript: newScript,
Sequence: oldTxIn.Sequence, Sequence: oldTxIn.Sequence,
SigOpCount: oldTxIn.SigOpCount,
} }
// Finally, append this fully copied txin. // Finally, append this fully copied txin.

View File

@ -68,7 +68,7 @@ func TestTx(t *testing.T) {
// Ensure we get the same transaction input back out. // Ensure we get the same transaction input back out.
sigScript := []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62} sigScript := []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62}
txIn := NewTxIn(prevOut, sigScript, constants.MaxTxInSequenceNum) txIn := NewTxIn(prevOut, sigScript, constants.MaxTxInSequenceNum, 1)
if !reflect.DeepEqual(&txIn.PreviousOutpoint, prevOut) { if !reflect.DeepEqual(&txIn.PreviousOutpoint, prevOut) {
t.Errorf("NewTxIn: wrong prev outpoint - got %v, want %v", t.Errorf("NewTxIn: wrong prev outpoint - got %v, want %v",
spew.Sprint(&txIn.PreviousOutpoint), spew.Sprint(&txIn.PreviousOutpoint),

View File

@ -61,6 +61,7 @@ type RPCTransactionInput struct {
PreviousOutpoint *RPCOutpoint PreviousOutpoint *RPCOutpoint
SignatureScript string SignatureScript string
Sequence uint64 Sequence uint64
SigOpCount byte
VerboseData *RPCTransactionInputVerboseData VerboseData *RPCTransactionInputVerboseData
} }
@ -98,7 +99,7 @@ type RPCUTXOEntry struct {
type RPCTransactionVerboseData struct { type RPCTransactionVerboseData struct {
TransactionID string TransactionID string
Hash string Hash string
Size uint64 Mass uint64
BlockHash string BlockHash string
BlockTime uint64 BlockTime uint64
} }

View File

@ -130,6 +130,10 @@ type fakeRelayInvsContext struct {
rwLock sync.RWMutex rwLock sync.RWMutex
} }
func (f *fakeRelayInvsContext) PopulateMass(*externalapi.DomainTransaction) {
panic("implement me")
}
func (f *fakeRelayInvsContext) DeleteStagingConsensus() error { func (f *fakeRelayInvsContext) DeleteStagingConsensus() error {
panic("implement me") panic("implement me")
} }

View File

@ -10,7 +10,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes" "github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript" "github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/appmessage"
@ -114,10 +113,11 @@ func (ctx *Context) PopulateTransactionWithVerboseData(
return err return err
} }
ctx.Domain.Consensus().PopulateMass(domainTransaction)
transaction.VerboseData = &appmessage.RPCTransactionVerboseData{ transaction.VerboseData = &appmessage.RPCTransactionVerboseData{
TransactionID: consensushashing.TransactionID(domainTransaction).String(), TransactionID: consensushashing.TransactionID(domainTransaction).String(),
Hash: consensushashing.TransactionHash(domainTransaction).String(), Hash: consensushashing.TransactionHash(domainTransaction).String(),
Size: estimatedsize.TransactionEstimatedSerializedSize(domainTransaction), Mass: domainTransaction.Mass,
} }
if domainBlockHeader != nil { if domainBlockHeader != nil {
transaction.VerboseData.BlockHash = consensushashing.HeaderHash(domainBlockHeader).String() transaction.VerboseData.BlockHash = consensushashing.HeaderHash(domainBlockHeader).String()

View File

@ -89,7 +89,7 @@ type PartiallySignedInput struct {
PrevOutput *TransactionOutput `protobuf:"bytes,2,opt,name=prevOutput,proto3" json:"prevOutput,omitempty"` PrevOutput *TransactionOutput `protobuf:"bytes,2,opt,name=prevOutput,proto3" json:"prevOutput,omitempty"`
MinimumSignatures uint32 `protobuf:"varint,3,opt,name=minimumSignatures,proto3" json:"minimumSignatures,omitempty"` MinimumSignatures uint32 `protobuf:"varint,3,opt,name=minimumSignatures,proto3" json:"minimumSignatures,omitempty"`
PubKeySignaturePairs []*PubKeySignaturePair `protobuf:"bytes,4,rep,name=pubKeySignaturePairs,proto3" json:"pubKeySignaturePairs,omitempty"` PubKeySignaturePairs []*PubKeySignaturePair `protobuf:"bytes,4,rep,name=pubKeySignaturePairs,proto3" json:"pubKeySignaturePairs,omitempty"`
DerivationPath string `protobuf:"bytes,5,opt,name=DerivationPath,proto3" json:"DerivationPath,omitempty"` DerivationPath string `protobuf:"bytes,5,opt,name=derivationPath,proto3" json:"derivationPath,omitempty"`
} }
func (x *PartiallySignedInput) Reset() { func (x *PartiallySignedInput) Reset() {
@ -364,6 +364,7 @@ type TransactionInput struct {
PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"` PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"`
SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"` SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"`
Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"`
SigOpCount uint32 `protobuf:"varint,4,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
} }
func (x *TransactionInput) Reset() { func (x *TransactionInput) Reset() {
@ -419,6 +420,13 @@ func (x *TransactionInput) GetSequence() uint64 {
return 0 return 0
} }
func (x *TransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type Outpoint struct { type Outpoint struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -664,9 +672,9 @@ var file_wallet_proto_rawDesc = []byte{
0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50,
0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x61, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x61,
0x69, 0x72, 0x52, 0x14, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x69, 0x72, 0x52, 0x14, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
0x75, 0x72, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x65, 0x72, 0x69, 0x75, 0x72, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x65, 0x72, 0x69,
0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0e, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68,
0x22, 0x5b, 0x0a, 0x13, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x22, 0x5b, 0x0a, 0x13, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
0x75, 0x72, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x75, 0x72, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e,
0x64, 0x65, 0x64, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x64, 0x65, 0x64, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
@ -695,7 +703,7 @@ var file_wallet_proto_rawDesc = []byte{
0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01,
0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f,
0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61,
0x64, 0x22, 0xa2, 0x01, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x64, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x48, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x48, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
@ -705,7 +713,9 @@ var file_wallet_proto_rawDesc = []byte{
0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65,
0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65,
0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x69, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x4f,
0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x69, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69,
0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x6f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54,

View File

@ -13,7 +13,7 @@ message PartiallySignedInput{
TransactionOutput prevOutput = 2; TransactionOutput prevOutput = 2;
uint32 minimumSignatures = 3; uint32 minimumSignatures = 3;
repeated PubKeySignaturePair pubKeySignaturePairs = 4; repeated PubKeySignaturePair pubKeySignaturePairs = 4;
string DerivationPath = 5; string derivationPath = 5;
} }
message PubKeySignaturePair{ message PubKeySignaturePair{
@ -39,6 +39,7 @@ message TransactionInput{
Outpoint previousOutpoint = 1; Outpoint previousOutpoint = 1;
bytes signatureScript = 2; bytes signatureScript = 2;
uint64 sequence = 3; uint64 sequence = 3;
uint32 sigOpCount = 4;
} }
message Outpoint{ message Outpoint{

View File

@ -1,12 +1,13 @@
package serialization package serialization
import ( import (
"math"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization/protoserialization" "github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization/protoserialization"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks" "github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/pkg/errors" "github.com/pkg/errors"
"math"
) )
// PartiallySignedTransaction is a type that is intended // PartiallySignedTransaction is a type that is intended
@ -190,6 +191,10 @@ func transactionToProto(tx *externalapi.DomainTransaction) *protoserialization.T
} }
func transactionInputFromProto(protoInput *protoserialization.TransactionInput) (*externalapi.DomainTransactionInput, error) { func transactionInputFromProto(protoInput *protoserialization.TransactionInput) (*externalapi.DomainTransactionInput, error) {
if protoInput.SigOpCount > math.MaxUint8 {
return nil, errors.New("TransactionInput SigOpCount > math.MaxUint8")
}
outpoint, err := outpointFromProto(protoInput.PreviousOutpoint) outpoint, err := outpointFromProto(protoInput.PreviousOutpoint)
if err != nil { if err != nil {
return nil, err return nil, err
@ -199,6 +204,7 @@ func transactionInputFromProto(protoInput *protoserialization.TransactionInput)
PreviousOutpoint: *outpoint, PreviousOutpoint: *outpoint,
SignatureScript: protoInput.SignatureScript, SignatureScript: protoInput.SignatureScript,
Sequence: protoInput.Sequence, Sequence: protoInput.Sequence,
SigOpCount: byte(protoInput.SigOpCount),
}, nil }, nil
} }
@ -207,6 +213,7 @@ func transactionInputToProto(input *externalapi.DomainTransactionInput) *protose
PreviousOutpoint: outpointToProto(&input.PreviousOutpoint), PreviousOutpoint: outpointToProto(&input.PreviousOutpoint),
SignatureScript: input.SignatureScript, SignatureScript: input.SignatureScript,
Sequence: input.Sequence, Sequence: input.Sequence,
SigOpCount: uint32(input.SigOpCount),
} }
} }

View File

@ -58,6 +58,7 @@ func sign(params *dagconfig.Params, mnemonic string, partiallySignedTransaction
false, // This is a fake value, because it's irrelevant for the signature false, // This is a fake value, because it's irrelevant for the signature
0, // This is a fake value, because it's irrelevant for the signature 0, // This is a fake value, because it's irrelevant for the signature
) )
partiallySignedTransaction.Tx.Inputs[i].SigOpCount = byte(len(partiallySignedInput.PubKeySignaturePairs))
} }
signed := false signed := false

View File

@ -96,8 +96,7 @@ func (s *consensus) ValidateTransactionAndPopulateWithConsensusData(transaction
if err != nil { if err != nil {
return err return err
} }
return s.transactionValidator.ValidateTransactionInContextAndPopulateFee(
return s.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee(
stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime) stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime)
} }
@ -556,3 +555,7 @@ func (s *consensus) EstimateNetworkHashesPerSecond(startHash *externalapi.Domain
return s.difficultyManager.EstimateNetworkHashesPerSecond(startHash, windowSize) return s.difficultyManager.EstimateNetworkHashesPerSecond(startHash, windowSize)
} }
func (s *consensus) PopulateMass(transaction *externalapi.DomainTransaction) {
s.transactionValidator.PopulateMass(transaction)
}

View File

@ -333,6 +333,7 @@ type DbTransactionInput struct {
PreviousOutpoint *DbOutpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"` PreviousOutpoint *DbOutpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"`
SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"` SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"`
Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"`
SigOpCount uint32 `protobuf:"varint,4,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
} }
func (x *DbTransactionInput) Reset() { func (x *DbTransactionInput) Reset() {
@ -388,6 +389,13 @@ func (x *DbTransactionInput) GetSequence() uint64 {
return 0 return 0
} }
func (x *DbTransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type DbOutpoint struct { type DbOutpoint struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -1664,7 +1672,7 @@ var file_dbobjects_proto_rawDesc = []byte{
0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44, 0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44,
0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67,
0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xc1, 0x01, 0x0a,
0x12, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x12, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x70, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f,
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
@ -1675,6 +1683,8 @@ var file_dbobjects_proto_rawDesc = []byte{
0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63,
0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74,
0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44, 0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44,
0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,

View File

@ -37,6 +37,7 @@ message DbTransactionInput {
DbOutpoint previousOutpoint = 1; DbOutpoint previousOutpoint = 1;
bytes signatureScript = 2; bytes signatureScript = 2;
uint64 sequence = 3; uint64 sequence = 3;
uint32 sigOpCount = 4;
} }
message DbOutpoint { message DbOutpoint {

View File

@ -1,9 +1,10 @@
package serialization package serialization
import ( import (
"math"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/pkg/errors" "github.com/pkg/errors"
"math"
) )
// DomainTransactionToDbTransaction converts DomainTransaction to DbTransaction // DomainTransactionToDbTransaction converts DomainTransaction to DbTransaction
@ -14,6 +15,7 @@ func DomainTransactionToDbTransaction(domainTransaction *externalapi.DomainTrans
PreviousOutpoint: DomainOutpointToDbOutpoint(&domainTransactionInput.PreviousOutpoint), PreviousOutpoint: DomainOutpointToDbOutpoint(&domainTransactionInput.PreviousOutpoint),
SignatureScript: domainTransactionInput.SignatureScript, SignatureScript: domainTransactionInput.SignatureScript,
Sequence: domainTransactionInput.Sequence, Sequence: domainTransactionInput.Sequence,
SigOpCount: uint32(domainTransactionInput.SigOpCount),
} }
} }
@ -54,6 +56,7 @@ func DbTransactionToDomainTransaction(dbTransaction *DbTransaction) (*externalap
PreviousOutpoint: *domainPreviousOutpoint, PreviousOutpoint: *domainPreviousOutpoint,
SignatureScript: dbTransactionInput.SignatureScript, SignatureScript: dbTransactionInput.SignatureScript,
Sequence: dbTransactionInput.Sequence, Sequence: dbTransactionInput.Sequence,
SigOpCount: byte(dbTransactionInput.SigOpCount),
} }
} }

View File

@ -1,13 +1,14 @@
package consensus package consensus
import ( import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/prefixmanager/prefix"
"github.com/pkg/errors"
"io/ioutil" "io/ioutil"
"os" "os"
"sync" "sync"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/prefixmanager/prefix"
"github.com/pkg/errors"
consensusdatabase "github.com/kaspanet/kaspad/domain/consensus/database" consensusdatabase "github.com/kaspanet/kaspad/domain/consensus/database"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/acceptancedatastore" "github.com/kaspanet/kaspad/domain/consensus/datastructures/acceptancedatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockheaderstore" "github.com/kaspanet/kaspad/domain/consensus/datastructures/blockheaderstore"
@ -231,7 +232,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
config.SkipProofOfWork, config.SkipProofOfWork,
genesisHash, genesisHash,
config.EnableNonNativeSubnetworks, config.EnableNonNativeSubnetworks,
config.MaxBlockSize, config.MaxBlockMass,
config.MergeSetSizeLimit, config.MergeSetSizeLimit,
config.MaxBlockParents, config.MaxBlockParents,
config.TimestampDeviationTolerance, config.TimestampDeviationTolerance,
@ -259,7 +260,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
consensusStateManager, err := consensusstatemanager.New( consensusStateManager, err := consensusstatemanager.New(
dbManager, dbManager,
config.PruningDepth(), config.PruningDepth(),
config.MaxMassAcceptedByBlock,
config.MaxBlockParents, config.MaxBlockParents,
config.MergeSetSizeLimit, config.MergeSetSizeLimit,
genesisHash, genesisHash,

View File

@ -9,7 +9,6 @@ import (
) )
func initTestTransactionAcceptanceDataForClone() []*externalapi.TransactionAcceptanceData { func initTestTransactionAcceptanceDataForClone() []*externalapi.TransactionAcceptanceData {
tests := []*externalapi.TransactionAcceptanceData{ tests := []*externalapi.TransactionAcceptanceData{
{ {
&externalapi.DomainTransaction{ &externalapi.DomainTransaction{
@ -18,6 +17,7 @@ func initTestTransactionAcceptanceDataForClone() []*externalapi.TransactionAccep
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -62,6 +62,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -91,6 +92,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -119,6 +121,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -147,6 +150,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -176,6 +180,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -206,6 +211,7 @@ func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStru
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -311,6 +317,7 @@ func initTestBlockAcceptanceDataForClone() []*externalapi.BlockAcceptanceData {
0xFFFF}, 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -358,6 +365,7 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -390,6 +398,7 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -422,6 +431,7 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -454,6 +464,7 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -487,6 +498,7 @@ func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -590,6 +602,7 @@ func initTestAcceptanceDataForClone() []externalapi.AcceptanceData {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -639,6 +652,7 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -671,6 +685,7 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -703,6 +718,7 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -735,6 +751,7 @@ func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},

View File

@ -35,4 +35,5 @@ type Consensus interface {
GetHeadersSelectedTip() (*DomainHash, error) GetHeadersSelectedTip() (*DomainHash, error)
Anticone(blockHash *DomainHash) ([]*DomainHash, error) Anticone(blockHash *DomainHash) ([]*DomainHash, error)
EstimateNetworkHashesPerSecond(startHash *DomainHash, windowSize int) (uint64, error) EstimateNetworkHashesPerSecond(startHash *DomainHash, windowSize int) (uint64, error)
PopulateMass(transaction *DomainTransaction)
} }

View File

@ -131,13 +131,14 @@ type DomainTransactionInput struct {
PreviousOutpoint DomainOutpoint PreviousOutpoint DomainOutpoint
SignatureScript []byte SignatureScript []byte
Sequence uint64 Sequence uint64
SigOpCount byte
UTXOEntry UTXOEntry UTXOEntry UTXOEntry
} }
// If this doesn't compile, it means the type definition has been changed, so it's // If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly. // an indication to update Equal and Clone accordingly.
var _ = &DomainTransactionInput{DomainOutpoint{}, []byte{}, 0, nil} var _ = &DomainTransactionInput{DomainOutpoint{}, []byte{}, 0, 0, nil}
// Equal returns whether input equals to other // Equal returns whether input equals to other
func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool { func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool {
@ -157,6 +158,10 @@ func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool {
return false return false
} }
if input.SigOpCount != other.SigOpCount {
return false
}
if input.UTXOEntry != nil && other.UTXOEntry != nil && !input.UTXOEntry.Equal(other.UTXOEntry) { if input.UTXOEntry != nil && other.UTXOEntry != nil && !input.UTXOEntry.Equal(other.UTXOEntry) {
panic(errors.New("identical inputs should always have the same UTXO entry")) panic(errors.New("identical inputs should always have the same UTXO entry"))
} }
@ -173,6 +178,7 @@ func (input *DomainTransactionInput) Clone() *DomainTransactionInput {
PreviousOutpoint: *input.PreviousOutpoint.Clone(), PreviousOutpoint: *input.PreviousOutpoint.Clone(),
SignatureScript: signatureScriptClone, SignatureScript: signatureScriptClone,
Sequence: input.Sequence, Sequence: input.Sequence,
SigOpCount: input.SigOpCount,
UTXOEntry: input.UTXOEntry, UTXOEntry: input.UTXOEntry,
} }
} }

View File

@ -71,6 +71,7 @@ func initTestBaseTransaction() *externalapi.DomainTransaction {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -99,6 +100,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}, //Changed &externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}, //Changed
@ -123,6 +125,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -147,6 +150,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -171,6 +175,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -196,6 +201,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -221,6 +227,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -245,6 +252,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -268,6 +276,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -291,6 +300,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -314,11 +324,13 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)},
{externalapi.DomainOutpoint{ {externalapi.DomainOutpoint{
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -342,6 +354,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -366,6 +379,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -386,6 +400,31 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFF0), // Changed sequence uint64(0xFFFFFFF0), // Changed sequence
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
[]byte{0x01},
0,
1,
externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}),
},
expectedResult: false,
}, {
tx: &externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
3, // Changed SigOpCount
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
@ -410,6 +449,7 @@ func initTestTransactionToCompare() []*transactionToCompare {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF), []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}},
@ -442,6 +482,7 @@ func initTestDomainTransactionForClone() []*externalapi.DomainTransaction {
*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)}, utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2)},
}, },
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
@ -556,6 +597,7 @@ func initTestBaseDomainTransactionInput() *externalapi.DomainTransactionInput {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
} }
return basetxInput return basetxInput
@ -567,6 +609,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, },
expectedResult: true, expectedResult: true,
@ -575,6 +618,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, false, 2), // Changed utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, false, 2), // Changed
}, },
expectsPanic: true, expectsPanic: true,
@ -583,6 +627,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
nil, // Changed nil, // Changed
}, },
expectedResult: true, expectedResult: true,
@ -591,6 +636,16 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFF0), // Changed uint64(0xFFFFFFF0), // Changed
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
},
expectedResult: false,
}, {
tx: &externalapi.DomainTransactionInput{
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFF0),
5, // Changed
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, },
expectedResult: false, expectedResult: false,
@ -599,6 +654,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3, 4}, // Changed []byte{1, 2, 3, 4}, // Changed
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, },
expectedResult: false, expectedResult: false,
@ -607,6 +663,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, },
expectedResult: false, expectedResult: false,
@ -615,6 +672,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(2 /* Changed */, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), // Changed utxo.NewUTXOEntry(2 /* Changed */, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), // Changed
}, },
expectedResult: false, expectedResult: false,
@ -623,6 +681,7 @@ func initTestDomainTxInputToCompare() []*transactionInputToCompare {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01, 0x02}), 0xFFFF}, // Changed
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(3 /* Changed */, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 3), // Changed utxo.NewUTXOEntry(3 /* Changed */, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 3), // Changed
}, },
expectedResult: false, expectedResult: false,
@ -640,18 +699,21 @@ func initTestDomainTransactionInputForClone() []*externalapi.DomainTransactionIn
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, { }, {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFFF), uint64(0xFFFFFFFF),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}, { }, {
externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF}, externalapi.DomainOutpoint{*externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{0x01}), 0xFFFF},
[]byte{1, 2, 3}, []byte{1, 2, 3},
uint64(0xFFFFFFF0), uint64(0xFFFFFFF0),
1,
utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2), utxo.NewUTXOEntry(1, &externalapi.ScriptPublicKey{Script: []byte{0, 1, 2, 3}, Version: 0}, true, 2),
}} }}
return txInput return txInput

View File

@ -10,6 +10,7 @@ type TransactionValidator interface {
ValidateTransactionInIsolation(transaction *externalapi.DomainTransaction) error ValidateTransactionInIsolation(transaction *externalapi.DomainTransaction) error
ValidateTransactionInContextIgnoringUTXO(stagingArea *StagingArea, tx *externalapi.DomainTransaction, ValidateTransactionInContextIgnoringUTXO(stagingArea *StagingArea, tx *externalapi.DomainTransaction,
povBlockHash *externalapi.DomainHash) error povBlockHash *externalapi.DomainHash) error
ValidateTransactionInContextAndPopulateMassAndFee(stagingArea *StagingArea, ValidateTransactionInContextAndPopulateFee(stagingArea *StagingArea,
tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error
PopulateMass(transaction *externalapi.DomainTransaction)
} }

View File

@ -155,7 +155,7 @@ func (bb *blockBuilder) validateTransaction(
return err return err
} }
return bb.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee( return bb.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime) stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime)
} }

View File

@ -60,7 +60,6 @@ func (bp *blockProcessor) setBlockStatusAfterBlockValidation(
} }
func (bp *blockProcessor) updateVirtualAcceptanceDataAfterImportingPruningPoint(stagingArea *model.StagingArea) error { func (bp *blockProcessor) updateVirtualAcceptanceDataAfterImportingPruningPoint(stagingArea *model.StagingArea) error {
_, virtualAcceptanceData, virtualMultiset, err := _, virtualAcceptanceData, virtualMultiset, err :=
bp.consensusStateManager.CalculatePastUTXOAndAcceptanceData(stagingArea, model.VirtualBlockHash) bp.consensusStateManager.CalculatePastUTXOAndAcceptanceData(stagingArea, model.VirtualBlockHash)
if err != nil { if err != nil {

View File

@ -5,7 +5,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle" "github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks" "github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper" "github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
@ -34,11 +33,6 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return err return err
} }
err = v.checkBlockSize(block)
if err != nil {
return err
}
err = v.checkBlockContainsAtLeastOneTransaction(block) err = v.checkBlockContainsAtLeastOneTransaction(block)
if err != nil { if err != nil {
return err return err
@ -69,6 +63,11 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return err return err
} }
err = v.checkBlockMass(block)
if err != nil {
return err
}
err = v.checkBlockDuplicateTransactions(block) err = v.checkBlockDuplicateTransactions(block)
if err != nil { if err != nil {
return err return err
@ -215,16 +214,18 @@ func (v *blockValidator) validateGasLimit(block *externalapi.DomainBlock) error
return nil return nil
} }
func (v *blockValidator) checkBlockSize(block *externalapi.DomainBlock) error { func (v *blockValidator) checkBlockMass(block *externalapi.DomainBlock) error {
size := uint64(0) mass := uint64(0)
size += v.headerEstimatedSerializedSize(block.Header) mass += v.headerEstimatedSerializedSize(block.Header)
for _, tx := range block.Transactions { for _, transaction := range block.Transactions {
sizeBefore := size v.transactionValidator.PopulateMass(transaction)
size += estimatedsize.TransactionEstimatedSerializedSize(tx)
if size > v.maxBlockSize || size < sizeBefore { massBefore := mass
return errors.Wrapf(ruleerrors.ErrBlockSizeTooHigh, "block excceeded the size limit of %d", mass += transaction.Mass
v.maxBlockSize) if mass > v.maxBlockMass || mass < massBefore {
return errors.Wrapf(ruleerrors.ErrBlockMassTooHigh, "block exceeded the mass limit of %d",
v.maxBlockMass)
} }
} }

View File

@ -1027,17 +1027,16 @@ func TestCheckBlockHashMerkleRoot(t *testing.T) {
}) })
} }
func TestBlockSize(t *testing.T) { func TestBlockMass(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory() factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockSize") tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockMass")
if err != nil { if err != nil {
t.Fatalf("Error setting up tc: %+v", err) t.Fatalf("Error setting up tc: %+v", err)
} }
defer teardown(false) defer teardown(false)
block, _, err := initBlockWithInvalidBlockSize(consensusConfig, tc) block, _, err := initBlockWithInvalidBlockMass(consensusConfig, tc)
if err != nil { if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err) t.Fatalf("Error BuildBlockWithParents : %+v", err)
} }
@ -1046,14 +1045,14 @@ func TestBlockSize(t *testing.T) {
tc.BlockStore().Stage(stagingArea, blockHash, block) tc.BlockStore().Stage(stagingArea, blockHash, block)
err = tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash) err = tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
if err == nil || !errors.Is(err, ruleerrors.ErrBlockSizeTooHigh) { if err == nil || !errors.Is(err, ruleerrors.ErrBlockMassTooHigh) {
t.Fatalf("ValidateBodyInIsolationTest: TestBlockSize:"+ t.Fatalf("ValidateBodyInIsolationTest: TestBlockMass:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrBlockSizeTooHigh, err) " Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrBlockMassTooHigh, err)
} }
}) })
} }
func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) { func initBlockWithInvalidBlockMass(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
emptyCoinbase := externalapi.DomainCoinbaseData{ emptyCoinbase := externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{ ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil, Script: nil,
@ -1062,11 +1061,12 @@ func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi
} }
prevOutTxID := &externalapi.DomainTransactionID{} prevOutTxID := &externalapi.DomainTransactionID{}
prevOutPoint := externalapi.DomainOutpoint{TransactionID: *prevOutTxID, Index: 1} prevOutPoint := externalapi.DomainOutpoint{TransactionID: *prevOutTxID, Index: 1}
bigSignatureScript := bytes.Repeat([]byte("01"), 25000) bigSignatureScript := bytes.Repeat([]byte("01"), 500000)
txInput := externalapi.DomainTransactionInput{ txInput := externalapi.DomainTransactionInput{
PreviousOutpoint: prevOutPoint, PreviousOutpoint: prevOutPoint,
SignatureScript: bigSignatureScript, SignatureScript: bigSignatureScript,
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 10,
UTXOEntry: utxo.NewUTXOEntry( UTXOEntry: utxo.NewUTXOEntry(
100_000_000, 100_000_000,
&externalapi.ScriptPublicKey{}, &externalapi.ScriptPublicKey{},
@ -1079,7 +1079,7 @@ func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF), Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF), &externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}}, &externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}},
Payload: []byte{0x01}, Payload: []byte{},
} }
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx}) return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})

View File

@ -1,12 +1,12 @@
package blockvalidator package blockvalidator
import ( import (
"github.com/kaspanet/kaspad/util/difficulty"
"math/big" "math/big"
"time" "time"
"github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/util/difficulty"
) )
// blockValidator exposes a set of validation classes, after which // blockValidator exposes a set of validation classes, after which
@ -17,7 +17,7 @@ type blockValidator struct {
genesisHash *externalapi.DomainHash genesisHash *externalapi.DomainHash
enableNonNativeSubnetworks bool enableNonNativeSubnetworks bool
powMaxBits uint32 powMaxBits uint32
maxBlockSize uint64 maxBlockMass uint64
mergeSetSizeLimit uint64 mergeSetSizeLimit uint64
maxBlockParents model.KType maxBlockParents model.KType
timestampDeviationTolerance int timestampDeviationTolerance int
@ -48,7 +48,7 @@ func New(powMax *big.Int,
skipPoW bool, skipPoW bool,
genesisHash *externalapi.DomainHash, genesisHash *externalapi.DomainHash,
enableNonNativeSubnetworks bool, enableNonNativeSubnetworks bool,
maxBlockSize uint64, maxBlockMass uint64,
mergeSetSizeLimit uint64, mergeSetSizeLimit uint64,
maxBlockParents model.KType, maxBlockParents model.KType,
timestampDeviationTolerance int, timestampDeviationTolerance int,
@ -82,7 +82,7 @@ func New(powMax *big.Int,
genesisHash: genesisHash, genesisHash: genesisHash,
enableNonNativeSubnetworks: enableNonNativeSubnetworks, enableNonNativeSubnetworks: enableNonNativeSubnetworks,
powMaxBits: difficulty.BigToCompact(powMax), powMaxBits: difficulty.BigToCompact(powMax),
maxBlockSize: maxBlockSize, maxBlockMass: maxBlockMass,
mergeSetSizeLimit: mergeSetSizeLimit, mergeSetSizeLimit: mergeSetSizeLimit,
maxBlockParents: maxBlockParents, maxBlockParents: maxBlockParents,

View File

@ -237,7 +237,7 @@ func (csm *consensusStateManager) maybeAcceptTransaction(stagingArea *model.Stag
log.Tracef("Transaction %s is the coinbase of block %s", transactionID, blockHash) log.Tracef("Transaction %s is the coinbase of block %s", transactionID, blockHash)
} else { } else {
log.Tracef("Validating transaction %s in block %s", transactionID, blockHash) log.Tracef("Validating transaction %s in block %s", transactionID, blockHash)
err = csm.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee( err = csm.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, blockHash, selectedParentPastMedianTime) stagingArea, transaction, blockHash, selectedParentPastMedianTime)
if err != nil { if err != nil {
if !errors.As(err, &(ruleerrors.RuleError{})) { if !errors.As(err, &(ruleerrors.RuleError{})) {
@ -249,14 +249,6 @@ func (csm *consensusStateManager) maybeAcceptTransaction(stagingArea *model.Stag
return false, accumulatedMassBefore, nil return false, accumulatedMassBefore, nil
} }
log.Tracef("Validation passed for transaction %s in block %s", transactionID, blockHash) log.Tracef("Validation passed for transaction %s in block %s", transactionID, blockHash)
log.Tracef("Check mass for transaction %s in block %s", transactionID, blockHash)
isAccepted, accumulatedMassAfter = csm.checkTransactionMass(transaction, accumulatedMassBefore)
if !isAccepted {
log.Tracef("Transaction %s in block %s has too much mass, "+
"and cannot be accepted", transactionID, blockHash)
return false, accumulatedMassBefore, nil
}
} }
log.Tracef("Adding transaction %s in block %s to the accumulated diff", transactionID, blockHash) log.Tracef("Adding transaction %s in block %s to the accumulated diff", transactionID, blockHash)
@ -268,27 +260,6 @@ func (csm *consensusStateManager) maybeAcceptTransaction(stagingArea *model.Stag
return true, accumulatedMassAfter, nil return true, accumulatedMassAfter, nil
} }
func (csm *consensusStateManager) checkTransactionMass(transaction *externalapi.DomainTransaction, accumulatedMassBefore uint64) (
isAccepted bool, accumulatedMassAfter uint64) {
transactionID := consensushashing.TransactionID(transaction)
log.Tracef("checkTransactionMass start for transaction %s", transactionID)
defer log.Tracef("checkTransactionMass end for transaction %s", transactionID)
log.Tracef("Adding transaction %s with mass %d to the "+
"so-far accumulated mass of %d", transactionID, transaction.Mass, accumulatedMassBefore)
accumulatedMassAfter = accumulatedMassBefore + transaction.Mass
log.Tracef("Accumulated mass including transaction %s: %d", transactionID, accumulatedMassAfter)
// We could potentially overflow the accumulator so check for
// overflow as well.
if accumulatedMassAfter < transaction.Mass || accumulatedMassAfter > csm.maxMassAcceptedByBlock {
return false, 0
}
return true, accumulatedMassAfter
}
// RestorePastUTXOSetIterator restores the given block's UTXOSet iterator, and returns it as a externalapi.ReadOnlyUTXOSetIterator // RestorePastUTXOSetIterator restores the given block's UTXOSet iterator, and returns it as a externalapi.ReadOnlyUTXOSetIterator
func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) ( func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (
externalapi.ReadOnlyUTXOSetIterator, error) { externalapi.ReadOnlyUTXOSetIterator, error) {

View File

@ -7,12 +7,11 @@ import (
// consensusStateManager manages the node's consensus state // consensusStateManager manages the node's consensus state
type consensusStateManager struct { type consensusStateManager struct {
pruningDepth uint64 pruningDepth uint64
maxMassAcceptedByBlock uint64 maxBlockParents model.KType
maxBlockParents model.KType mergeSetSizeLimit uint64
mergeSetSizeLimit uint64 genesisHash *externalapi.DomainHash
genesisHash *externalapi.DomainHash databaseContext model.DBManager
databaseContext model.DBManager
ghostdagManager model.GHOSTDAGManager ghostdagManager model.GHOSTDAGManager
dagTopologyManager model.DAGTopologyManager dagTopologyManager model.DAGTopologyManager
@ -46,7 +45,6 @@ type consensusStateManager struct {
func New( func New(
databaseContext model.DBManager, databaseContext model.DBManager,
pruningDepth uint64, pruningDepth uint64,
maxMassAcceptedByBlock uint64,
maxBlockParents model.KType, maxBlockParents model.KType,
mergeSetSizeLimit uint64, mergeSetSizeLimit uint64,
genesisHash *externalapi.DomainHash, genesisHash *externalapi.DomainHash,
@ -77,12 +75,11 @@ func New(
daaBlocksStore model.DAABlocksStore) (model.ConsensusStateManager, error) { daaBlocksStore model.DAABlocksStore) (model.ConsensusStateManager, error) {
csm := &consensusStateManager{ csm := &consensusStateManager{
pruningDepth: pruningDepth, pruningDepth: pruningDepth,
maxMassAcceptedByBlock: maxMassAcceptedByBlock, maxBlockParents: maxBlockParents,
maxBlockParents: maxBlockParents, mergeSetSizeLimit: mergeSetSizeLimit,
mergeSetSizeLimit: mergeSetSizeLimit, genesisHash: genesisHash,
genesisHash: genesisHash, databaseContext: databaseContext,
databaseContext: databaseContext,
ghostdagManager: ghostdagManager, ghostdagManager: ghostdagManager,
dagTopologyManager: dagTopologyManager, dagTopologyManager: dagTopologyManager,

View File

@ -118,7 +118,7 @@ func (csm *consensusStateManager) importPruningPoint(
continue continue
} }
log.Tracef("Validating transaction %s and populating it with mass and fee", transactionID) log.Tracef("Validating transaction %s and populating it with mass and fee", transactionID)
err = csm.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee( err = csm.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, newPruningPointHash, newPruningPointSelectedParentMedianTime) stagingArea, transaction, newPruningPointHash, newPruningPointSelectedParentMedianTime)
if err != nil { if err != nil {
return err return err

View File

@ -83,8 +83,8 @@ func (csm *consensusStateManager) validateBlockTransactionsAgainstPastUTXO(stagi
return err return err
} }
log.Tracef("Validating transaction %s and populating it with mass and fee", transactionID) log.Tracef("Validating transaction %s and populating it with fee", transactionID)
err = csm.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee( err = csm.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, blockHash, selectedParentMedianTime) stagingArea, transaction, blockHash, selectedParentMedianTime)
if err != nil { if err != nil {
return err return err

View File

@ -2,47 +2,99 @@ package transactionvalidator
import ( import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper" "github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
) )
func (v *transactionValidator) transactionMassStandalonePart(tx *externalapi.DomainTransaction) uint64 { func (v *transactionValidator) PopulateMass(transaction *externalapi.DomainTransaction) {
size := estimatedsize.TransactionEstimatedSerializedSize(tx) if transaction.Mass != 0 {
return
}
transaction.Mass = v.transactionMass(transaction)
}
func (v *transactionValidator) transactionMass(transaction *externalapi.DomainTransaction) uint64 {
if transactionhelper.IsCoinBase(transaction) {
return 0
}
// calculate mass for size
size := transactionEstimatedSerializedSize(transaction)
massForSize := size * v.massPerTxByte
// calculate mass for scriptPubKey
totalScriptPubKeySize := uint64(0) totalScriptPubKeySize := uint64(0)
for _, output := range tx.Outputs { for _, output := range transaction.Outputs {
totalScriptPubKeySize += 2 //output.ScriptPublicKey.Version (uint16) totalScriptPubKeySize += 2 //output.ScriptPublicKey.Version (uint16)
totalScriptPubKeySize += uint64(len(output.ScriptPublicKey.Script)) totalScriptPubKeySize += uint64(len(output.ScriptPublicKey.Script))
} }
massForScriptPubKey := totalScriptPubKeySize * v.massPerScriptPubKeyByte
return size*v.massPerTxByte + totalScriptPubKeySize*v.massPerScriptPubKeyByte // calculate mass for SigOps
totalSigOpCount := uint64(0)
for _, input := range transaction.Inputs {
totalSigOpCount += uint64(input.SigOpCount)
}
massForSigOps := totalSigOpCount * v.massPerSigOp
// Sum all components of mass
return massForSize + massForScriptPubKey + massForSigOps
} }
func (v *transactionValidator) transactionMass(tx *externalapi.DomainTransaction) (uint64, error) { // transactionEstimatedSerializedSize is the estimated size of a transaction in some
// serialization. This has to be deterministic, but not necessarily accurate, since
// it's only used as the size component in the transaction and block mass limit
// calculation.
func transactionEstimatedSerializedSize(tx *externalapi.DomainTransaction) uint64 {
if transactionhelper.IsCoinBase(tx) { if transactionhelper.IsCoinBase(tx) {
return 0, nil return 0
} }
size := uint64(0)
standaloneMass := v.transactionMassStandalonePart(tx) size += 2 // Txn Version
sigOpsCount := uint64(0) size += 8 // number of inputs (uint64)
var missingOutpoints []*externalapi.DomainOutpoint
for _, input := range tx.Inputs { for _, input := range tx.Inputs {
utxoEntry := input.UTXOEntry size += transactionInputEstimatedSerializedSize(input)
if utxoEntry == nil {
missingOutpoints = append(missingOutpoints, &input.PreviousOutpoint)
continue
}
// Count the precise number of signature operations in the
// referenced public key script.
sigScript := input.SignatureScript
isP2SH := txscript.IsPayToScriptHash(utxoEntry.ScriptPublicKey())
sigOpsCount += uint64(txscript.GetPreciseSigOpCount(sigScript, utxoEntry.ScriptPublicKey(), isP2SH))
}
if len(missingOutpoints) > 0 {
return 0, ruleerrors.NewErrMissingTxOut(missingOutpoints)
} }
return standaloneMass + sigOpsCount*v.massPerSigOp, nil size += 8 // number of outputs (uint64)
for _, output := range tx.Outputs {
size += TransactionOutputEstimatedSerializedSize(output)
}
size += 8 // lock time (uint64)
size += externalapi.DomainSubnetworkIDSize
size += 8 // gas (uint64)
size += externalapi.DomainHashSize // payload hash
size += 8 // length of the payload (uint64)
size += uint64(len(tx.Payload))
return size
}
func transactionInputEstimatedSerializedSize(input *externalapi.DomainTransactionInput) uint64 {
size := uint64(0)
size += outpointEstimatedSerializedSize()
size += 8 // length of signature script (uint64)
size += uint64(len(input.SignatureScript))
size += 8 // sequence (uint64)
return size
}
func outpointEstimatedSerializedSize() uint64 {
size := uint64(0)
size += externalapi.DomainHashSize // ID
size += 4 // index (uint32)
return size
}
// TransactionOutputEstimatedSerializedSize is the same as transactionEstimatedSerializedSize but for outputs only
func TransactionOutputEstimatedSerializedSize(output *externalapi.DomainTransactionOutput) uint64 {
size := uint64(0)
size += 8 // value (uint64)
size += 2 // output.ScriptPublicKey.Version (uint 16)
size += 8 // length of script public key (uint64)
size += uint64(len(output.ScriptPublicKey.Script))
return size
} }

View File

@ -65,11 +65,11 @@ func (v *transactionValidator) ValidateTransactionInContextIgnoringUTXO(stagingA
return nil return nil
} }
// ValidateTransactionInContextAndPopulateMassAndFee validates the transaction against its referenced UTXO, and // ValidateTransactionInContextAndPopulateFee validates the transaction against its referenced UTXO, and
// populates its mass and fee fields. // populates its fee field.
// //
// Note: if the function fails, there's no guarantee that the transaction mass and fee fields will remain unaffected. // Note: if the function fails, there's no guarantee that the transaction fee field will remain unaffected.
func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee(stagingArea *model.StagingArea, func (v *transactionValidator) ValidateTransactionInContextAndPopulateFee(stagingArea *model.StagingArea,
tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error { tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error {
err := v.checkTransactionCoinbaseMaturity(stagingArea, povBlockHash, tx) err := v.checkTransactionCoinbaseMaturity(stagingArea, povBlockHash, tx)
@ -94,12 +94,12 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee
return err return err
} }
err = v.validateTransactionScripts(tx) err = v.validateTransactionSigOpCounts(tx)
if err != nil { if err != nil {
return err return err
} }
tx.Mass, err = v.transactionMass(tx) err = v.validateTransactionScripts(tx)
if err != nil { if err != nil {
return err return err
} }
@ -399,3 +399,21 @@ func (v *transactionValidator) sequenceLockActive(sequenceLock *sequenceLock, bl
return true return true
} }
func (v *transactionValidator) validateTransactionSigOpCounts(tx *externalapi.DomainTransaction) error {
for i, input := range tx.Inputs {
utxoEntry := input.UTXOEntry
// Count the precise number of signature operations in the
// referenced public key script.
sigScript := input.SignatureScript
isP2SH := txscript.IsPayToScriptHash(utxoEntry.ScriptPublicKey())
sigOpCount := txscript.GetPreciseSigOpCount(sigScript, utxoEntry.ScriptPublicKey(), isP2SH)
if sigOpCount != int(input.SigOpCount) {
return errors.Wrapf(ruleerrors.ErrWrongSigOpCount,
"input %d specifies SigOpCount %d while actual SigOpCount is %d",
i, input.SigOpCount, sigOpCount)
}
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// ValidateTransactionInIsolation validates the parts of the transaction that can be validated context-free
func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction) error { func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction) error {
err := v.checkTransactionInputCount(tx) err := v.checkTransactionInputCount(tx)
if err != nil { if err != nil {

View File

@ -20,10 +20,10 @@ type txSubnetworkData struct {
payload []byte payload []byte
} }
func TestValidateTransactionInIsolation(t *testing.T) { func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory() factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateTransactionInIsolation") tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateTransactionInIsolationAndPopulateMass")
if err != nil { if err != nil {
t.Fatalf("Error setting up consensus: %+v", err) t.Fatalf("Error setting up consensus: %+v", err)
} }
@ -111,7 +111,7 @@ func TestValidateTransactionInIsolation(t *testing.T) {
err := tc.TransactionValidator().ValidateTransactionInIsolation(tx) err := tc.TransactionValidator().ValidateTransactionInIsolation(tx)
if !errors.Is(err, test.expectedErr) { if !errors.Is(err, test.expectedErr) {
t.Errorf("TestValidateTransactionInIsolation: '%s': unexpected error %+v", test.name, err) t.Errorf("TestValidateTransactionInIsolationAndPopulateMass: '%s': unexpected error %+v", test.name, err)
} }
} }
}) })
@ -129,6 +129,7 @@ func createTxForTest(numInputs uint32, numOutputs uint32, outputValue uint64, su
}, },
SignatureScript: []byte{}, SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
}) })
} }

View File

@ -32,7 +32,7 @@ func (mdf *mocPastMedianTimeManager) PastMedianTime(*model.StagingArea, *externa
return mdf.pastMedianTimeForTest, nil return mdf.pastMedianTimeForTest, nil
} }
func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) { func TestValidateTransactionInContextAndPopulateFee(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory() factory := consensus.NewFactory()
@ -42,7 +42,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
return pastMedianManager return pastMedianManager
}) })
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
"TestValidateTransactionInContextAndPopulateMassAndFee") "TestValidateTransactionInContextAndPopulateFee")
if err != nil { if err != nil {
t.Fatalf("Failed create a NewTestConsensus: %s", err) t.Fatalf("Failed create a NewTestConsensus: %s", err)
} }
@ -76,6 +76,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint, PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{}, SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry( UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS 100_000_000, // 1 KAS
scriptPublicKey, scriptPublicKey,
@ -86,6 +87,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint, PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{}, SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry( UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS 100_000_000, // 1 KAS
scriptPublicKey, scriptPublicKey,
@ -96,6 +98,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint, PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{}, SignatureScript: []byte{},
Sequence: constants.SequenceLockTimeIsSeconds, Sequence: constants.SequenceLockTimeIsSeconds,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry( UTXOEntry: utxo.NewUTXOEntry(
100000000, // 1 KAS 100000000, // 1 KAS
scriptPublicKey, scriptPublicKey,
@ -106,12 +109,24 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint, PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{}, SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry( UTXOEntry: utxo.NewUTXOEntry(
constants.MaxSompi, constants.MaxSompi,
scriptPublicKey, scriptPublicKey,
true, true,
uint64(5)), uint64(5)),
} }
txInputWithBadSigOpCount := externalapi.DomainTransactionInput{
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 2,
UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS
scriptPublicKey,
true,
uint64(5)),
}
txOut := externalapi.DomainTransactionOutput{ txOut := externalapi.DomainTransactionOutput{
Value: 100000000, // 1 KAS Value: 100000000, // 1 KAS
@ -167,6 +182,13 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
SubnetworkID: subnetworks.SubnetworkIDRegistry, SubnetworkID: subnetworks.SubnetworkIDRegistry,
Gas: 0, Gas: 0,
LockTime: 0} LockTime: 0}
txWithBadSigOpCount := externalapi.DomainTransaction{
Version: constants.MaxTransactionVersion,
Inputs: []*externalapi.DomainTransactionInput{&txInputWithBadSigOpCount},
Outputs: []*externalapi.DomainTransactionOutput{&txOut},
SubnetworkID: subnetworks.SubnetworkIDRegistry,
Gas: 0,
LockTime: 0}
stagingArea := model.NewStagingArea() stagingArea := model.NewStagingArea()
@ -240,19 +262,27 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
isValid: false, isValid: false,
expectedError: ruleerrors.ErrScriptValidation, expectedError: ruleerrors.ErrScriptValidation,
}, },
{ // the SigOpCount in the input is wrong, and hence invalid
name: "checkTransactionSigOpCounts",
tx: &txWithBadSigOpCount,
povBlockHash: povBlockHash,
selectedParentMedianTime: 1,
isValid: false,
expectedError: ruleerrors.ErrWrongSigOpCount,
},
} }
for _, test := range tests { for _, test := range tests {
err := tc.TransactionValidator().ValidateTransactionInContextAndPopulateMassAndFee(stagingArea, test.tx, test.povBlockHash, test.selectedParentMedianTime) err := tc.TransactionValidator().ValidateTransactionInContextAndPopulateFee(stagingArea, test.tx, test.povBlockHash, test.selectedParentMedianTime)
if test.isValid { if test.isValid {
if err != nil { if err != nil {
t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateMassAndFee"+ t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateFee"+
" on test '%v': %+v", test.name, err) " on test '%v': %+v", test.name, err)
} }
} else { } else {
if err == nil || !errors.Is(err, test.expectedError) { if err == nil || !errors.Is(err, test.expectedError) {
t.Fatalf("TestValidateTransactionInContextAndPopulateMassAndFee: test %v:"+ t.Fatalf("TestValidateTransactionInContextAndPopulateFee: test %v:"+
" Unexpected error: Expected to: %v, but got : %+v", test.name, test.expectedError, err) " Unexpected error: Expected to: %v, but got : %+v", test.name, test.expectedError, err)
} }
} }
@ -335,16 +365,18 @@ func TestSigningTwoInputs(t *testing.T) {
TransactionID: *consensushashing.TransactionID(block2.Transactions[0]), TransactionID: *consensushashing.TransactionID(block2.Transactions[0]),
Index: 0, Index: 0,
}, },
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0), SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
}, },
{ {
PreviousOutpoint: externalapi.DomainOutpoint{ PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: *consensushashing.TransactionID(block3.Transactions[0]), TransactionID: *consensushashing.TransactionID(block3.Transactions[0]),
Index: 0, Index: 0,
}, },
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0), SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
}, },
}, },
Outputs: []*externalapi.DomainTransactionOutput{{ Outputs: []*externalapi.DomainTransactionOutput{{
@ -459,16 +491,18 @@ func TestSigningTwoInputsECDSA(t *testing.T) {
TransactionID: *consensushashing.TransactionID(block2.Transactions[0]), TransactionID: *consensushashing.TransactionID(block2.Transactions[0]),
Index: 0, Index: 0,
}, },
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0), SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
}, },
{ {
PreviousOutpoint: externalapi.DomainOutpoint{ PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: *consensushashing.TransactionID(block3.Transactions[0]), TransactionID: *consensushashing.TransactionID(block3.Transactions[0]),
Index: 0, Index: 0,
}, },
Sequence: constants.MaxTxInSequenceNum, Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0), SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
}, },
}, },
Outputs: []*externalapi.DomainTransactionOutput{{ Outputs: []*externalapi.DomainTransactionOutput{{

View File

@ -10,10 +10,10 @@ import (
func TestPruningDepth(t *testing.T) { func TestPruningDepth(t *testing.T) {
expectedResult := map[string]uint64{ expectedResult := map[string]uint64{
dagconfig.MainnetParams.Name: 244838, dagconfig.MainnetParams.Name: 185798,
dagconfig.TestnetParams.Name: 244838, dagconfig.TestnetParams.Name: 185798,
dagconfig.DevnetParams.Name: 244838, dagconfig.DevnetParams.Name: 185798,
dagconfig.SimnetParams.Name: 192038, dagconfig.SimnetParams.Name: 132998,
} }
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
expected, found := expectedResult[consensusConfig.Name] expected, found := expectedResult[consensusConfig.Name]

View File

@ -139,6 +139,9 @@ var (
// a Payload // a Payload
ErrInvalidPayload = newRuleError("ErrInvalidPayload") ErrInvalidPayload = newRuleError("ErrInvalidPayload")
// ErrWrongSigOpCount transaction input specifies an incorrect SigOpCount
ErrWrongSigOpCount = newRuleError("ErrWrongSigOpCount")
// ErrSubnetwork indicates that a block doesn't adhere to the subnetwork // ErrSubnetwork indicates that a block doesn't adhere to the subnetwork
// registry rules // registry rules
ErrSubnetworkRegistry = newRuleError("ErrSubnetworkRegistry") ErrSubnetworkRegistry = newRuleError("ErrSubnetworkRegistry")
@ -161,9 +164,9 @@ var (
// In the same block // In the same block
ErrChainedTransactions = newRuleError("ErrChainedTransactions") ErrChainedTransactions = newRuleError("ErrChainedTransactions")
// ErrBlockSizeTooHigh indicates the size of a block exceeds the maximum // ErrBlockMassTooHigh indicates the mass of a block exceeds the maximum
// allowed limits. // allowed limits.
ErrBlockSizeTooHigh = newRuleError("ErrBlockSizeTooHigh") ErrBlockMassTooHigh = newRuleError("ErrBlockMassTooHigh")
ErrKnownInvalid = newRuleError("ErrKnownInvalid") ErrKnownInvalid = newRuleError("ErrKnownInvalid")

View File

@ -53,6 +53,7 @@ func (sht SigHashType) isSigHashAnyOneCanPay() bool {
type SighashReusedValues struct { type SighashReusedValues struct {
previousOutputsHash *externalapi.DomainHash previousOutputsHash *externalapi.DomainHash
sequencesHash *externalapi.DomainHash sequencesHash *externalapi.DomainHash
sigOpCountsHash *externalapi.DomainHash
outputsHash *externalapi.DomainHash outputsHash *externalapi.DomainHash
payloadHash *externalapi.DomainHash payloadHash *externalapi.DomainHash
} }
@ -102,6 +103,9 @@ func calculateSignatureHash(tx *externalapi.DomainTransaction, inputIndex int, t
sequencesHash := getSequencesHash(tx, hashType, reusedValues) sequencesHash := getSequencesHash(tx, hashType, reusedValues)
infallibleWriteElement(hashWriter, sequencesHash) infallibleWriteElement(hashWriter, sequencesHash)
sigOpCountsHash := getSigOpCountsHash(tx, hashType, reusedValues)
infallibleWriteElement(hashWriter, sigOpCountsHash)
hashOutpoint(hashWriter, txIn.PreviousOutpoint) hashOutpoint(hashWriter, txIn.PreviousOutpoint)
infallibleWriteElement(hashWriter, prevScriptPublicKey.Version) infallibleWriteElement(hashWriter, prevScriptPublicKey.Version)
@ -111,6 +115,8 @@ func calculateSignatureHash(tx *externalapi.DomainTransaction, inputIndex int, t
infallibleWriteElement(hashWriter, txIn.Sequence) infallibleWriteElement(hashWriter, txIn.Sequence)
infallibleWriteElement(hashWriter, txIn.SigOpCount)
outputsHash := getOutputsHash(tx, inputIndex, hashType, reusedValues) outputsHash := getOutputsHash(tx, inputIndex, hashType, reusedValues)
infallibleWriteElement(hashWriter, outputsHash) infallibleWriteElement(hashWriter, outputsHash)
@ -159,6 +165,22 @@ func getSequencesHash(tx *externalapi.DomainTransaction, hashType SigHashType, r
return reusedValues.sequencesHash return reusedValues.sequencesHash
} }
func getSigOpCountsHash(tx *externalapi.DomainTransaction, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash {
if hashType.isSigHashAnyOneCanPay() {
return externalapi.NewZeroHash()
}
if reusedValues.sigOpCountsHash == nil {
hashWriter := hashes.NewTransactionSigningHashWriter()
for _, txIn := range tx.Inputs {
infallibleWriteElement(hashWriter, txIn.SigOpCount)
}
reusedValues.sigOpCountsHash = hashWriter.Finalize()
}
return reusedValues.sigOpCountsHash
}
func getOutputsHash(tx *externalapi.DomainTransaction, inputIndex int, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash { func getOutputsHash(tx *externalapi.DomainTransaction, inputIndex int, hashType SigHashType, reusedValues *SighashReusedValues) *externalapi.DomainHash {
// SigHashNone: return zero-hash // SigHashNone: return zero-hash
if hashType.isSigHashNone() { if hashType.isSigHashNone() {

View File

@ -108,86 +108,86 @@ func TestCalculateSignatureHashSchnorr(t *testing.T) {
// sigHashAll // sigHashAll
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "3e4a8effa6903dea5f762754ec410d732114ec2907e5bcbae7b6dd8d3f309a10"}, expectedSignatureHash: "56071ab5533ce9635d2a65d911b15d50b5e5f3e3103797d53173188a11696962"},
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyInput(1), // should change the hash modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "0bd2947383101f9708d94d5799626c69c1b8472d2de66523c90c4a674e99cc51"}, expectedSignatureHash: "3ee15a1f5d3827b9c3bca740ebbe422a8d07fbde287944f855da26c06782d38b"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "ae69aa1372e958f069bf52d2628ead7ee789f195340b615ff0bcb6f01a995810"}, expectedSignatureHash: "1794d1d074a587678174223788bea272d092a6155f031686b85caf11595ff6d8"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "51295575e7efc1fe1c2e741ade49089e3d780d15d26e9a0b18b3d90e35caf795"}, expectedSignatureHash: "8c580bd47a220e4ab6f343dde74a23f9e4b3971b2b519b0ed0ad34d682aa85d3"},
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"}, expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(0), // should change the hash modificationFunction: modifyInput(0), // should change the hash
expectedSignatureHash: "aeaa56f5bc99daea0be5ed4b047808ce0123a81ac89c6089b72fa7199f5cd1c6"}, expectedSignatureHash: "29cca3e62ad1e7069ccb67a4589ad6858b741ecb2abd9d470d0ec72903467edc"},
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(1), // shouldn't change the hash modificationFunction: modifyInput(1), // shouldn't change the hash
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"}, expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"}, expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
// sigHashNone // sigHashNone
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"}, expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"}, expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "72c07c152a3792fb863d2de219ab4e863fe6779dc970a5c3958e26b3a3b9f139"}, expectedSignatureHash: "52b3888a3680c79712b53c4010b7cdebd158e09b7574d95b846ba9989946c38b"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"}, expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "18eb79df328a516708f792cadfc4bf2be21b6add35fb6637a20347d532b1dce1"}, expectedSignatureHash: "cf1fd4691c22a75011909e7444c0d9582610374f7eea3debc450bbe939862cac"},
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyAmountSpent(0), // should change the hash modificationFunction: modifyAmountSpent(0), // should change the hash
expectedSignatureHash: "674a8e6effa0bbfdb3df3ca45a7b17ab695cc0f9b3e0519e5bff165de13604e2"}, expectedSignatureHash: "f76731710af7731896e415d85da6518fa316cddebd8abcb4b2ee931679296a0a"},
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyScriptPublicKey(0), // should change the hash modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "7a879d339c9b948c5264f1c0b8463f551221b2dcd575623f178cbbfcf7e01987"}, expectedSignatureHash: "382e8196e1fe34ccc4c3004ad6e6d4c41b81b8a5dd6de24fe51065a1970ef00b"},
// sigHashSingle // sigHashSingle
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"}, expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(0), // should change the hash modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "92189a32391ca50a454d1853efed55acb1c49993911a1201df9891c866c483ee"}, expectedSignatureHash: "ca882be7c6c3ae37badda62c9277be0808160d65a6a89feb514e41ed7a9658f0"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"}, expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "765e2289df98b3a5269f112d4b36d57fe32c74d42e04a3046c6a3c8dd78a4121"}, expectedSignatureHash: "7dec3b5b7b5ccd3f82f93c6c08cd05acecb970d4a4d127fcd87a11d7e0dd96e3"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"}, expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2, {name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"}, expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2, {name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"}, expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0, {name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "2e270f86fd68f780a5aa8d250364ab6786d990040268e5d561d09dde365dfab7"}, expectedSignatureHash: "35d28b074df6959cbef5aca8923e53312db3a88aab0039bd0a6b2fe92dff5aa7"},
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2, {name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
expectedSignatureHash: "afc05dd6b4a530cc3a4d7d23126548bd1f31c793e9282cbbfa27ff5566219501"}, expectedSignatureHash: "26a05df8e562f5c43cacab9a8126ae2da77e2137f8c28d13a330cd3d2b37d56b"},
// subnetwork transaction // subnetwork transaction
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "5a67423ee048e067b94e2d4fc2960f62eceff6aa8b6c5ad71e3b7b7e5ff6bad7"}, expectedSignatureHash: "1529c132cad68a014b01bac39992462f8d6c9ba6a34382e0d1d3054232e46c54"},
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyPayload, // should change the hash modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "0d3bc5914da8dc8df081945fea1255359f380ca9baa8b31dfb3657c1e3c6038a"}, expectedSignatureHash: "0366d1f0ab7a2150cd1b80b8f8944e7f6a42a38b846f2610adc4106fe70696ec"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "70abe9f947d0a0f5d735f9a063db8af41fe5902940f2693a1782119063097094"}, expectedSignatureHash: "19054bbf6dc75936dd018983373afd623a292ad1f39774cd1783b58074c3caa7"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "571a0b7ea905b7a6ff7ab825b72d23f911bac0bfaa7c4c97a4887a3d090925d4"}, expectedSignatureHash: "2fbfa5d3d24673b2e3530c3b268b58ecb6e7e34116d5c18849c27b0e7b6bfe4c"},
} }
for _, test := range tests { for _, test := range tests {
@ -230,86 +230,86 @@ func TestCalculateSignatureHashECDSA(t *testing.T) {
// sigHashAll // sigHashAll
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "150a2bcd0296f76a3395a4a9982df46bf24ce93f955bc39c10ffc95b6c524eb3"}, expectedSignatureHash: "ea7b79230b41f503baa6d3c14edf2d3e2cabc62db5b384bbac451a84c7a69694"},
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyInput(1), // should change the hash modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "8fb5304e181b003e0c123ea6f6677abc3704feec47054e8a1c218b827bf57ca0"}, expectedSignatureHash: "9ba940467c07b4254f913a95398dc6f9fac0915e0dfe9560c58dfc1f87977c08"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "180cb36454aa80822694decde4fc711104e35a4bddf92286a83877f2b8d0aabb"}, expectedSignatureHash: "ba413a6ef1101c4a4995ac30a9013fe5591ef5f6dd8d7aabaa5dd8cb74d4d765"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0, {name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "5b5f1c42a3c3c16bb4922777e2963c00e6a2cce39afa1980d2288053378f9632"}, expectedSignatureHash: "a471958e25168ab6671a76629d6f83b7f197a22972b333ebfa55d62dcc0ef065"},
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "9473ffbe0db4914f2cd8fe5d67479224a02eb031882d9170b785d0d2c7bfcd1b"}, expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(0), // should change the hash modificationFunction: modifyInput(0), // should change the hash
expectedSignatureHash: "1208491d564c138d613f51b997394dbad23feca7c0ca88c7f36cdf6b9173327d"}, expectedSignatureHash: "6cce1e9ac60a7921a08ced668c03f74d207df02064896e0beb46988a8d2c243d"},
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(1), // shouldn't change the hash modificationFunction: modifyInput(1), // shouldn't change the hash
expectedSignatureHash: "9473ffbe0db4914f2cd8fe5d67479224a02eb031882d9170b785d0d2c7bfcd1b"}, expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0, {name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "9473ffbe0db4914f2cd8fe5d67479224a02eb031882d9170b785d0d2c7bfcd1b"}, expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
// sigHashNone // sigHashNone
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
expectedSignatureHash: "6e427f26e4a9c1a7fc556a8aabdedb8799a897bc5d42a0a18615e5a0f7639d8f"}, expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "6e427f26e4a9c1a7fc556a8aabdedb8799a897bc5d42a0a18615e5a0f7639d8f"}, expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "57d76e2568cd3fc3426b4f8836fe900a2d20e740fad744949126651fd549f75e"}, expectedSignatureHash: "155e020f420fdaf62b31ccb3a13b6cb684c3db9ff85fc7062bb7e6a0653c7057"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0, {name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "6e427f26e4a9c1a7fc556a8aabdedb8799a897bc5d42a0a18615e5a0f7639d8f"}, expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "ef97a0f89d623302619f9aa2a00fce1522e72d4d255e6c6d3ed225ffc02f38ff"}, expectedSignatureHash: "3ee6c91cbbc998c52c02cad43b4a28743d6e96c9422393de69a0e15e08f470fb"},
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyAmountSpent(0), // should change the hash modificationFunction: modifyAmountSpent(0), // should change the hash
expectedSignatureHash: "043a2a943f02607be126ac6609ab2324aae389d784a4147f27101e7da379311a"}, expectedSignatureHash: "36e54667d08987a5d28d2124e7277ba5c2e93a9b8b9a7392bb7a57f1637edf76"},
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0, {name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyScriptPublicKey(0), // should change the hash modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "f2cd43d0d047cdcfbf8b6e12a86cfbf250f1e2c34dc5e631675a5f5b867bd9e6"}, expectedSignatureHash: "bdce98b53163b42175f4e885f50e8a44821159fc05d7756e3870c5f91df2be2f"},
// sigHashSingle // sigHashSingle
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
expectedSignatureHash: "1cf376b9f180f59a1b9a5e420390198c20e1ba79c39349271632145fda175247"}, expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(0), // should change the hash modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "c2c7e77516a15f0f47f886b14cc47af2045eea15f176a9a560a9d47d8866958f"}, expectedSignatureHash: "394192ce7faee4f5055939c6fa3bf41a3008ec29e667d60bd5203987850debd4"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "1cf376b9f180f59a1b9a5e420390198c20e1ba79c39349271632145fda175247"}, expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "2034eec2acc08c49d3896cc1bda214904ca850fc5989518885465b5a3154ee7f"}, expectedSignatureHash: "55b1a9f7ee395ea37a8a6da804c9a654216364a42e37d329c5dc69c349369825"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0, {name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "1cf376b9f180f59a1b9a5e420390198c20e1ba79c39349271632145fda175247"}, expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2, {name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
expectedSignatureHash: "84ae3bb03202efc587d97e5aea7b80581b82242b969e6dea13b8daa32d24c0c1"}, expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2, {name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "84ae3bb03202efc587d97e5aea7b80581b82242b969e6dea13b8daa32d24c0c1"}, expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0, {name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "b2ccf259a65c3231d741a03420967b95563c3928cc15d3d15e8e795f383ab48b"}, expectedSignatureHash: "7062156c393e71c6308f9d451a9f4850d9c331f77372d165bb9bcf0296e6a3d3"},
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2, {name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
expectedSignatureHash: "652c8cd0ac050e41aad347ea09ee788360eec70908ba22fe5bba5bdde49b8ae1"}, expectedSignatureHash: "84b56500814e4c7de8569ef6a5dfc269ca35db3160adaebedd92e68fe9d2c02b"},
// subnetwork transaction // subnetwork transaction
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "2e828c04f5f03e4ce4b3de1fa5303400da5fa504291b760f5f6d4e98fc24597f"}, expectedSignatureHash: "ab783013148f1fbc6a0c29c5e2e320ea1dab61122f4b556810ef07c96871964a"},
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyPayload, // should change the hash modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "d5f3993aa8b7f47df52f78f2be9965f928c9cca9ac9e9542f1190b9d5ed6c17d"}, expectedSignatureHash: "bad87ce0a6d5fade1bb9eb5de572a3a9904e6d0ef5d627b97c69380818c1ad6f"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "e74d4a9fa5cdf476299ebdfa03f3c8021a157f814731ea11f6a6d606dc5cd439"}, expectedSignatureHash: "54bdd33d4c8ea1baac6e92a129ad8a6bb90803b7b21387cc4ec9640752f4bb61"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0, {name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "ca8bf9bc42cda2ec3ce8bee090011072e56ff4d0d8616d5c20cefe5f84d7fb37"}, expectedSignatureHash: "e71d0226c6c0cc26e0a99146f597ff9b9b51406f64854235b18f741d4c87eac4"},
} }
for _, test := range tests { for _, test := range tests {

View File

@ -1,65 +0,0 @@
package estimatedsize
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
)
// TransactionEstimatedSerializedSize is the estimated size of a transaction in some
// serialization. This has to be deterministic, but not necessarily accurate, since
// it's only used as the size component in the transaction mass and block size limit
// calculation.
func TransactionEstimatedSerializedSize(tx *externalapi.DomainTransaction) uint64 {
if transactionhelper.IsCoinBase(tx) {
return 0
}
size := uint64(0)
size += 2 // Txn Version
size += 8 // number of inputs (uint64)
for _, input := range tx.Inputs {
size += transactionInputEstimatedSerializedSize(input)
}
size += 8 // number of outputs (uint64)
for _, output := range tx.Outputs {
size += TransactionOutputEstimatedSerializedSize(output)
}
size += 8 // lock time (uint64)
size += externalapi.DomainSubnetworkIDSize
size += 8 // gas (uint64)
size += externalapi.DomainHashSize // payload hash
size += 8 // length of the payload (uint64)
size += uint64(len(tx.Payload))
return size
}
func transactionInputEstimatedSerializedSize(input *externalapi.DomainTransactionInput) uint64 {
size := uint64(0)
size += outpointEstimatedSerializedSize()
size += 8 // length of signature script (uint64)
size += uint64(len(input.SignatureScript))
size += 8 // sequence (uint64)
return size
}
func outpointEstimatedSerializedSize() uint64 {
size := uint64(0)
size += externalapi.DomainHashSize // ID
size += 4 // index (uint32)
return size
}
// TransactionOutputEstimatedSerializedSize is the same as TransactionEstimatedSerializedSize but for outputs only
func TransactionOutputEstimatedSerializedSize(output *externalapi.DomainTransactionOutput) uint64 {
size := uint64(0)
size += 8 // value (uint64)
size += 2 //output.ScriptPublicKey.Version (uint 16)
size += 8 // length of script public key (uint64)
size += uint64(len(output.ScriptPublicKey.Script))
return size
}

View File

@ -242,13 +242,9 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int {
nSigs := 0 nSigs := 0
for i, pop := range pops { for i, pop := range pops {
switch pop.opcode.value { switch pop.opcode.value {
case OpCheckSig: case OpCheckSig, OpCheckSigVerify, OpCheckSigECDSA:
fallthrough
case OpCheckSigVerify:
nSigs++ nSigs++
case OpCheckMultiSig: case OpCheckMultiSig, OpCheckMultiSigVerify, OpCheckMultiSigECDSA:
fallthrough
case OpCheckMultiSigVerify:
// If we are being precise then look for familiar // If we are being precise then look for familiar
// patterns for multisig, for now all we recognize is // patterns for multisig, for now all we recognize is
// OP_1 - OP_16 to signify the number of pubkeys. // OP_1 - OP_16 to signify the number of pubkeys.

View File

@ -1,8 +1,9 @@
package dagconfig package dagconfig
import ( import (
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"time" "time"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
) )
// The documentation refers to the following constants which aren't explicated in the code: // The documentation refers to the following constants which aren't explicated in the code:
@ -23,30 +24,32 @@ import (
const ( const (
defaultMaxCoinbasePayloadLength = 150 defaultMaxCoinbasePayloadLength = 150
// defaultMaxBlockSize is a bound on the size of a block in bytes, larger values increase the bound d // defaultMaxBlockMass is a bound on the mass of a block, larger values increase the bound d
// on the round trip time of a block, which affects the other parameters as described below // on the round trip time of a block, which affects the other parameters as described below
defaultMaxBlockSize = 50_000 defaultMaxBlockMass = 500_000
// defaultMaxBlockParents is the number of blocks any block can point to. // defaultMassPerTxByte, defaultMassPerScriptPubKeyByte and defaultMassPerSigOp define the number of grams per
// Should be about d/defaultTargetTimePerBlock where d is a bound on the round trip time of a block. // transaction byte, script pub key byte and sig op respectively.
defaultMaxBlockParents = 10 // These values are used when calculating a transactions mass.
defaultMassPerTxByte = 1 defaultMassPerTxByte = 1
defaultMassPerScriptPubKeyByte = 10 defaultMassPerScriptPubKeyByte = 10
defaultMassPerSigOp = 10000 defaultMassPerSigOp = 1000
// defaultMergeSetSizeLimit is a bound on the size of the past of a block and the size of the past // defaultMaxBlockParents is the number of blocks any block can point to.
// of its selected parent. Any block which violates this bound is invalid. // Should be about d/defaultTargetTimePerBlock where d is a bound on the round trip time of a block.
// Should be at least an order of magnitude smaller than defaultFinalityDuration/defaultTargetTimePerBlock. defaultMaxBlockParents = 10
// (Higher values make pruning attacks easier by a constant, lower values make merging after a split or a spike
// in block take longer)
defaultMergeSetSizeLimit = 1000
defaultMaxMassAcceptedByBlock = 500_000
defaultBaseSubsidy = 50 * constants.SompiPerKaspa
defaultCoinbasePayloadScriptPublicKeyMaxLength = 150
// defaultGHOSTDAGK is a bound on the number of blue blocks in the anticone of a blue block. Approximates the maximal // defaultGHOSTDAGK is a bound on the number of blue blocks in the anticone of a blue block. Approximates the maximal
// width of the network. // width of the network.
// Formula (1) in section 4.2 of the PHATOM paper shows how to calculate defaultGHOSTDAGK. The delta term represents a bound // Formula (1) in section 4.2 of the PHATOM paper shows how to calculate defaultGHOSTDAGK. The delta term represents a bound
// on the expected fraction of the network life in which the width was higher than defaultGHOSTDAGK. The current value of K // on the expected fraction of the network life in which the width was higher than defaultGHOSTDAGK. The current value of K
// was calculated for d = 5 seconds and delta = 0.05. // was calculated for d = 5 seconds and delta = 0.05.
defaultGHOSTDAGK = 18 defaultGHOSTDAGK = 18
// defaultMergeSetSizeLimit is a bound on the size of the past of a block and the size of the past
// of its selected parent. Any block which violates this bound is invalid.
// Should be at least an order of magnitude smaller than defaultFinalityDuration/defaultTargetTimePerBlock.
// (Higher values make pruning attacks easier by a constant, lower values make merging after a split or a spike
// in block take longer)
defaultMergeSetSizeLimit = defaultGHOSTDAGK * 10
defaultBaseSubsidy = 50 * constants.SompiPerKaspa
defaultCoinbasePayloadScriptPublicKeyMaxLength = 150
// defaultDifficultyAdjustmentWindowSize is the number of blocks in a block's past used to calculate its difficulty // defaultDifficultyAdjustmentWindowSize is the number of blocks in a block's past used to calculate its difficulty
// target. // target.
defaultDifficultyAdjustmentWindowSize = 2640 defaultDifficultyAdjustmentWindowSize = 2640

View File

@ -150,8 +150,8 @@ type Params struct {
// MaxCoinbasePayloadLength is the maximum length in bytes allowed for a block's coinbase's payload // MaxCoinbasePayloadLength is the maximum length in bytes allowed for a block's coinbase's payload
MaxCoinbasePayloadLength uint64 MaxCoinbasePayloadLength uint64
// MaxBlockSize is the maximum size in bytes a block is allowed // MaxBlockMass is the maximum mass a block is allowed
MaxBlockSize uint64 MaxBlockMass uint64
// MaxBlockParents is the maximum number of blocks a block is allowed to point to // MaxBlockParents is the maximum number of blocks a block is allowed to point to
MaxBlockParents model.KType MaxBlockParents model.KType
@ -171,9 +171,6 @@ type Params struct {
// MergeSetSizeLimit is the maximum number of blocks in a block's merge set // MergeSetSizeLimit is the maximum number of blocks in a block's merge set
MergeSetSizeLimit uint64 MergeSetSizeLimit uint64
// MaxMassAcceptedByBlock is the maximum total transaction mass a block may accept.
MaxMassAcceptedByBlock uint64
// CoinbasePayloadScriptPublicKeyMaxLength is the maximum allowed script public key in the coinbase's payload // CoinbasePayloadScriptPublicKeyMaxLength is the maximum allowed script public key in the coinbase's payload
CoinbasePayloadScriptPublicKeyMaxLength uint8 CoinbasePayloadScriptPublicKeyMaxLength uint8
@ -242,13 +239,12 @@ var MainnetParams = Params{
DisableDifficultyAdjustment: false, DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength, MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize, MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents, MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte, MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte, MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp, MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit, MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy, BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength, CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
} }
@ -299,13 +295,12 @@ var TestnetParams = Params{
DisableDifficultyAdjustment: false, DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength, MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize, MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents, MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte, MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte, MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp, MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit, MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy, BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength, CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
} }
@ -360,13 +355,12 @@ var SimnetParams = Params{
DisableDifficultyAdjustment: true, DisableDifficultyAdjustment: true,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength, MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize, MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents, MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte, MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte, MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp, MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit, MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy, BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength, CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
} }
@ -417,13 +411,12 @@ var DevnetParams = Params{
DisableDifficultyAdjustment: false, DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength, MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize, MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents, MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte, MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte, MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp, MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit, MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy, BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength, CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
} }

View File

@ -19,7 +19,7 @@ func (f *factory) NewMiningManager(consensus externalapi.Consensus, params *dagc
mempoolConfig *mempoolpkg.Config) MiningManager { mempoolConfig *mempoolpkg.Config) MiningManager {
mempool := mempoolpkg.New(mempoolConfig, consensus) mempool := mempoolpkg.New(mempoolConfig, consensus)
blockTemplateBuilder := blocktemplatebuilder.New(consensus, mempool, params.MaxMassAcceptedByBlock) blockTemplateBuilder := blocktemplatebuilder.New(consensus, mempool, params.MaxBlockMass)
return &miningManager{ return &miningManager{
mempool: mempool, mempool: mempool,

View File

@ -3,11 +3,12 @@ package mempool
import ( import (
"fmt" "fmt"
"github.com/kaspanet/kaspad/domain/consensus/processes/transactionvalidator"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants" "github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript" "github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/util" "github.com/kaspanet/kaspad/util"
) )
@ -36,10 +37,9 @@ const (
// (1 + 15*74 + 3) + (15*34 + 3) + 23 = 1650 // (1 + 15*74 + 3) + (15*34 + 3) + 23 = 1650
maximumStandardSignatureScriptSize = 1650 maximumStandardSignatureScriptSize = 1650
// maximumStandardTransactionSize is the maximum size allowed for transactions that // maximumStandardTransactionMass is the maximum mass allowed for transactions that
// are considered standard and will therefore be relayed and considered // are considered standard and will therefore be relayed and considered for mining.
// for mining. maximumStandardTransactionMass = 100000
maximumStandardTransactionSize = 100000
) )
func (mp *mempool) checkTransactionStandardInIsolation(transaction *externalapi.DomainTransaction) error { func (mp *mempool) checkTransactionStandardInIsolation(transaction *externalapi.DomainTransaction) error {
@ -59,10 +59,9 @@ func (mp *mempool) checkTransactionStandardInIsolation(transaction *externalapi.
// almost as much to process as the sender fees, limit the maximum // almost as much to process as the sender fees, limit the maximum
// size of a transaction. This also helps mitigate CPU exhaustion // size of a transaction. This also helps mitigate CPU exhaustion
// attacks. // attacks.
serializedLength := estimatedsize.TransactionEstimatedSerializedSize(transaction) if transaction.Mass > maximumStandardTransactionMass {
if serializedLength > maximumStandardTransactionSize { str := fmt.Sprintf("transaction mass of %d is larger than max allowed size of %d",
str := fmt.Sprintf("transaction size of %d is larger than max allowed size of %d", transaction.Mass, maximumStandardTransactionMass)
serializedLength, maximumStandardTransactionSize)
return transactionRuleError(RejectNonstandard, str) return transactionRuleError(RejectNonstandard, str)
} }
@ -129,7 +128,7 @@ func (mp *mempool) IsTransactionOutputDust(output *externalapi.DomainTransaction
// The most common scripts are pay-to-pubkey, and as per the above // The most common scripts are pay-to-pubkey, and as per the above
// breakdown, the minimum size of a p2pk input script is 148 bytes. So // breakdown, the minimum size of a p2pk input script is 148 bytes. So
// that figure is used. // that figure is used.
totalSerializedSize := estimatedsize.TransactionOutputEstimatedSerializedSize(output) + 148 totalSerializedSize := transactionvalidator.TransactionOutputEstimatedSerializedSize(output) + 148
// The output is considered dust if the cost to the network to spend the // The output is considered dust if the cost to the network to spend the
// coins is more than 1/3 of the minimum free transaction relay fee. // coins is more than 1/3 of the minimum free transaction relay fee.
@ -176,8 +175,7 @@ func (mp *mempool) checkTransactionStandardInContext(transaction *externalapi.Do
} }
} }
serializedSize := estimatedsize.TransactionEstimatedSerializedSize(transaction) minimumFee := mp.minimumRequiredTransactionRelayFee(transaction.Mass)
minimumFee := mp.minimumRequiredTransactionRelayFee(serializedSize)
if transaction.Fee < minimumFee { if transaction.Fee < minimumFee {
str := fmt.Sprintf("transaction %s has %d fees which is under the required amount of %d", str := fmt.Sprintf("transaction %s has %d fees which is under the required amount of %d",
consensushashing.TransactionID(transaction), transaction.Fee, minimumFee) consensushashing.TransactionID(transaction), transaction.Fee, minimumFee)
@ -188,14 +186,12 @@ func (mp *mempool) checkTransactionStandardInContext(transaction *externalapi.Do
} }
// minimumRequiredTransactionRelayFee returns the minimum transaction fee required for a // minimumRequiredTransactionRelayFee returns the minimum transaction fee required for a
// transaction with the passed serialized size to be accepted into the memory // transaction with the passed mass to be accepted into the mampool and relayed.
// pool and relayed. func (mp *mempool) minimumRequiredTransactionRelayFee(mass uint64) uint64 {
func (mp *mempool) minimumRequiredTransactionRelayFee(serializedSize uint64) uint64 {
// Calculate the minimum fee for a transaction to be allowed into the // Calculate the minimum fee for a transaction to be allowed into the
// mempool and relayed by scaling the base fee. MinimumRelayTransactionFee is in // mempool and relayed by scaling the base fee. MinimumRelayTransactionFee is in
// sompi/kB so multiply by serializedSize (which is in bytes) and // sompi/kg so multiply by mass (which is in grams) and divide by 1000 to get minimum sompis.
// divide by 1000 to get minimum sompis. minimumFee := (mass * uint64(mp.config.MinimumRelayTransactionFee)) / 1000
minimumFee := (serializedSize * uint64(mp.config.MinimumRelayTransactionFee)) / 1000
if minimumFee == 0 && mp.config.MinimumRelayTransactionFee > 0 { if minimumFee == 0 && mp.config.MinimumRelayTransactionFee > 0 {
minimumFee = uint64(mp.config.MinimumRelayTransactionFee) minimumFee = uint64(mp.config.MinimumRelayTransactionFee)

View File

@ -44,13 +44,13 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
}, },
{ {
"max standard tx size with default minimum relay fee", "max standard tx size with default minimum relay fee",
maximumStandardTransactionSize, maximumStandardTransactionMass,
defaultMinimumRelayTransactionFee, defaultMinimumRelayTransactionFee,
100000, 100000,
}, },
{ {
"max standard tx size with max sompi relay fee", "max standard tx size with max sompi relay fee",
maximumStandardTransactionSize, maximumStandardTransactionMass,
util.MaxSompi, util.MaxSompi,
util.MaxSompi, util.MaxSompi,
}, },
@ -244,7 +244,7 @@ func TestCheckTransactionStandardInIsolation(t *testing.T) {
name: "Transaction size is too large", name: "Transaction size is too large",
tx: &externalapi.DomainTransaction{Version: 0, Inputs: []*externalapi.DomainTransactionInput{&dummyTxIn}, Outputs: []*externalapi.DomainTransactionOutput{{ tx: &externalapi.DomainTransaction{Version: 0, Inputs: []*externalapi.DomainTransactionInput{&dummyTxIn}, Outputs: []*externalapi.DomainTransactionOutput{{
Value: 0, Value: 0,
ScriptPublicKey: &externalapi.ScriptPublicKey{bytes.Repeat([]byte{0x00}, maximumStandardTransactionSize+1), 0}, ScriptPublicKey: &externalapi.ScriptPublicKey{bytes.Repeat([]byte{0x00}, maximumStandardTransactionMass+1), 0},
}}}, }}},
height: 300000, height: 300000,
isStandard: false, isStandard: false,

View File

@ -18,11 +18,13 @@ const (
defaultOrphanExpireIntervalSeconds uint64 = 60 defaultOrphanExpireIntervalSeconds uint64 = 60
defaultOrphanExpireScanIntervalSeconds uint64 = 10 defaultOrphanExpireScanIntervalSeconds uint64 = 10
defaultMaximumOrphanTransactionSize = 100000 defaultMaximumOrphanTransactionMass = 100000
// defaultMaximumOrphanTransactionCount should remain small as long as we have recursion in // defaultMaximumOrphanTransactionCount should remain small as long as we have recursion in
// removeOrphans when removeRedeemers = true // removeOrphans when removeRedeemers = true
defaultMaximumOrphanTransactionCount = 50 defaultMaximumOrphanTransactionCount = 50
// defaultMinimumRelayTransactionFee specifies the minimum transaction fee for a transaction to be accepted to
// the mempool and relayed. It is specified in sompi per 1kg (or 1000 grams) of transaction mass.
defaultMinimumRelayTransactionFee = util.Amount(1000) defaultMinimumRelayTransactionFee = util.Amount(1000)
// Standard transaction version range might be different from what consensus accepts, therefore // Standard transaction version range might be different from what consensus accepts, therefore
@ -41,10 +43,10 @@ type Config struct {
TransactionExpireScanIntervalSeconds uint64 TransactionExpireScanIntervalSeconds uint64
OrphanExpireIntervalDAAScore uint64 OrphanExpireIntervalDAAScore uint64
OrphanExpireScanIntervalDAAScore uint64 OrphanExpireScanIntervalDAAScore uint64
MaximumOrphanTransactionSize uint64 MaximumOrphanTransactionMass uint64
MaximumOrphanTransactionCount uint64 MaximumOrphanTransactionCount uint64
AcceptNonStandard bool AcceptNonStandard bool
MaximumMassAcceptedByBlock uint64 MaximumMassPerBlock uint64
MinimumRelayTransactionFee util.Amount MinimumRelayTransactionFee util.Amount
MinimumStandardTransactionVersion uint16 MinimumStandardTransactionVersion uint16
MaximumStandardTransactionVersion uint16 MaximumStandardTransactionVersion uint16
@ -61,10 +63,10 @@ func DefaultConfig(dagParams *dagconfig.Params) *Config {
TransactionExpireScanIntervalSeconds: defaultTransactionExpireScanIntervalSeconds, TransactionExpireScanIntervalSeconds: defaultTransactionExpireScanIntervalSeconds,
OrphanExpireIntervalDAAScore: defaultOrphanExpireIntervalSeconds / targetBlocksPerSecond, OrphanExpireIntervalDAAScore: defaultOrphanExpireIntervalSeconds / targetBlocksPerSecond,
OrphanExpireScanIntervalDAAScore: defaultOrphanExpireScanIntervalSeconds / targetBlocksPerSecond, OrphanExpireScanIntervalDAAScore: defaultOrphanExpireScanIntervalSeconds / targetBlocksPerSecond,
MaximumOrphanTransactionSize: defaultMaximumOrphanTransactionSize, MaximumOrphanTransactionMass: defaultMaximumOrphanTransactionMass,
MaximumOrphanTransactionCount: defaultMaximumOrphanTransactionCount, MaximumOrphanTransactionCount: defaultMaximumOrphanTransactionCount,
AcceptNonStandard: dagParams.RelayNonStdTxs, AcceptNonStandard: dagParams.RelayNonStdTxs,
MaximumMassAcceptedByBlock: dagParams.MaxMassAcceptedByBlock, MaximumMassPerBlock: dagParams.MaxBlockMass,
MinimumRelayTransactionFee: defaultMinimumRelayTransactionFee, MinimumRelayTransactionFee: defaultMinimumRelayTransactionFee,
MinimumStandardTransactionVersion: defaultMinimumStandardTransactionVersion, MinimumStandardTransactionVersion: defaultMinimumStandardTransactionVersion,
MaximumStandardTransactionVersion: defaultMaximumStandardTransactionVersion, MaximumStandardTransactionVersion: defaultMaximumStandardTransactionVersion,

View File

@ -10,7 +10,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo" "github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model" "github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -44,7 +43,7 @@ func (op *orphansPool) maybeAddOrphan(transaction *externalapi.DomainTransaction
return err return err
} }
err = op.checkOrphanSize(transaction) err = op.checkOrphanMass(transaction)
if err != nil { if err != nil {
return err return err
} }
@ -87,12 +86,11 @@ func (op *orphansPool) limitOrphanPoolSize() error {
return nil return nil
} }
func (op *orphansPool) checkOrphanSize(transaction *externalapi.DomainTransaction) error { func (op *orphansPool) checkOrphanMass(transaction *externalapi.DomainTransaction) error {
serializedLength := estimatedsize.TransactionEstimatedSerializedSize(transaction) if transaction.Mass > op.mempool.config.MaximumOrphanTransactionMass {
if serializedLength > op.mempool.config.MaximumOrphanTransactionSize {
str := fmt.Sprintf("orphan transaction size of %d bytes is "+ str := fmt.Sprintf("orphan transaction size of %d bytes is "+
"larger than max allowed size of %d bytes", "larger than max allowed size of %d bytes",
serializedLength, op.mempool.config.MaximumOrphanTransactionSize) transaction.Mass, op.mempool.config.MaximumOrphanTransactionMass)
return transactionRuleError(RejectBadOrphan, str) return transactionRuleError(RejectBadOrphan, str)
} }
return nil return nil

View File

@ -16,6 +16,9 @@ func (mp *mempool) validateAndInsertTransaction(transaction *externalapi.DomainT
fmt.Sprintf("validateAndInsertTransaction %s", consensushashing.TransactionID(transaction))) fmt.Sprintf("validateAndInsertTransaction %s", consensushashing.TransactionID(transaction)))
defer onEnd() defer onEnd()
// Populate mass in the beginning, it will be used in multiple places throughout the validation and insertion.
mp.consensus.PopulateMass(transaction)
err = mp.validateTransactionPreUTXOEntry(transaction) err = mp.validateTransactionPreUTXOEntry(transaction)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -44,13 +44,6 @@ func (mp *mempool) validateTransactionInIsolation(transaction *externalapi.Domai
} }
func (mp *mempool) validateTransactionInContext(transaction *externalapi.DomainTransaction) error { func (mp *mempool) validateTransactionInContext(transaction *externalapi.DomainTransaction) error {
transactionID := consensushashing.TransactionID(transaction)
if transaction.Mass > mp.config.MaximumMassAcceptedByBlock {
return transactionRuleError(RejectInvalid, fmt.Sprintf("transaction %s mass is %d which is "+
"higher than the maxmimum of %d", transactionID,
transaction.Mass, mp.config.MaximumMassAcceptedByBlock))
}
if !mp.config.AcceptNonStandard { if !mp.config.AcceptNonStandard {
err := mp.checkTransactionStandardInContext(transaction) err := mp.checkTransactionStandardInContext(transaction)
if err != nil { if err != nil {

View File

@ -28,8 +28,7 @@ type overrideDAGParamsConfig struct {
K *model.KType `json:"k"` K *model.KType `json:"k"`
MaxBlockParents *model.KType `json:"maxBlockParents"` MaxBlockParents *model.KType `json:"maxBlockParents"`
MergeSetSizeLimit *uint64 `json:"mergeSetSizeLimit"` MergeSetSizeLimit *uint64 `json:"mergeSetSizeLimit"`
MaxMassAcceptedByBlock *uint64 `json:"maxMassAcceptedByBlock"` MaxBlockMass *uint64 `json:"maxBlockMass"`
MaxBlockSize *uint64 `json:"maxBlockSize"`
MaxCoinbasePayloadLength *uint64 `json:"maxCoinbasePayloadLength"` MaxCoinbasePayloadLength *uint64 `json:"maxCoinbasePayloadLength"`
MassPerTxByte *uint64 `json:"massPerTxByte"` MassPerTxByte *uint64 `json:"massPerTxByte"`
MassPerScriptPubKeyByte *uint64 `json:"massPerScriptPubKeyByte"` MassPerScriptPubKeyByte *uint64 `json:"massPerScriptPubKeyByte"`
@ -132,12 +131,8 @@ func (networkFlags *NetworkFlags) overrideDAGParams() error {
networkFlags.ActiveNetParams.MergeSetSizeLimit = *config.MergeSetSizeLimit networkFlags.ActiveNetParams.MergeSetSizeLimit = *config.MergeSetSizeLimit
} }
if config.MaxMassAcceptedByBlock != nil { if config.MaxBlockMass != nil {
networkFlags.ActiveNetParams.MaxMassAcceptedByBlock = *config.MaxMassAcceptedByBlock networkFlags.ActiveNetParams.MaxBlockMass = *config.MaxBlockMass
}
if config.MaxBlockSize != nil {
networkFlags.ActiveNetParams.MaxBlockSize = *config.MaxBlockSize
} }
if config.MaxCoinbasePayloadLength != nil { if config.MaxCoinbasePayloadLength != nil {

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.25.0
// protoc v3.12.3 // protoc v3.12.3
// source: messages.proto // source: messages.proto
package protowire package protowire
import ( import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type KaspadMessage struct { type KaspadMessage struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache

View File

@ -11,8 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion6
const _ = grpc.SupportPackageIsVersion7
// P2PClient is the client API for P2P service. // P2PClient is the client API for P2P service.
// //
@ -30,7 +29,7 @@ func NewP2PClient(cc grpc.ClientConnInterface) P2PClient {
} }
func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) { func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &P2P_ServiceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...) stream, err := c.cc.NewStream(ctx, &_P2P_serviceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -72,20 +71,13 @@ type P2PServer interface {
type UnimplementedP2PServer struct { type UnimplementedP2PServer struct {
} }
func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error { func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
} }
func (UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {} func (*UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {}
// UnsafeP2PServer may be embedded to opt out of forward compatibility for this service. func RegisterP2PServer(s *grpc.Server, srv P2PServer) {
// Use of this interface is not recommended, as added methods to P2PServer will s.RegisterService(&_P2P_serviceDesc, srv)
// result in compilation errors.
type UnsafeP2PServer interface {
mustEmbedUnimplementedP2PServer()
}
func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) {
s.RegisterService(&P2P_ServiceDesc, srv)
} }
func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -114,10 +106,7 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil return m, nil
} }
// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service. var _P2P_serviceDesc = grpc.ServiceDesc{
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var P2P_ServiceDesc = grpc.ServiceDesc{
ServiceName: "protowire.P2P", ServiceName: "protowire.P2P",
HandlerType: (*P2PServer)(nil), HandlerType: (*P2PServer)(nil),
Methods: []grpc.MethodDesc{}, Methods: []grpc.MethodDesc{},
@ -148,7 +137,7 @@ func NewRPCClient(cc grpc.ClientConnInterface) RPCClient {
} }
func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) { func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &RPC_ServiceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...) stream, err := c.cc.NewStream(ctx, &_RPC_serviceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -190,20 +179,13 @@ type RPCServer interface {
type UnimplementedRPCServer struct { type UnimplementedRPCServer struct {
} }
func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error { func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
} }
func (UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {} func (*UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {}
// UnsafeRPCServer may be embedded to opt out of forward compatibility for this service. func RegisterRPCServer(s *grpc.Server, srv RPCServer) {
// Use of this interface is not recommended, as added methods to RPCServer will s.RegisterService(&_RPC_serviceDesc, srv)
// result in compilation errors.
type UnsafeRPCServer interface {
mustEmbedUnimplementedRPCServer()
}
func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) {
s.RegisterService(&RPC_ServiceDesc, srv)
} }
func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -232,10 +214,7 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil return m, nil
} }
// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service. var _RPC_serviceDesc = grpc.ServiceDesc{
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RPC_ServiceDesc = grpc.ServiceDesc{
ServiceName: "protowire.RPC", ServiceName: "protowire.RPC",
HandlerType: (*RPCServer)(nil), HandlerType: (*RPCServer)(nil),
Methods: []grpc.MethodDesc{}, Methods: []grpc.MethodDesc{},

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.25.0
// protoc v3.12.3 // protoc v3.12.3
// source: p2p.proto // source: p2p.proto
package protowire package protowire
import ( import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type RequestAddressesMessage struct { type RequestAddressesMessage struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -335,6 +340,7 @@ type TransactionInput struct {
PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"` PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"`
SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"` SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"`
Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"`
SigOpCount uint32 `protobuf:"varint,4,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
} }
func (x *TransactionInput) Reset() { func (x *TransactionInput) Reset() {
@ -390,6 +396,13 @@ func (x *TransactionInput) GetSequence() uint64 {
return 0 return 0
} }
func (x *TransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type Outpoint struct { type Outpoint struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -2269,7 +2282,7 @@ var file_p2p_proto_rawDesc = []byte{
0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12,
0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61,
0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x99, 0x01, 0x0a, 0x10, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xb9, 0x01, 0x0a, 0x10,
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x12, 0x3f, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x12, 0x3f, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f,
@ -2279,7 +2292,9 @@ var file_p2p_proto_rawDesc = []byte{
0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e,
0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73,
0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73,
0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x60, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70,
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67,
0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x60, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x69, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,

View File

@ -36,6 +36,7 @@ message TransactionInput{
Outpoint previousOutpoint = 1; Outpoint previousOutpoint = 1;
bytes signatureScript = 2; bytes signatureScript = 2;
uint64 sequence = 3; uint64 sequence = 3;
uint32 sigOpCount = 4;
} }
message Outpoint{ message Outpoint{

View File

@ -1,9 +1,10 @@
package protowire package protowire
import ( import (
"math"
"github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/appmessage"
"github.com/pkg/errors" "github.com/pkg/errors"
"math"
) )
func (x *KaspadMessage_Transaction) toAppMessage() (appmessage.Message, error) { func (x *KaspadMessage_Transaction) toAppMessage() (appmessage.Message, error) {
@ -64,11 +65,14 @@ func (x *TransactionInput) toAppMessage() (*appmessage.TxIn, error) {
if x == nil { if x == nil {
return nil, errors.Wrapf(errorNil, "TransactionInput is nil") return nil, errors.Wrapf(errorNil, "TransactionInput is nil")
} }
if x.SigOpCount > math.MaxUint8 {
return nil, errors.New("TransactionInput SigOpCount > math.MaxUint8")
}
outpoint, err := x.PreviousOutpoint.toAppMessage() outpoint, err := x.PreviousOutpoint.toAppMessage()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return appmessage.NewTxIn(outpoint, x.SignatureScript, x.Sequence), nil return appmessage.NewTxIn(outpoint, x.SignatureScript, x.Sequence, byte(x.SigOpCount)), nil
} }
func (x *TransactionOutput) toAppMessage() (*appmessage.TxOut, error) { func (x *TransactionOutput) toAppMessage() (*appmessage.TxOut, error) {
@ -95,6 +99,7 @@ func (x *TransactionMessage) fromAppMessage(msgTx *appmessage.MsgTx) {
}, },
SignatureScript: input.SignatureScript, SignatureScript: input.SignatureScript,
Sequence: input.Sequence, Sequence: input.Sequence,
SigOpCount: uint32(input.SigOpCount),
} }
} }
@ -118,5 +123,4 @@ func (x *TransactionMessage) fromAppMessage(msgTx *appmessage.MsgTx) {
Gas: msgTx.Gas, Gas: msgTx.Gas,
Payload: msgTx.Payload, Payload: msgTx.Payload,
} }
} }

View File

@ -230,6 +230,7 @@ Receivers of any ResponseMessage are expected to check whether its error field i
| previousOutpoint | [RpcOutpoint](#protowire.RpcOutpoint) | | | | previousOutpoint | [RpcOutpoint](#protowire.RpcOutpoint) | | |
| signatureScript | [string](#string) | | | | signatureScript | [string](#string) | | |
| sequence | [uint64](#uint64) | | | | sequence | [uint64](#uint64) | | |
| sigOpCount | [uint32](#uint32) | | |
| verboseData | [RpcTransactionInputVerboseData](#protowire.RpcTransactionInputVerboseData) | | | | verboseData | [RpcTransactionInputVerboseData](#protowire.RpcTransactionInputVerboseData) | | |
@ -727,6 +728,7 @@ SubmitTransactionRequestMessage submits a transaction to the mempool
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| transaction | [RpcTransaction](#protowire.RpcTransaction) | | | | transaction | [RpcTransaction](#protowire.RpcTransaction) | | |
| allowOrphan | [bool](#bool) | | |

View File

@ -10,13 +10,14 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.25.0
// protoc v3.12.3 // protoc v3.12.3
// source: rpc.proto // source: rpc.proto
package protowire package protowire
import ( import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
@ -30,6 +31,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type SubmitBlockResponseMessage_RejectReason int32 type SubmitBlockResponseMessage_RejectReason int32
const ( const (
@ -501,6 +506,7 @@ type RpcTransactionInput struct {
PreviousOutpoint *RpcOutpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"` PreviousOutpoint *RpcOutpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,omitempty"`
SignatureScript string `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"` SignatureScript string `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,omitempty"`
Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"`
SigOpCount uint32 `protobuf:"varint,5,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
VerboseData *RpcTransactionInputVerboseData `protobuf:"bytes,4,opt,name=verboseData,proto3" json:"verboseData,omitempty"` VerboseData *RpcTransactionInputVerboseData `protobuf:"bytes,4,opt,name=verboseData,proto3" json:"verboseData,omitempty"`
} }
@ -557,6 +563,13 @@ func (x *RpcTransactionInput) GetSequence() uint64 {
return 0 return 0
} }
func (x *RpcTransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
func (x *RpcTransactionInput) GetVerboseData() *RpcTransactionInputVerboseData { func (x *RpcTransactionInput) GetVerboseData() *RpcTransactionInputVerboseData {
if x != nil { if x != nil {
return x.VerboseData return x.VerboseData
@ -815,7 +828,7 @@ type RpcTransactionVerboseData struct {
TransactionId string `protobuf:"bytes,1,opt,name=transactionId,proto3" json:"transactionId,omitempty"` TransactionId string `protobuf:"bytes,1,opt,name=transactionId,proto3" json:"transactionId,omitempty"`
Hash string `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` Hash string `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
Size uint64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` Mass uint64 `protobuf:"varint,4,opt,name=mass,proto3" json:"mass,omitempty"`
BlockHash string `protobuf:"bytes,12,opt,name=blockHash,proto3" json:"blockHash,omitempty"` BlockHash string `protobuf:"bytes,12,opt,name=blockHash,proto3" json:"blockHash,omitempty"`
BlockTime uint64 `protobuf:"varint,14,opt,name=blockTime,proto3" json:"blockTime,omitempty"` BlockTime uint64 `protobuf:"varint,14,opt,name=blockTime,proto3" json:"blockTime,omitempty"`
} }
@ -866,9 +879,9 @@ func (x *RpcTransactionVerboseData) GetHash() string {
return "" return ""
} }
func (x *RpcTransactionVerboseData) GetSize() uint64 { func (x *RpcTransactionVerboseData) GetMass() uint64 {
if x != nil { if x != nil {
return x.Size return x.Mass
} }
return 0 return 0
} }
@ -5337,7 +5350,7 @@ var file_rpc_proto_rawDesc = []byte{
0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52,
0x0b, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0xec, 0x01, 0x0a, 0x0b, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x8c, 0x02, 0x0a,
0x13, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x13, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49,
0x6e, 0x70, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73,
0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
@ -5347,7 +5360,9 @@ var file_rpc_proto_rawDesc = []byte{
0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x09, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69,
0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e,
0x0a, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4b,
0x0a, 0x0b, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x0a, 0x0b, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e,
0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
@ -5392,8 +5407,8 @@ var file_rpc_proto_rawDesc = []byte{
0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x73, 0x73,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x6d, 0x61, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09,
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62,

View File

@ -61,6 +61,7 @@ message RpcTransactionInput {
RpcOutpoint previousOutpoint = 1; RpcOutpoint previousOutpoint = 1;
string signatureScript = 2; string signatureScript = 2;
uint64 sequence = 3; uint64 sequence = 3;
uint32 sigOpCount = 5;
RpcTransactionInputVerboseData verboseData = 4; RpcTransactionInputVerboseData verboseData = 4;
} }
@ -90,7 +91,7 @@ message RpcUtxoEntry {
message RpcTransactionVerboseData{ message RpcTransactionVerboseData{
string transactionId = 1; string transactionId = 1;
string hash = 2; string hash = 2;
uint64 size = 3; uint64 mass = 4;
string blockHash = 12; string blockHash = 12;
uint64 blockTime = 14; uint64 blockTime = 14;
} }

View File

@ -146,6 +146,9 @@ func (x *RpcTransactionInput) toAppMessage() (*appmessage.RPCTransactionInput, e
if x == nil { if x == nil {
return nil, errors.Wrapf(errorNil, "RpcTransactionInput is nil") return nil, errors.Wrapf(errorNil, "RpcTransactionInput is nil")
} }
if x.SigOpCount > math.MaxUint8 {
return nil, errors.New("TransactionInput SigOpCount > math.MaxUint8")
}
outpoint, err := x.PreviousOutpoint.toAppMessage() outpoint, err := x.PreviousOutpoint.toAppMessage()
if err != nil { if err != nil {
return nil, err return nil, err
@ -163,6 +166,7 @@ func (x *RpcTransactionInput) toAppMessage() (*appmessage.RPCTransactionInput, e
SignatureScript: x.SignatureScript, SignatureScript: x.SignatureScript,
Sequence: x.Sequence, Sequence: x.Sequence,
VerboseData: verboseData, VerboseData: verboseData,
SigOpCount: byte(x.SigOpCount),
}, nil }, nil
} }
@ -179,6 +183,7 @@ func (x *RpcTransactionInput) fromAppMessage(message *appmessage.RPCTransactionI
SignatureScript: message.SignatureScript, SignatureScript: message.SignatureScript,
Sequence: message.Sequence, Sequence: message.Sequence,
VerboseData: verboseData, VerboseData: verboseData,
SigOpCount: uint32(message.SigOpCount),
} }
} }
@ -291,7 +296,7 @@ func (x *RpcTransactionVerboseData) toAppMessage() (*appmessage.RPCTransactionVe
return &appmessage.RPCTransactionVerboseData{ return &appmessage.RPCTransactionVerboseData{
TransactionID: x.TransactionId, TransactionID: x.TransactionId,
Hash: x.Hash, Hash: x.Hash,
Size: x.Size, Mass: x.Mass,
BlockHash: x.BlockHash, BlockHash: x.BlockHash,
BlockTime: x.BlockTime, BlockTime: x.BlockTime,
}, nil }, nil
@ -301,7 +306,7 @@ func (x *RpcTransactionVerboseData) fromAppMessage(message *appmessage.RPCTransa
*x = RpcTransactionVerboseData{ *x = RpcTransactionVerboseData{
TransactionId: message.TransactionID, TransactionId: message.TransactionID,
Hash: message.Hash, Hash: message.Hash,
Size: message.Size, Mass: message.Mass,
BlockHash: message.BlockHash, BlockHash: message.BlockHash,
BlockTime: message.BlockTime, BlockTime: message.BlockTime,
} }

View File

@ -95,7 +95,7 @@ func waitForPayeeToReceiveBlock(t *testing.T, payeeBlockAddedChan chan *appmessa
func generateTx(t *testing.T, firstBlockCoinbase *externalapi.DomainTransaction, payer, payee *appHarness) *appmessage.MsgTx { func generateTx(t *testing.T, firstBlockCoinbase *externalapi.DomainTransaction, payer, payee *appHarness) *appmessage.MsgTx {
txIns := make([]*appmessage.TxIn, 1) txIns := make([]*appmessage.TxIn, 1)
txIns[0] = appmessage.NewTxIn(appmessage.NewOutpoint(consensushashing.TransactionID(firstBlockCoinbase), 0), []byte{}, 0) txIns[0] = appmessage.NewTxIn(appmessage.NewOutpoint(consensushashing.TransactionID(firstBlockCoinbase), 0), []byte{}, 0, 1)
payeeAddress, err := util.DecodeAddress(payee.miningAddress, util.Bech32PrefixKaspaSim) payeeAddress, err := util.DecodeAddress(payee.miningAddress, util.Bech32PrefixKaspaSim)
if err != nil { if err != nil {

View File

@ -161,7 +161,7 @@ func buildTransactionForUTXOIndexTest(t *testing.T, entry *appmessage.UTXOsByAdd
} }
txIns := make([]*appmessage.TxIn, 1) txIns := make([]*appmessage.TxIn, 1)
txIns[0] = appmessage.NewTxIn(appmessage.NewOutpoint(transactionID, entry.Outpoint.Index), []byte{}, 0) txIns[0] = appmessage.NewTxIn(appmessage.NewOutpoint(transactionID, entry.Outpoint.Index), []byte{}, 0, 1)
payeeAddress, err := util.DecodeAddress(miningAddress1, util.Bech32PrefixKaspaSim) payeeAddress, err := util.DecodeAddress(miningAddress1, util.Bech32PrefixKaspaSim)
if err != nil { if err != nil {