From d5b7d1cc34e766f2e2c2b82c00c5d12cf71a9cac Mon Sep 17 00:00:00 2001 From: Boqin Qin Date: Tue, 19 May 2020 18:48:27 +0800 Subject: [PATCH] accounts: add blockByNumberNoLock() to avoid double-lock (#20983) * abi/bind/backends: testcase for double-lock * accounts: add blockByNumberNoLock to avoid double-lock * backend/simulated: use stateroot, not blockhash for retrieveing state Co-authored-by: Martin Holst Swende --- accounts/abi/bind/backends/simulated.go | 10 ++++++++-- accounts/abi/bind/backends/simulated_test.go | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 6d4bfe1cb..6a98edec1 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -133,11 +133,11 @@ func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber * if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 { return b.blockchain.State() } - block, err := b.BlockByNumber(ctx, blockNumber) + block, err := b.blockByNumberNoLock(ctx, blockNumber) if err != nil { return nil, err } - return b.blockchain.StateAt(block.Hash()) + return b.blockchain.StateAt(block.Root()) } // CodeAt returns the code associated with a certain account in the blockchain. @@ -244,6 +244,12 @@ func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) ( b.mu.Lock() defer b.mu.Unlock() + return b.blockByNumberNoLock(ctx, number) +} + +// blockByNumberNoLock retrieves a block from the database by number, caching it +// (associated with its hash) if found without Lock. +func (b *SimulatedBackend) blockByNumberNoLock(ctx context.Context, number *big.Int) (*types.Block, error) { if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 { return b.blockchain.CurrentBlock(), nil } diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index a55b4460a..25b36d497 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -268,6 +268,16 @@ func TestSimulatedBackend_NonceAt(t *testing.T) { if newNonce != nonce+uint64(1) { t.Errorf("received incorrect nonce. expected 1, got %v", nonce) } + // create some more blocks + sim.Commit() + // Check that we can get data for an older block/state + newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1)) + if err != nil { + t.Fatalf("could not get nonce for test addr: %v", err) + } + if newNonce != nonce+uint64(1) { + t.Fatalf("received incorrect nonce. expected 1, got %v", nonce) + } } func TestSimulatedBackend_SendTransaction(t *testing.T) {