core: don't reverify mempooled transactions in AddBlock

The end effect is almost as if `VerifyTransactions: false` was set in the
config, but without actually compromising the guarantees provided by it.

It almost doubles performance for single-mode benchmarks and makes block
processing smoother (more smaller blocks are being produced).
This commit is contained in:
Roman Khimov 2020-08-19 14:38:58 +03:00
parent 187a2d14b1
commit 3a379e4f3e
2 changed files with 43 additions and 0 deletions

View file

@ -437,6 +437,12 @@ func (bc *Blockchain) AddBlock(block *block.Block) error {
} }
if bc.config.VerifyTransactions { if bc.config.VerifyTransactions {
for _, tx := range block.Transactions { for _, tx := range block.Transactions {
// Transactions are verified before adding them
// into the pool, so there is no point in doing
// it again even if we're verifying in-block transactions.
if bc.memPool.ContainsKey(tx.Hash()) {
continue
}
err := bc.VerifyTx(tx, block) err := bc.VerifyTx(tx, block)
if err != nil { if err != nil {
return fmt.Errorf("transaction %s failed to verify: %w", tx.Hash().StringLE(), err) return fmt.Errorf("transaction %s failed to verify: %w", tx.Hash().StringLE(), err)

View file

@ -117,6 +117,43 @@ func TestAddBlock(t *testing.T) {
assert.Equal(t, lastBlock.Hash(), bc.CurrentHeaderHash()) assert.Equal(t, lastBlock.Hash(), bc.CurrentHeaderHash())
} }
func TestAddBadBlock(t *testing.T) {
bc := newTestChain(t)
defer bc.Close()
// It has ValidUntilBlock == 0, which is wrong
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Signers = []transaction.Signer{{
Account: testchain.MultisigScriptHash(),
Scopes: transaction.FeeOnly,
}}
require.NoError(t, signTx(bc, tx))
b1 := bc.newBlock(tx)
require.Error(t, bc.AddBlock(b1))
bc.config.VerifyTransactions = false
require.NoError(t, bc.AddBlock(b1))
b2 := bc.newBlock()
b2.PrevHash = util.Uint256{}
require.Error(t, bc.AddBlock(b2))
bc.config.VerifyBlocks = false
require.NoError(t, bc.AddBlock(b2))
tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = 128
tx.Signers = []transaction.Signer{{
Account: testchain.MultisigScriptHash(),
Scopes: transaction.FeeOnly,
}}
require.NoError(t, signTx(bc, tx))
require.NoError(t, bc.PoolTx(tx))
bc.config.VerifyTransactions = true
bc.config.VerifyBlocks = true
b3 := bc.newBlock(tx)
require.NoError(t, bc.AddBlock(b3))
}
func TestScriptFromWitness(t *testing.T) { func TestScriptFromWitness(t *testing.T) {
witness := &transaction.Witness{} witness := &transaction.Witness{}
h := util.Uint160{1, 2, 3} h := util.Uint160{1, 2, 3}