From 048caebda37987862204c026856fc26a71fefab5 Mon Sep 17 00:00:00 2001 From: Svarog Date: Sun, 29 Nov 2020 10:18:00 +0200 Subject: [PATCH] [NOD-1551] Add SigCache to TransactionValidator + Option to manipulate it in TestConsensus (#1159) * [NOD-1551] Add SigCache * [NOD-1551] Add option to edit SigCache in TestConsensus * [NOD-1551] Fix comments and make SetSigCache pointer-receiver --- domain/consensus/factory.go | 3 +++ .../interface_processes_blockvalidator.go | 4 +++- ...nterface_processes_transactionvalidator.go | 14 +++++++++-- .../consensus/model/testapi/test_consensus.go | 2 +- .../test_transaction_validator.go | 23 +++++++++++++++++++ .../transaction_in_context.go | 2 +- .../transactionvalidator.go | 5 ++++ domain/consensus/test_consensus.go | 5 +++- domain/consensus/test_consensus_getters.go | 4 ++-- domain/consensus/utils/txscript/opcode.go | 1 - 10 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 domain/consensus/processes/transactionvalidator/test_transaction_validator.go diff --git a/domain/consensus/factory.go b/domain/consensus/factory.go index 17907cac9..4e95ca67b 100644 --- a/domain/consensus/factory.go +++ b/domain/consensus/factory.go @@ -338,11 +338,14 @@ func (f *factory) NewTestConsensusWithDataDir(dagParams *dagconfig.Params, dataD testConsensusStateManager := consensusstatemanager.NewTestConsensusStateManager(consensusAsImplementation.consensusStateManager) + testTransactionValidator := transactionvalidator.NewTestTransactionValidator(consensusAsImplementation.transactionValidator) + tstConsensus := &testConsensus{ consensus: consensusAsImplementation, testConsensusStateManager: testConsensusStateManager, testReachabilityManager: reachabilitymanager.NewTestReachabilityManager(consensusAsImplementation. reachabilityManager), + testTransactionValidator: testTransactionValidator, } tstConsensus.testBlockBuilder = blockbuilder.NewTestBlockBuilder(consensusAsImplementation.blockBuilder, tstConsensus) teardown = func() { diff --git a/domain/consensus/model/interface_processes_blockvalidator.go b/domain/consensus/model/interface_processes_blockvalidator.go index 5a89c09c7..0cdc771e7 100644 --- a/domain/consensus/model/interface_processes_blockvalidator.go +++ b/domain/consensus/model/interface_processes_blockvalidator.go @@ -1,6 +1,8 @@ package model -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +) // BlockValidator exposes a set of validation classes, after which // it's possible to determine whether a block is valid diff --git a/domain/consensus/model/interface_processes_transactionvalidator.go b/domain/consensus/model/interface_processes_transactionvalidator.go index 2d8b09a89..ccf5de817 100644 --- a/domain/consensus/model/interface_processes_transactionvalidator.go +++ b/domain/consensus/model/interface_processes_transactionvalidator.go @@ -1,11 +1,21 @@ package model -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "github.com/kaspanet/kaspad/domain/consensus/utils/txscript" +) // TransactionValidator exposes a set of validation classes, after which // it's possible to determine whether a transaction is valid type TransactionValidator interface { ValidateTransactionInIsolation(transaction *externalapi.DomainTransaction) error ValidateTransactionInContextAndPopulateMassAndFee(tx *externalapi.DomainTransaction, - povBlockHash *externalapi.DomainHash, selectedParentMedianTime int64) error + povTransactionHash *externalapi.DomainHash, selectedParentMedianTime int64) error +} + +// TestTransactionValidator adds to the main TransactionValidator methods required by tests +type TestTransactionValidator interface { + TransactionValidator + SigCache() *txscript.SigCache + SetSigCache(sigCache *txscript.SigCache) } diff --git a/domain/consensus/model/testapi/test_consensus.go b/domain/consensus/model/testapi/test_consensus.go index f87cb9f37..d1cdc657f 100644 --- a/domain/consensus/model/testapi/test_consensus.go +++ b/domain/consensus/model/testapi/test_consensus.go @@ -48,5 +48,5 @@ type TestConsensus interface { PruningManager() model.PruningManager ReachabilityManager() model.TestReachabilityManager SyncManager() model.SyncManager - TransactionValidator() model.TransactionValidator + TransactionValidator() model.TestTransactionValidator } diff --git a/domain/consensus/processes/transactionvalidator/test_transaction_validator.go b/domain/consensus/processes/transactionvalidator/test_transaction_validator.go new file mode 100644 index 000000000..342b682e2 --- /dev/null +++ b/domain/consensus/processes/transactionvalidator/test_transaction_validator.go @@ -0,0 +1,23 @@ +package transactionvalidator + +import ( + "github.com/kaspanet/kaspad/domain/consensus/model" + "github.com/kaspanet/kaspad/domain/consensus/utils/txscript" +) + +type testTransactionValidator struct { + *transactionValidator +} + +// NewTestTransactionValidator creates an instance of a TestTransactionValidator +func NewTestTransactionValidator(baseTransactionValidator model.TransactionValidator) model.TestTransactionValidator { + return &testTransactionValidator{transactionValidator: baseTransactionValidator.(*transactionValidator)} +} + +func (tbv *testTransactionValidator) SigCache() *txscript.SigCache { + return tbv.sigCache +} + +func (tbv *testTransactionValidator) SetSigCache(sigCache *txscript.SigCache) { + tbv.sigCache = sigCache +} diff --git a/domain/consensus/processes/transactionvalidator/transaction_in_context.go b/domain/consensus/processes/transactionvalidator/transaction_in_context.go index edf886921..bc8dd7af4 100644 --- a/domain/consensus/processes/transactionvalidator/transaction_in_context.go +++ b/domain/consensus/processes/transactionvalidator/transaction_in_context.go @@ -189,7 +189,7 @@ func (v *transactionValidator) validateTransactionScripts(tx *externalapi.Domain scriptPubKey := utxoEntry.ScriptPublicKey vm, err := txscript.NewEngine(scriptPubKey, tx, - i, txscript.ScriptNoFlags, nil) + i, txscript.ScriptNoFlags, v.sigCache) if err != nil { return errors.Wrapf(ruleerrors.ErrScriptMalformed, "failed to parse input "+ "%d which references output %s - "+ diff --git a/domain/consensus/processes/transactionvalidator/transactionvalidator.go b/domain/consensus/processes/transactionvalidator/transactionvalidator.go index 41c338b97..9500bb556 100644 --- a/domain/consensus/processes/transactionvalidator/transactionvalidator.go +++ b/domain/consensus/processes/transactionvalidator/transactionvalidator.go @@ -2,8 +2,11 @@ package transactionvalidator import ( "github.com/kaspanet/kaspad/domain/consensus/model" + "github.com/kaspanet/kaspad/domain/consensus/utils/txscript" ) +const sigCacheSize = 10_000 + // transactionValidator exposes a set of validation classes, after which // it's possible to determine whether either a transaction is valid type transactionValidator struct { @@ -12,6 +15,7 @@ type transactionValidator struct { pastMedianTimeManager model.PastMedianTimeManager ghostdagDataStore model.GHOSTDAGDataStore enableNonNativeSubnetworks bool + sigCache *txscript.SigCache } // New instantiates a new TransactionValidator @@ -26,5 +30,6 @@ func New(blockCoinbaseMaturity uint64, databaseContext: databaseContext, pastMedianTimeManager: pastMedianTimeManager, ghostdagDataStore: ghostdagDataStore, + sigCache: txscript.NewSigCache(sigCacheSize), } } diff --git a/domain/consensus/test_consensus.go b/domain/consensus/test_consensus.go index d845b4e6f..a0dc83936 100644 --- a/domain/consensus/test_consensus.go +++ b/domain/consensus/test_consensus.go @@ -12,9 +12,12 @@ type testConsensus struct { testBlockBuilder model.TestBlockBuilder testReachabilityManager model.TestReachabilityManager testConsensusStateManager model.TestConsensusStateManager + testTransactionValidator model.TestTransactionValidator } -func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, *model.UTXODiff, error) { +func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.DomainHash, + coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) ( + *externalapi.DomainBlock, *model.UTXODiff, error) { // Require write lock because BuildBlockWithParents stages temporary data tc.lock.Lock() diff --git a/domain/consensus/test_consensus_getters.go b/domain/consensus/test_consensus_getters.go index 0ab7f6ccd..9d9061f3d 100644 --- a/domain/consensus/test_consensus_getters.go +++ b/domain/consensus/test_consensus_getters.go @@ -116,6 +116,6 @@ func (tc *testConsensus) SyncManager() model.SyncManager { return tc.syncManager } -func (tc *testConsensus) TransactionValidator() model.TransactionValidator { - return tc.transactionValidator +func (tc *testConsensus) TransactionValidator() model.TestTransactionValidator { + return tc.testTransactionValidator } diff --git a/domain/consensus/utils/txscript/opcode.go b/domain/consensus/utils/txscript/opcode.go index f87bb87b0..6c83230f7 100644 --- a/domain/consensus/utils/txscript/opcode.go +++ b/domain/consensus/utils/txscript/opcode.go @@ -2249,7 +2249,6 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { secpHash := secp256k1.Hash(*sigHash) var valid bool if vm.sigCache != nil { - valid = vm.sigCache.Exists(secpHash, parsedSig, parsedPubKey) if !valid && parsedPubKey.SchnorrVerify(&secpHash, parsedSig) { vm.sigCache.Add(secpHash, parsedSig, parsedPubKey)