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

View File

@ -90,16 +90,18 @@ type TxIn struct {
PreviousOutpoint Outpoint
SignatureScript []byte
Sequence uint64
SigOpCount byte
}
// NewTxIn returns a new kaspa transaction input with the provided
// previous outpoint point and signature script with a default sequence of
// MaxTxInSequenceNum.
func NewTxIn(prevOut *Outpoint, signatureScript []byte, sequence uint64) *TxIn {
func NewTxIn(prevOut *Outpoint, signatureScript []byte, sequence uint64, sigOpCount byte) *TxIn {
return &TxIn{
PreviousOutpoint: *prevOut,
SignatureScript: signatureScript,
Sequence: sequence,
SigOpCount: sigOpCount,
}
}
@ -206,6 +208,7 @@ func (msg *MsgTx) Copy() *MsgTx {
PreviousOutpoint: newOutpoint,
SignatureScript: newScript,
Sequence: oldTxIn.Sequence,
SigOpCount: oldTxIn.SigOpCount,
}
// 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.
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) {
t.Errorf("NewTxIn: wrong prev outpoint - got %v, want %v",
spew.Sprint(&txIn.PreviousOutpoint),

View File

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

View File

@ -130,6 +130,10 @@ type fakeRelayInvsContext struct {
rwLock sync.RWMutex
}
func (f *fakeRelayInvsContext) PopulateMass(*externalapi.DomainTransaction) {
panic("implement me")
}
func (f *fakeRelayInvsContext) DeleteStagingConsensus() error {
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/estimatedsize"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/app/appmessage"
@ -114,10 +113,11 @@ func (ctx *Context) PopulateTransactionWithVerboseData(
return err
}
ctx.Domain.Consensus().PopulateMass(domainTransaction)
transaction.VerboseData = &appmessage.RPCTransactionVerboseData{
TransactionID: consensushashing.TransactionID(domainTransaction).String(),
Hash: consensushashing.TransactionHash(domainTransaction).String(),
Size: estimatedsize.TransactionEstimatedSerializedSize(domainTransaction),
Mass: domainTransaction.Mass,
}
if domainBlockHeader != nil {
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"`
MinimumSignatures uint32 `protobuf:"varint,3,opt,name=minimumSignatures,proto3" json:"minimumSignatures,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() {
@ -364,6 +364,7 @@ type TransactionInput struct {
PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,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"`
SigOpCount uint32 `protobuf:"varint,4,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
}
func (x *TransactionInput) Reset() {
@ -419,6 +420,13 @@ func (x *TransactionInput) GetSequence() uint64 {
return 0
}
func (x *TransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type Outpoint struct {
state protoimpl.MessageState
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,
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,
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,
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,
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,
@ -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,
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,
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,
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,
@ -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,
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, 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, 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,

View File

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

View File

@ -1,12 +1,13 @@
package serialization
import (
"math"
"github.com/golang/protobuf/proto"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization/protoserialization"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/pkg/errors"
"math"
)
// 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) {
if protoInput.SigOpCount > math.MaxUint8 {
return nil, errors.New("TransactionInput SigOpCount > math.MaxUint8")
}
outpoint, err := outpointFromProto(protoInput.PreviousOutpoint)
if err != nil {
return nil, err
@ -199,6 +204,7 @@ func transactionInputFromProto(protoInput *protoserialization.TransactionInput)
PreviousOutpoint: *outpoint,
SignatureScript: protoInput.SignatureScript,
Sequence: protoInput.Sequence,
SigOpCount: byte(protoInput.SigOpCount),
}, nil
}
@ -207,6 +213,7 @@ func transactionInputToProto(input *externalapi.DomainTransactionInput) *protose
PreviousOutpoint: outpointToProto(&input.PreviousOutpoint),
SignatureScript: input.SignatureScript,
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
0, // This is a fake value, because it's irrelevant for the signature
)
partiallySignedTransaction.Tx.Inputs[i].SigOpCount = byte(len(partiallySignedInput.PubKeySignaturePairs))
}
signed := false

View File

@ -96,8 +96,7 @@ func (s *consensus) ValidateTransactionAndPopulateWithConsensusData(transaction
if err != nil {
return err
}
return s.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee(
return s.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime)
}
@ -556,3 +555,7 @@ func (s *consensus) EstimateNetworkHashesPerSecond(startHash *externalapi.Domain
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"`
SignatureScript []byte `protobuf:"bytes,2,opt,name=signatureScript,proto3" json:"signatureScript,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() {
@ -388,6 +389,13 @@ func (x *DbTransactionInput) GetSequence() uint64 {
return 0
}
func (x *DbTransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type DbOutpoint struct {
state protoimpl.MessageState
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,
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,
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,
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,
@ -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,
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,
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,
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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,13 +131,14 @@ type DomainTransactionInput struct {
PreviousOutpoint DomainOutpoint
SignatureScript []byte
Sequence uint64
SigOpCount byte
UTXOEntry UTXOEntry
}
// If this doesn't compile, it means the type definition has been changed, so it's
// 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
func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool {
@ -157,6 +158,10 @@ func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool {
return false
}
if input.SigOpCount != other.SigOpCount {
return false
}
if input.UTXOEntry != nil && other.UTXOEntry != nil && !input.UTXOEntry.Equal(other.UTXOEntry) {
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(),
SignatureScript: signatureScriptClone,
Sequence: input.Sequence,
SigOpCount: input.SigOpCount,
UTXOEntry: input.UTXOEntry,
}
}

View File

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

View File

@ -10,6 +10,7 @@ type TransactionValidator interface {
ValidateTransactionInIsolation(transaction *externalapi.DomainTransaction) error
ValidateTransactionInContextIgnoringUTXO(stagingArea *StagingArea, tx *externalapi.DomainTransaction,
povBlockHash *externalapi.DomainHash) error
ValidateTransactionInContextAndPopulateMassAndFee(stagingArea *StagingArea,
ValidateTransactionInContextAndPopulateFee(stagingArea *StagingArea,
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 bb.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee(
return bb.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, model.VirtualBlockHash, virtualSelectedParentMedianTime)
}

View File

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

View File

@ -5,7 +5,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"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/subnetworks"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
@ -34,11 +33,6 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return err
}
err = v.checkBlockSize(block)
if err != nil {
return err
}
err = v.checkBlockContainsAtLeastOneTransaction(block)
if err != nil {
return err
@ -69,6 +63,11 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return err
}
err = v.checkBlockMass(block)
if err != nil {
return err
}
err = v.checkBlockDuplicateTransactions(block)
if err != nil {
return err
@ -215,16 +214,18 @@ func (v *blockValidator) validateGasLimit(block *externalapi.DomainBlock) error
return nil
}
func (v *blockValidator) checkBlockSize(block *externalapi.DomainBlock) error {
size := uint64(0)
size += v.headerEstimatedSerializedSize(block.Header)
func (v *blockValidator) checkBlockMass(block *externalapi.DomainBlock) error {
mass := uint64(0)
mass += v.headerEstimatedSerializedSize(block.Header)
for _, tx := range block.Transactions {
sizeBefore := size
size += estimatedsize.TransactionEstimatedSerializedSize(tx)
if size > v.maxBlockSize || size < sizeBefore {
return errors.Wrapf(ruleerrors.ErrBlockSizeTooHigh, "block excceeded the size limit of %d",
v.maxBlockSize)
for _, transaction := range block.Transactions {
v.transactionValidator.PopulateMass(transaction)
massBefore := mass
mass += transaction.Mass
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) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockSize")
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockMass")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := initBlockWithInvalidBlockSize(consensusConfig, tc)
block, _, err := initBlockWithInvalidBlockMass(consensusConfig, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
}
@ -1046,14 +1045,14 @@ func TestBlockSize(t *testing.T) {
tc.BlockStore().Stage(stagingArea, blockHash, block)
err = tc.BlockValidator().ValidateBodyInIsolation(stagingArea, blockHash)
if err == nil || !errors.Is(err, ruleerrors.ErrBlockSizeTooHigh) {
t.Fatalf("ValidateBodyInIsolationTest: TestBlockSize:"+
" Unexpected error: Expected to: %v, but got : %v", ruleerrors.ErrBlockSizeTooHigh, err)
if err == nil || !errors.Is(err, ruleerrors.ErrBlockMassTooHigh) {
t.Fatalf("ValidateBodyInIsolationTest: TestBlockMass:"+
" 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{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,
@ -1062,11 +1061,12 @@ func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi
}
prevOutTxID := &externalapi.DomainTransactionID{}
prevOutPoint := externalapi.DomainOutpoint{TransactionID: *prevOutTxID, Index: 1}
bigSignatureScript := bytes.Repeat([]byte("01"), 25000)
bigSignatureScript := bytes.Repeat([]byte("01"), 500000)
txInput := externalapi.DomainTransactionInput{
PreviousOutpoint: prevOutPoint,
SignatureScript: bigSignatureScript,
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 10,
UTXOEntry: utxo.NewUTXOEntry(
100_000_000,
&externalapi.ScriptPublicKey{},
@ -1079,7 +1079,7 @@ func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 2}, Version: 0}}, {uint64(0xFFFF),
&externalapi.ScriptPublicKey{Script: []byte{1, 3}, Version: 0}}},
Payload: []byte{0x01},
Payload: []byte{},
}
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})

View File

@ -1,12 +1,12 @@
package blockvalidator
import (
"github.com/kaspanet/kaspad/util/difficulty"
"math/big"
"time"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/util/difficulty"
)
// blockValidator exposes a set of validation classes, after which
@ -17,7 +17,7 @@ type blockValidator struct {
genesisHash *externalapi.DomainHash
enableNonNativeSubnetworks bool
powMaxBits uint32
maxBlockSize uint64
maxBlockMass uint64
mergeSetSizeLimit uint64
maxBlockParents model.KType
timestampDeviationTolerance int
@ -48,7 +48,7 @@ func New(powMax *big.Int,
skipPoW bool,
genesisHash *externalapi.DomainHash,
enableNonNativeSubnetworks bool,
maxBlockSize uint64,
maxBlockMass uint64,
mergeSetSizeLimit uint64,
maxBlockParents model.KType,
timestampDeviationTolerance int,
@ -82,7 +82,7 @@ func New(powMax *big.Int,
genesisHash: genesisHash,
enableNonNativeSubnetworks: enableNonNativeSubnetworks,
powMaxBits: difficulty.BigToCompact(powMax),
maxBlockSize: maxBlockSize,
maxBlockMass: maxBlockMass,
mergeSetSizeLimit: mergeSetSizeLimit,
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)
} else {
log.Tracef("Validating transaction %s in block %s", transactionID, blockHash)
err = csm.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee(
err = csm.transactionValidator.ValidateTransactionInContextAndPopulateFee(
stagingArea, transaction, blockHash, selectedParentPastMedianTime)
if err != nil {
if !errors.As(err, &(ruleerrors.RuleError{})) {
@ -249,14 +249,6 @@ func (csm *consensusStateManager) maybeAcceptTransaction(stagingArea *model.Stag
return false, accumulatedMassBefore, nil
}
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)
@ -268,27 +260,6 @@ func (csm *consensusStateManager) maybeAcceptTransaction(stagingArea *model.Stag
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
func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (
externalapi.ReadOnlyUTXOSetIterator, error) {

View File

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

View File

@ -118,7 +118,7 @@ func (csm *consensusStateManager) importPruningPoint(
continue
}
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)
if err != nil {
return err

View File

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

View File

@ -2,47 +2,99 @@ package transactionvalidator
import (
"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/txscript"
)
func (v *transactionValidator) transactionMassStandalonePart(tx *externalapi.DomainTransaction) uint64 {
size := estimatedsize.TransactionEstimatedSerializedSize(tx)
func (v *transactionValidator) PopulateMass(transaction *externalapi.DomainTransaction) {
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)
for _, output := range tx.Outputs {
for _, output := range transaction.Outputs {
totalScriptPubKeySize += 2 //output.ScriptPublicKey.Version (uint16)
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) {
return 0, nil
return 0
}
standaloneMass := v.transactionMassStandalonePart(tx)
sigOpsCount := uint64(0)
var missingOutpoints []*externalapi.DomainOutpoint
size := uint64(0)
size += 2 // Txn Version
size += 8 // number of inputs (uint64)
for _, input := range tx.Inputs {
utxoEntry := input.UTXOEntry
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)
size += transactionInputEstimatedSerializedSize(input)
}
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
}
// ValidateTransactionInContextAndPopulateMassAndFee validates the transaction against its referenced UTXO, and
// populates its mass and fee fields.
// ValidateTransactionInContextAndPopulateFee validates the transaction against its referenced UTXO, and
// populates its fee field.
//
// Note: if the function fails, there's no guarantee that the transaction mass and fee fields will remain unaffected.
func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee(stagingArea *model.StagingArea,
// Note: if the function fails, there's no guarantee that the transaction fee field will remain unaffected.
func (v *transactionValidator) ValidateTransactionInContextAndPopulateFee(stagingArea *model.StagingArea,
tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error {
err := v.checkTransactionCoinbaseMaturity(stagingArea, povBlockHash, tx)
@ -94,12 +94,12 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee
return err
}
err = v.validateTransactionScripts(tx)
err = v.validateTransactionSigOpCounts(tx)
if err != nil {
return err
}
tx.Mass, err = v.transactionMass(tx)
err = v.validateTransactionScripts(tx)
if err != nil {
return err
}
@ -399,3 +399,21 @@ func (v *transactionValidator) sequenceLockActive(sequenceLock *sequenceLock, bl
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"
)
// ValidateTransactionInIsolation validates the parts of the transaction that can be validated context-free
func (v *transactionValidator) ValidateTransactionInIsolation(tx *externalapi.DomainTransaction) error {
err := v.checkTransactionInputCount(tx)
if err != nil {

View File

@ -20,10 +20,10 @@ type txSubnetworkData struct {
payload []byte
}
func TestValidateTransactionInIsolation(t *testing.T) {
func TestValidateTransactionInIsolationAndPopulateMass(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateTransactionInIsolation")
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateTransactionInIsolationAndPopulateMass")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@ -111,7 +111,7 @@ func TestValidateTransactionInIsolation(t *testing.T) {
err := tc.TransactionValidator().ValidateTransactionInIsolation(tx)
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{},
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
})
}

View File

@ -32,7 +32,7 @@ func (mdf *mocPastMedianTimeManager) PastMedianTime(*model.StagingArea, *externa
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) {
factory := consensus.NewFactory()
@ -42,7 +42,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
return pastMedianManager
})
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
"TestValidateTransactionInContextAndPopulateMassAndFee")
"TestValidateTransactionInContextAndPopulateFee")
if err != nil {
t.Fatalf("Failed create a NewTestConsensus: %s", err)
}
@ -76,6 +76,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS
scriptPublicKey,
@ -86,6 +87,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS
scriptPublicKey,
@ -96,6 +98,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.SequenceLockTimeIsSeconds,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
100000000, // 1 KAS
scriptPublicKey,
@ -106,12 +109,24 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(
constants.MaxSompi,
scriptPublicKey,
true,
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{
Value: 100000000, // 1 KAS
@ -167,6 +182,13 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
SubnetworkID: subnetworks.SubnetworkIDRegistry,
Gas: 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()
@ -240,19 +262,27 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
isValid: false,
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 {
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 err != nil {
t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateMassAndFee"+
t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateFee"+
" on test '%v': %+v", test.name, err)
}
} else {
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)
}
}
@ -335,16 +365,18 @@ func TestSigningTwoInputs(t *testing.T) {
TransactionID: *consensushashing.TransactionID(block2.Transactions[0]),
Index: 0,
},
Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
},
{
PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: *consensushashing.TransactionID(block3.Transactions[0]),
Index: 0,
},
Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
},
},
Outputs: []*externalapi.DomainTransactionOutput{{
@ -459,16 +491,18 @@ func TestSigningTwoInputsECDSA(t *testing.T) {
TransactionID: *consensushashing.TransactionID(block2.Transactions[0]),
Index: 0,
},
Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block2TxOut.Value, block2TxOut.ScriptPublicKey, true, 0),
},
{
PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: *consensushashing.TransactionID(block3.Transactions[0]),
Index: 0,
},
Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
Sequence: constants.MaxTxInSequenceNum,
SigOpCount: 1,
UTXOEntry: utxo.NewUTXOEntry(block3TxOut.Value, block3TxOut.ScriptPublicKey, true, 0),
},
},
Outputs: []*externalapi.DomainTransactionOutput{{

View File

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

View File

@ -139,6 +139,9 @@ var (
// a Payload
ErrInvalidPayload = newRuleError("ErrInvalidPayload")
// ErrWrongSigOpCount transaction input specifies an incorrect SigOpCount
ErrWrongSigOpCount = newRuleError("ErrWrongSigOpCount")
// ErrSubnetwork indicates that a block doesn't adhere to the subnetwork
// registry rules
ErrSubnetworkRegistry = newRuleError("ErrSubnetworkRegistry")
@ -161,9 +164,9 @@ var (
// In the same block
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.
ErrBlockSizeTooHigh = newRuleError("ErrBlockSizeTooHigh")
ErrBlockMassTooHigh = newRuleError("ErrBlockMassTooHigh")
ErrKnownInvalid = newRuleError("ErrKnownInvalid")

View File

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

View File

@ -108,86 +108,86 @@ func TestCalculateSignatureHashSchnorr(t *testing.T) {
// sigHashAll
{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,
modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "0bd2947383101f9708d94d5799626c69c1b8472d2de66523c90c4a674e99cc51"},
expectedSignatureHash: "3ee15a1f5d3827b9c3bca740ebbe422a8d07fbde287944f855da26c06782d38b"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "ae69aa1372e958f069bf52d2628ead7ee789f195340b615ff0bcb6f01a995810"},
expectedSignatureHash: "1794d1d074a587678174223788bea272d092a6155f031686b85caf11595ff6d8"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "51295575e7efc1fe1c2e741ade49089e3d780d15d26e9a0b18b3d90e35caf795"},
expectedSignatureHash: "8c580bd47a220e4ab6f343dde74a23f9e4b3971b2b519b0ed0ad34d682aa85d3"},
{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,
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,
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,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"},
expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
// sigHashNone
{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,
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,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "72c07c152a3792fb863d2de219ab4e863fe6779dc970a5c3958e26b3a3b9f139"},
expectedSignatureHash: "52b3888a3680c79712b53c4010b7cdebd158e09b7574d95b846ba9989946c38b"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"},
expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{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,
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,
modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "7a879d339c9b948c5264f1c0b8463f551221b2dcd575623f178cbbfcf7e01987"},
expectedSignatureHash: "382e8196e1fe34ccc4c3004ad6e6d4c41b81b8a5dd6de24fe51065a1970ef00b"},
// sigHashSingle
{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,
modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "92189a32391ca50a454d1853efed55acb1c49993911a1201df9891c866c483ee"},
expectedSignatureHash: "ca882be7c6c3ae37badda62c9277be0808160d65a6a89feb514e41ed7a9658f0"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
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,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "765e2289df98b3a5269f112d4b36d57fe32c74d42e04a3046c6a3c8dd78a4121"},
expectedSignatureHash: "7dec3b5b7b5ccd3f82f93c6c08cd05acecb970d4a4d127fcd87a11d7e0dd96e3"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
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,
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"},
expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"},
expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{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,
expectedSignatureHash: "afc05dd6b4a530cc3a4d7d23126548bd1f31c793e9282cbbfa27ff5566219501"},
expectedSignatureHash: "26a05df8e562f5c43cacab9a8126ae2da77e2137f8c28d13a330cd3d2b37d56b"},
// subnetwork transaction
{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,
modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "0d3bc5914da8dc8df081945fea1255359f380ca9baa8b31dfb3657c1e3c6038a"},
expectedSignatureHash: "0366d1f0ab7a2150cd1b80b8f8944e7f6a42a38b846f2610adc4106fe70696ec"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "70abe9f947d0a0f5d735f9a063db8af41fe5902940f2693a1782119063097094"},
expectedSignatureHash: "19054bbf6dc75936dd018983373afd623a292ad1f39774cd1783b58074c3caa7"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "571a0b7ea905b7a6ff7ab825b72d23f911bac0bfaa7c4c97a4887a3d090925d4"},
expectedSignatureHash: "2fbfa5d3d24673b2e3530c3b268b58ecb6e7e34116d5c18849c27b0e7b6bfe4c"},
}
for _, test := range tests {
@ -230,86 +230,86 @@ func TestCalculateSignatureHashECDSA(t *testing.T) {
// sigHashAll
{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,
modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "8fb5304e181b003e0c123ea6f6677abc3704feec47054e8a1c218b827bf57ca0"},
expectedSignatureHash: "9ba940467c07b4254f913a95398dc6f9fac0915e0dfe9560c58dfc1f87977c08"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "180cb36454aa80822694decde4fc711104e35a4bddf92286a83877f2b8d0aabb"},
expectedSignatureHash: "ba413a6ef1101c4a4995ac30a9013fe5591ef5f6dd8d7aabaa5dd8cb74d4d765"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "5b5f1c42a3c3c16bb4922777e2963c00e6a2cce39afa1980d2288053378f9632"},
expectedSignatureHash: "a471958e25168ab6671a76629d6f83b7f197a22972b333ebfa55d62dcc0ef065"},
{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,
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,
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,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "9473ffbe0db4914f2cd8fe5d67479224a02eb031882d9170b785d0d2c7bfcd1b"},
expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
// sigHashNone
{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,
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,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "57d76e2568cd3fc3426b4f8836fe900a2d20e740fad744949126651fd549f75e"},
expectedSignatureHash: "155e020f420fdaf62b31ccb3a13b6cb684c3db9ff85fc7062bb7e6a0653c7057"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "6e427f26e4a9c1a7fc556a8aabdedb8799a897bc5d42a0a18615e5a0f7639d8f"},
expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{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,
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,
modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "f2cd43d0d047cdcfbf8b6e12a86cfbf250f1e2c34dc5e631675a5f5b867bd9e6"},
expectedSignatureHash: "bdce98b53163b42175f4e885f50e8a44821159fc05d7756e3870c5f91df2be2f"},
// sigHashSingle
{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,
modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "c2c7e77516a15f0f47f886b14cc47af2045eea15f176a9a560a9d47d8866958f"},
expectedSignatureHash: "394192ce7faee4f5055939c6fa3bf41a3008ec29e667d60bd5203987850debd4"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
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,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "2034eec2acc08c49d3896cc1bda214904ca850fc5989518885465b5a3154ee7f"},
expectedSignatureHash: "55b1a9f7ee395ea37a8a6da804c9a654216364a42e37d329c5dc69c349369825"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
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,
expectedSignatureHash: "84ae3bb03202efc587d97e5aea7b80581b82242b969e6dea13b8daa32d24c0c1"},
expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "84ae3bb03202efc587d97e5aea7b80581b82242b969e6dea13b8daa32d24c0c1"},
expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{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,
expectedSignatureHash: "652c8cd0ac050e41aad347ea09ee788360eec70908ba22fe5bba5bdde49b8ae1"},
expectedSignatureHash: "84b56500814e4c7de8569ef6a5dfc269ca35db3160adaebedd92e68fe9d2c02b"},
// subnetwork transaction
{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,
modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "d5f3993aa8b7f47df52f78f2be9965f928c9cca9ac9e9542f1190b9d5ed6c17d"},
expectedSignatureHash: "bad87ce0a6d5fade1bb9eb5de572a3a9904e6d0ef5d627b97c69380818c1ad6f"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "e74d4a9fa5cdf476299ebdfa03f3c8021a157f814731ea11f6a6d606dc5cd439"},
expectedSignatureHash: "54bdd33d4c8ea1baac6e92a129ad8a6bb90803b7b21387cc4ec9640752f4bb61"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "ca8bf9bc42cda2ec3ce8bee090011072e56ff4d0d8616d5c20cefe5f84d7fb37"},
expectedSignatureHash: "e71d0226c6c0cc26e0a99146f597ff9b9b51406f64854235b18f741d4c87eac4"},
}
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
for i, pop := range pops {
switch pop.opcode.value {
case OpCheckSig:
fallthrough
case OpCheckSigVerify:
case OpCheckSig, OpCheckSigVerify, OpCheckSigECDSA:
nSigs++
case OpCheckMultiSig:
fallthrough
case OpCheckMultiSigVerify:
case OpCheckMultiSig, OpCheckMultiSigVerify, OpCheckMultiSigECDSA:
// If we are being precise then look for familiar
// patterns for multisig, for now all we recognize is
// OP_1 - OP_16 to signify the number of pubkeys.

View File

@ -1,8 +1,9 @@
package dagconfig
import (
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"time"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
)
// The documentation refers to the following constants which aren't explicated in the code:
@ -23,30 +24,32 @@ import (
const (
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
defaultMaxBlockSize = 50_000
// defaultMaxBlockParents is the number of blocks any block can point to.
// Should be about d/defaultTargetTimePerBlock where d is a bound on the round trip time of a block.
defaultMaxBlockParents = 10
defaultMaxBlockMass = 500_000
// defaultMassPerTxByte, defaultMassPerScriptPubKeyByte and defaultMassPerSigOp define the number of grams per
// transaction byte, script pub key byte and sig op respectively.
// These values are used when calculating a transactions mass.
defaultMassPerTxByte = 1
defaultMassPerScriptPubKeyByte = 10
defaultMassPerSigOp = 10000
// 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 = 1000
defaultMaxMassAcceptedByBlock = 500_000
defaultBaseSubsidy = 50 * constants.SompiPerKaspa
defaultCoinbasePayloadScriptPublicKeyMaxLength = 150
defaultMassPerSigOp = 1000
// defaultMaxBlockParents is the number of blocks any block can point to.
// Should be about d/defaultTargetTimePerBlock where d is a bound on the round trip time of a block.
defaultMaxBlockParents = 10
// defaultGHOSTDAGK is a bound on the number of blue blocks in the anticone of a blue block. Approximates the maximal
// 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
// 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.
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
// target.
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 uint64
// MaxBlockSize is the maximum size in bytes a block is allowed
MaxBlockSize uint64
// MaxBlockMass is the maximum mass a block is allowed
MaxBlockMass uint64
// MaxBlockParents is the maximum number of blocks a block is allowed to point to
MaxBlockParents model.KType
@ -171,9 +171,6 @@ type Params struct {
// MergeSetSizeLimit is the maximum number of blocks in a block's merge set
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 uint8
@ -242,13 +239,12 @@ var MainnetParams = Params{
DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize,
MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
}
@ -299,13 +295,12 @@ var TestnetParams = Params{
DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize,
MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
}
@ -360,13 +355,12 @@ var SimnetParams = Params{
DisableDifficultyAdjustment: true,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize,
MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
}
@ -417,13 +411,12 @@ var DevnetParams = Params{
DisableDifficultyAdjustment: false,
MaxCoinbasePayloadLength: defaultMaxCoinbasePayloadLength,
MaxBlockSize: defaultMaxBlockSize,
MaxBlockMass: defaultMaxBlockMass,
MaxBlockParents: defaultMaxBlockParents,
MassPerTxByte: defaultMassPerTxByte,
MassPerScriptPubKeyByte: defaultMassPerScriptPubKeyByte,
MassPerSigOp: defaultMassPerSigOp,
MergeSetSizeLimit: defaultMergeSetSizeLimit,
MaxMassAcceptedByBlock: defaultMaxMassAcceptedByBlock,
BaseSubsidy: defaultBaseSubsidy,
CoinbasePayloadScriptPublicKeyMaxLength: defaultCoinbasePayloadScriptPublicKeyMaxLength,
}

View File

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

View File

@ -3,11 +3,12 @@ package mempool
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/processes/transactionvalidator"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"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/util"
)
@ -36,10 +37,9 @@ const (
// (1 + 15*74 + 3) + (15*34 + 3) + 23 = 1650
maximumStandardSignatureScriptSize = 1650
// maximumStandardTransactionSize is the maximum size allowed for transactions that
// are considered standard and will therefore be relayed and considered
// for mining.
maximumStandardTransactionSize = 100000
// maximumStandardTransactionMass is the maximum mass allowed for transactions that
// are considered standard and will therefore be relayed and considered for mining.
maximumStandardTransactionMass = 100000
)
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
// size of a transaction. This also helps mitigate CPU exhaustion
// attacks.
serializedLength := estimatedsize.TransactionEstimatedSerializedSize(transaction)
if serializedLength > maximumStandardTransactionSize {
str := fmt.Sprintf("transaction size of %d is larger than max allowed size of %d",
serializedLength, maximumStandardTransactionSize)
if transaction.Mass > maximumStandardTransactionMass {
str := fmt.Sprintf("transaction mass of %d is larger than max allowed size of %d",
transaction.Mass, maximumStandardTransactionMass)
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
// breakdown, the minimum size of a p2pk input script is 148 bytes. So
// 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
// 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(serializedSize)
minimumFee := mp.minimumRequiredTransactionRelayFee(transaction.Mass)
if transaction.Fee < minimumFee {
str := fmt.Sprintf("transaction %s has %d fees which is under the required amount of %d",
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
// transaction with the passed serialized size to be accepted into the memory
// pool and relayed.
func (mp *mempool) minimumRequiredTransactionRelayFee(serializedSize uint64) uint64 {
// transaction with the passed mass to be accepted into the mampool and relayed.
func (mp *mempool) minimumRequiredTransactionRelayFee(mass uint64) uint64 {
// Calculate the minimum fee for a transaction to be allowed into the
// mempool and relayed by scaling the base fee. MinimumRelayTransactionFee is in
// sompi/kB so multiply by serializedSize (which is in bytes) and
// divide by 1000 to get minimum sompis.
minimumFee := (serializedSize * uint64(mp.config.MinimumRelayTransactionFee)) / 1000
// sompi/kg so multiply by mass (which is in grams) and divide by 1000 to get minimum sompis.
minimumFee := (mass * uint64(mp.config.MinimumRelayTransactionFee)) / 1000
if minimumFee == 0 && mp.config.MinimumRelayTransactionFee > 0 {
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",
maximumStandardTransactionSize,
maximumStandardTransactionMass,
defaultMinimumRelayTransactionFee,
100000,
},
{
"max standard tx size with max sompi relay fee",
maximumStandardTransactionSize,
maximumStandardTransactionMass,
util.MaxSompi,
util.MaxSompi,
},
@ -244,7 +244,7 @@ func TestCheckTransactionStandardInIsolation(t *testing.T) {
name: "Transaction size is too large",
tx: &externalapi.DomainTransaction{Version: 0, Inputs: []*externalapi.DomainTransactionInput{&dummyTxIn}, Outputs: []*externalapi.DomainTransactionOutput{{
Value: 0,
ScriptPublicKey: &externalapi.ScriptPublicKey{bytes.Repeat([]byte{0x00}, maximumStandardTransactionSize+1), 0},
ScriptPublicKey: &externalapi.ScriptPublicKey{bytes.Repeat([]byte{0x00}, maximumStandardTransactionMass+1), 0},
}}},
height: 300000,
isStandard: false,

View File

@ -18,11 +18,13 @@ const (
defaultOrphanExpireIntervalSeconds uint64 = 60
defaultOrphanExpireScanIntervalSeconds uint64 = 10
defaultMaximumOrphanTransactionSize = 100000
defaultMaximumOrphanTransactionMass = 100000
// defaultMaximumOrphanTransactionCount should remain small as long as we have recursion in
// removeOrphans when removeRedeemers = true
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)
// Standard transaction version range might be different from what consensus accepts, therefore
@ -41,10 +43,10 @@ type Config struct {
TransactionExpireScanIntervalSeconds uint64
OrphanExpireIntervalDAAScore uint64
OrphanExpireScanIntervalDAAScore uint64
MaximumOrphanTransactionSize uint64
MaximumOrphanTransactionMass uint64
MaximumOrphanTransactionCount uint64
AcceptNonStandard bool
MaximumMassAcceptedByBlock uint64
MaximumMassPerBlock uint64
MinimumRelayTransactionFee util.Amount
MinimumStandardTransactionVersion uint16
MaximumStandardTransactionVersion uint16
@ -61,10 +63,10 @@ func DefaultConfig(dagParams *dagconfig.Params) *Config {
TransactionExpireScanIntervalSeconds: defaultTransactionExpireScanIntervalSeconds,
OrphanExpireIntervalDAAScore: defaultOrphanExpireIntervalSeconds / targetBlocksPerSecond,
OrphanExpireScanIntervalDAAScore: defaultOrphanExpireScanIntervalSeconds / targetBlocksPerSecond,
MaximumOrphanTransactionSize: defaultMaximumOrphanTransactionSize,
MaximumOrphanTransactionMass: defaultMaximumOrphanTransactionMass,
MaximumOrphanTransactionCount: defaultMaximumOrphanTransactionCount,
AcceptNonStandard: dagParams.RelayNonStdTxs,
MaximumMassAcceptedByBlock: dagParams.MaxMassAcceptedByBlock,
MaximumMassPerBlock: dagParams.MaxBlockMass,
MinimumRelayTransactionFee: defaultMinimumRelayTransactionFee,
MinimumStandardTransactionVersion: defaultMinimumStandardTransactionVersion,
MaximumStandardTransactionVersion: defaultMaximumStandardTransactionVersion,

View File

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

View File

@ -16,6 +16,9 @@ func (mp *mempool) validateAndInsertTransaction(transaction *externalapi.DomainT
fmt.Sprintf("validateAndInsertTransaction %s", consensushashing.TransactionID(transaction)))
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)
if err != nil {
return nil, err

View File

@ -44,13 +44,6 @@ func (mp *mempool) validateTransactionInIsolation(transaction *externalapi.Domai
}
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 {
err := mp.checkTransactionStandardInContext(transaction)
if err != nil {

View File

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

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: messages.proto
package protowire
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = 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 {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache

View File

@ -11,8 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const _ = grpc.SupportPackageIsVersion6
// 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) {
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 {
return nil, err
}
@ -72,20 +71,13 @@ type P2PServer interface {
type UnimplementedP2PServer struct {
}
func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
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.
// Use of this interface is not recommended, as added methods to P2PServer will
// result in compilation errors.
type UnsafeP2PServer interface {
mustEmbedUnimplementedP2PServer()
}
func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) {
s.RegisterService(&P2P_ServiceDesc, srv)
func RegisterP2PServer(s *grpc.Server, srv P2PServer) {
s.RegisterService(&_P2P_serviceDesc, srv)
}
func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -114,10 +106,7 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil
}
// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service.
// 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{
var _P2P_serviceDesc = grpc.ServiceDesc{
ServiceName: "protowire.P2P",
HandlerType: (*P2PServer)(nil),
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) {
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 {
return nil, err
}
@ -190,20 +179,13 @@ type RPCServer interface {
type UnimplementedRPCServer struct {
}
func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
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.
// Use of this interface is not recommended, as added methods to RPCServer will
// result in compilation errors.
type UnsafeRPCServer interface {
mustEmbedUnimplementedRPCServer()
}
func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) {
s.RegisterService(&RPC_ServiceDesc, srv)
func RegisterRPCServer(s *grpc.Server, srv RPCServer) {
s.RegisterService(&_RPC_serviceDesc, srv)
}
func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -232,10 +214,7 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil
}
// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service.
// 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{
var _RPC_serviceDesc = grpc.ServiceDesc{
ServiceName: "protowire.RPC",
HandlerType: (*RPCServer)(nil),
Methods: []grpc.MethodDesc{},

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: p2p.proto
package protowire
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = 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 {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -335,6 +340,7 @@ type TransactionInput struct {
PreviousOutpoint *Outpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,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"`
SigOpCount uint32 `protobuf:"varint,4,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
}
func (x *TransactionInput) Reset() {
@ -390,6 +396,13 @@ func (x *TransactionInput) GetSequence() uint64 {
return 0
}
func (x *TransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
type Outpoint struct {
state protoimpl.MessageState
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,
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,
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,
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,
@ -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,
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, 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,
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,

View File

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

View File

@ -1,9 +1,10 @@
package protowire
import (
"math"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/pkg/errors"
"math"
)
func (x *KaspadMessage_Transaction) toAppMessage() (appmessage.Message, error) {
@ -64,11 +65,14 @@ func (x *TransactionInput) toAppMessage() (*appmessage.TxIn, error) {
if x == 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()
if err != nil {
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) {
@ -95,6 +99,7 @@ func (x *TransactionMessage) fromAppMessage(msgTx *appmessage.MsgTx) {
},
SignatureScript: input.SignatureScript,
Sequence: input.Sequence,
SigOpCount: uint32(input.SigOpCount),
}
}
@ -118,5 +123,4 @@ func (x *TransactionMessage) fromAppMessage(msgTx *appmessage.MsgTx) {
Gas: msgTx.Gas,
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) | | |
| signatureScript | [string](#string) | | |
| sequence | [uint64](#uint64) | | |
| sigOpCount | [uint32](#uint32) | | |
| verboseData | [RpcTransactionInputVerboseData](#protowire.RpcTransactionInputVerboseData) | | |
@ -727,6 +728,7 @@ SubmitTransactionRequestMessage submits a transaction to the mempool
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| transaction | [RpcTransaction](#protowire.RpcTransaction) | | |
| allowOrphan | [bool](#bool) | | |

View File

@ -10,13 +10,14 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: rpc.proto
package protowire
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@ -30,6 +31,10 @@ const (
_ = 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
const (
@ -501,6 +506,7 @@ type RpcTransactionInput struct {
PreviousOutpoint *RpcOutpoint `protobuf:"bytes,1,opt,name=previousOutpoint,proto3" json:"previousOutpoint,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"`
SigOpCount uint32 `protobuf:"varint,5,opt,name=sigOpCount,proto3" json:"sigOpCount,omitempty"`
VerboseData *RpcTransactionInputVerboseData `protobuf:"bytes,4,opt,name=verboseData,proto3" json:"verboseData,omitempty"`
}
@ -557,6 +563,13 @@ func (x *RpcTransactionInput) GetSequence() uint64 {
return 0
}
func (x *RpcTransactionInput) GetSigOpCount() uint32 {
if x != nil {
return x.SigOpCount
}
return 0
}
func (x *RpcTransactionInput) GetVerboseData() *RpcTransactionInputVerboseData {
if x != nil {
return x.VerboseData
@ -815,7 +828,7 @@ type RpcTransactionVerboseData struct {
TransactionId string `protobuf:"bytes,1,opt,name=transactionId,proto3" json:"transactionId,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"`
BlockTime uint64 `protobuf:"varint,14,opt,name=blockTime,proto3" json:"blockTime,omitempty"`
}
@ -866,9 +879,9 @@ func (x *RpcTransactionVerboseData) GetHash() string {
return ""
}
func (x *RpcTransactionVerboseData) GetSize() uint64 {
func (x *RpcTransactionVerboseData) GetMass() uint64 {
if x != nil {
return x.Size
return x.Mass
}
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,
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,
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,
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,
@ -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,
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,
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,
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,
@ -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,
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,
0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09,
0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x73, 0x73,
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,
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,

View File

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

View File

@ -146,6 +146,9 @@ func (x *RpcTransactionInput) toAppMessage() (*appmessage.RPCTransactionInput, e
if x == 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()
if err != nil {
return nil, err
@ -163,6 +166,7 @@ func (x *RpcTransactionInput) toAppMessage() (*appmessage.RPCTransactionInput, e
SignatureScript: x.SignatureScript,
Sequence: x.Sequence,
VerboseData: verboseData,
SigOpCount: byte(x.SigOpCount),
}, nil
}
@ -179,6 +183,7 @@ func (x *RpcTransactionInput) fromAppMessage(message *appmessage.RPCTransactionI
SignatureScript: message.SignatureScript,
Sequence: message.Sequence,
VerboseData: verboseData,
SigOpCount: uint32(message.SigOpCount),
}
}
@ -291,7 +296,7 @@ func (x *RpcTransactionVerboseData) toAppMessage() (*appmessage.RPCTransactionVe
return &appmessage.RPCTransactionVerboseData{
TransactionID: x.TransactionId,
Hash: x.Hash,
Size: x.Size,
Mass: x.Mass,
BlockHash: x.BlockHash,
BlockTime: x.BlockTime,
}, nil
@ -301,7 +306,7 @@ func (x *RpcTransactionVerboseData) fromAppMessage(message *appmessage.RPCTransa
*x = RpcTransactionVerboseData{
TransactionId: message.TransactionID,
Hash: message.Hash,
Size: message.Size,
Mass: message.Mass,
BlockHash: message.BlockHash,
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 {
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)
if err != nil {

View File

@ -161,7 +161,7 @@ func buildTransactionForUTXOIndexTest(t *testing.T, entry *appmessage.UTXOsByAdd
}
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)
if err != nil {