mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/abi/backends: change SimulatedBackend to interface
This commit is contained in:
parent
cb549c9455
commit
71eec44d7b
2 changed files with 84 additions and 25 deletions
|
|
@ -19,8 +19,12 @@ package backends
|
|||
import (
|
||||
"context"
|
||||
"math"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/eth/catalyst"
|
||||
|
|
@ -34,9 +38,51 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||
var _ bind.ContractBackend = (*simBackend)(nil)
|
||||
|
||||
type SimulatedBackend struct {
|
||||
type SimChainManagement interface {
|
||||
// Commit seals a block and moves the chain forward to a new empty block.
|
||||
Commit() common.Hash
|
||||
|
||||
// Rollback un-sends previously added transactions.
|
||||
Rollback()
|
||||
|
||||
// Fork sets the head to a new block, which is based on the provided parentHash.
|
||||
Fork(ctx context.Context, parentHash common.Hash) error
|
||||
|
||||
// AdjustTime changes the block timestamp.
|
||||
AdjustTime(adjustment time.Duration) error
|
||||
|
||||
// Close closes the backend. You need to call this to clean up resources.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// TODO: these methods should have their own interface in the ethereum package.
|
||||
type SimChainExtras interface {
|
||||
BlockNumber(context.Context) (uint64, error)
|
||||
ChainID(context.Context) (*big.Int, error)
|
||||
}
|
||||
|
||||
// SimulatedBackend all interfaces in the ethereum package, but is based on a
|
||||
// simulated blockchain. It is intended for testing purposes.
|
||||
type SimulatedBackend interface {
|
||||
SimChainManagement
|
||||
|
||||
// The backend implements all interfaces in the ethereum package.
|
||||
ethereum.ChainReader
|
||||
ethereum.ChainStateReader
|
||||
ethereum.ContractCaller
|
||||
ethereum.GasEstimator
|
||||
ethereum.LogFilterer
|
||||
ethereum.GasPricer
|
||||
ethereum.PendingStateReader
|
||||
ethereum.PendingContractCaller
|
||||
ethereum.TransactionReader
|
||||
ethereum.TransactionSender
|
||||
SimChainExtras
|
||||
}
|
||||
|
||||
type simBackend struct {
|
||||
eth *eth.Ethereum
|
||||
*catalyst.SimulatedBeacon
|
||||
*ethclient.Client
|
||||
|
|
@ -45,7 +91,7 @@ type SimulatedBackend struct {
|
|||
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
|
||||
// for testing purposes.
|
||||
// A simulated backend always uses chainID 1337.
|
||||
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
|
||||
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) SimulatedBackend {
|
||||
// Setup the node object
|
||||
nodeConf := node.DefaultConfig
|
||||
nodeConf.DataDir = ""
|
||||
|
|
@ -76,7 +122,7 @@ func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBac
|
|||
// NewSimWithNode sets up a simulated backend on an existing node
|
||||
// this allows users to do persistent simulations.
|
||||
// The provided node must not be started and will be started by NewSimWithNode
|
||||
func NewSimWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*SimulatedBackend, error) {
|
||||
func NewSimWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (SimulatedBackend, error) {
|
||||
backend, err := eth.New(stack, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -105,14 +151,14 @@ func NewSimWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*Si
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &SimulatedBackend{
|
||||
return &simBackend{
|
||||
eth: backend,
|
||||
SimulatedBeacon: beacon,
|
||||
Client: ethclient.NewClient(stack.Attach()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *SimulatedBackend) Close() error {
|
||||
func (n *simBackend) Close() error {
|
||||
if n.Client != nil {
|
||||
n.Client.Close()
|
||||
n.Client = nil
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ var (
|
|||
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
||||
)
|
||||
|
||||
func simTestBackend(testAddr common.Address) *SimulatedBackend {
|
||||
func simTestBackend(testAddr common.Address) SimulatedBackend {
|
||||
return NewSimulatedBackend(
|
||||
core.GenesisAlloc{
|
||||
testAddr: {Balance: big.NewInt(10000000000000000)},
|
||||
|
|
@ -44,12 +44,7 @@ func simTestBackend(testAddr common.Address) *SimulatedBackend {
|
|||
)
|
||||
}
|
||||
|
||||
func (sim *SimulatedBackend) currentBlock() *types.Block {
|
||||
current, _ := sim.BlockByNumber(context.Background(), nil)
|
||||
return current
|
||||
}
|
||||
|
||||
func (sim *SimulatedBackend) newTx(key *ecdsa.PrivateKey) (*types.Transaction, error) {
|
||||
func newTx(sim SimulatedBackend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
|
||||
// create a signed transaction to send
|
||||
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
|
||||
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
|
||||
|
|
@ -113,7 +108,7 @@ func TestSendTransaction(t *testing.T) {
|
|||
defer sim.Close()
|
||||
bgCtx := context.Background()
|
||||
|
||||
signedTx, err := sim.newTx(testKey)
|
||||
signedTx, err := newTx(sim, testKey)
|
||||
if err != nil {
|
||||
t.Errorf("could not create transaction: %v", err)
|
||||
}
|
||||
|
|
@ -148,25 +143,35 @@ func TestFork(t *testing.T) {
|
|||
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||
sim := simTestBackend(testAddr)
|
||||
defer sim.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 1.
|
||||
parent := sim.currentBlock()
|
||||
parent, _ := sim.HeaderByNumber(ctx, nil)
|
||||
|
||||
// 2.
|
||||
n := int(rand.Int31n(21))
|
||||
for i := 0; i < n; i++ {
|
||||
sim.Commit()
|
||||
}
|
||||
|
||||
// 3.
|
||||
if sim.currentBlock().Number().Uint64() != uint64(n) {
|
||||
b, _ := sim.BlockNumber(ctx)
|
||||
if b != uint64(n) {
|
||||
t.Error("wrong chain length")
|
||||
}
|
||||
|
||||
// 4.
|
||||
sim.Fork(context.Background(), parent.Hash())
|
||||
sim.Fork(ctx, parent.Hash())
|
||||
|
||||
// 5.
|
||||
for i := 0; i < n+1; i++ {
|
||||
sim.Commit()
|
||||
}
|
||||
|
||||
// 6.
|
||||
if sim.currentBlock().Number().Uint64() != uint64(n+1) {
|
||||
b, _ = sim.BlockNumber(ctx)
|
||||
if b != uint64(n+1) {
|
||||
t.Error("wrong chain length")
|
||||
}
|
||||
}
|
||||
|
|
@ -185,24 +190,30 @@ func TestForkResendTx(t *testing.T) {
|
|||
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||
sim := simTestBackend(testAddr)
|
||||
defer sim.Close()
|
||||
|
||||
// 1.
|
||||
parent := sim.currentBlock()
|
||||
ctx := context.Background()
|
||||
parent, _ := sim.HeaderByNumber(ctx, nil)
|
||||
|
||||
// 2.
|
||||
tx, err := sim.newTx(testKey)
|
||||
tx, err := newTx(sim, testKey)
|
||||
if err != nil {
|
||||
t.Fatalf("could not create transaction: %v", err)
|
||||
}
|
||||
sim.SendTransaction(context.Background(), tx)
|
||||
sim.Commit()
|
||||
|
||||
// 3.
|
||||
receipt, _ := sim.TransactionReceipt(context.Background(), tx.Hash())
|
||||
if h := receipt.BlockNumber.Uint64(); h != 1 {
|
||||
t.Errorf("TX included in wrong block: %d", h)
|
||||
}
|
||||
|
||||
// 4.
|
||||
if err := sim.Fork(context.Background(), parent.Hash()); err != nil {
|
||||
t.Errorf("forking: %v", err)
|
||||
}
|
||||
|
||||
// 5.
|
||||
sim.Commit()
|
||||
if err := sim.SendTransaction(context.Background(), tx); err != nil {
|
||||
|
|
@ -223,7 +234,8 @@ func TestCommitReturnValue(t *testing.T) {
|
|||
|
||||
// Test if Commit returns the correct block hash
|
||||
h1 := sim.Commit()
|
||||
if h1 != sim.currentBlock().Hash() {
|
||||
cur, _ := sim.HeaderByNumber(context.Background(), nil)
|
||||
if h1 != cur.Hash() {
|
||||
t.Error("Commit did not return the hash of the last block.")
|
||||
}
|
||||
|
||||
|
|
@ -262,14 +274,15 @@ func TestAdjustTimeAfterFork(t *testing.T) {
|
|||
defer sim.Close()
|
||||
|
||||
sim.Commit() // h1
|
||||
h1 := sim.currentBlock().Hash()
|
||||
h1, _ := sim.HeaderByNumber(context.Background(), nil)
|
||||
|
||||
sim.Commit() // h2
|
||||
sim.Fork(context.Background(), h1)
|
||||
sim.Fork(context.Background(), h1.Hash())
|
||||
sim.AdjustTime(1 * time.Second)
|
||||
sim.Commit()
|
||||
|
||||
head := sim.currentBlock()
|
||||
if head.Number() == common.Big2 && head.ParentHash() != h1 {
|
||||
head, _ := sim.HeaderByNumber(context.Background(), nil)
|
||||
if head.Number.Uint64() == 2 && head.ParentHash != h1.Hash() {
|
||||
t.Errorf("failed to build block on fork")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue