From 5b3848b605b92b1844a9966567805c3f0a2f5b06 Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Mon, 6 Jan 2025 20:14:30 +0800 Subject: [PATCH] accounts/abi/bind/backends: Disallow AdjustTime for non-empty blocks (#21334) --- accounts/abi/bind/backends/simulated.go | 9 +++-- accounts/abi/bind/backends/simulated_test.go | 41 +++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index d7099e7d8ab7b..409b19b7582d4 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -803,13 +803,16 @@ func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *type } // AdjustTime adds a time shift to the simulated clock. +// It can only be called on empty blocks. func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { b.mu.Lock() defer b.mu.Unlock() + + if len(b.pendingBlock.Transactions()) != 0 { + return errors.New("could not adjust time on non-empty block") + } + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.blockchain.Engine(), b.database, 1, func(number int, block *core.BlockGen) { - for _, tx := range b.pendingBlock.Transactions() { - block.AddTx(tx) - } block.OffsetTime(int64(adjustment.Seconds())) }) statedb, _ := b.blockchain.State() diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index c2116c30e859e..ca5993a57d410 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -143,8 +143,7 @@ func TestSimulatedBackend_AdjustTime(t *testing.T) { defer sim.Close() prevTime := sim.pendingBlock.Time().Uint64() - err := sim.AdjustTime(time.Second) - if err != nil { + if err := sim.AdjustTime(time.Second); err != nil { t.Error(err) } newTime := sim.pendingBlock.Time().Uint64() @@ -154,6 +153,44 @@ func TestSimulatedBackend_AdjustTime(t *testing.T) { } } +func TestNewSimulatedBackend_AdjustTimeFail(t *testing.T) { + testAddr := crypto.PubkeyToAddress(testKey.PublicKey) + sim := simTestBackend(testAddr) + // Create tx and send + tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) + signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey) + if err != nil { + t.Errorf("could not sign tx: %v", err) + } + sim.SendTransaction(context.Background(), signedTx) + // AdjustTime should fail on non-empty block + if err := sim.AdjustTime(time.Second); err == nil { + t.Error("Expected adjust time to error on non-empty block") + } + sim.Commit() + + prevTime := sim.pendingBlock.Time().Uint64() + if err := sim.AdjustTime(time.Minute); err != nil { + t.Error(err) + } + newTime := sim.pendingBlock.Time().Uint64() + if newTime-prevTime != uint64(time.Minute.Seconds()) { + t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime) + } + // Put a transaction after adjusting time + tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil) + signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey) + if err != nil { + t.Errorf("could not sign tx: %v", err) + } + sim.SendTransaction(context.Background(), signedTx2) + sim.Commit() + newTime = sim.pendingBlock.Time().Uint64() + if newTime-prevTime >= uint64(time.Minute.Seconds()) { + t.Errorf("time adjusted, but shouldn't be: prev: %v, new: %v", prevTime, newTime) + } +} + func TestSimulatedBackend_BalanceAt(t *testing.T) { testAddr := crypto.PubkeyToAddress(testKey.PublicKey) expectedBal := big.NewInt(10000000000)