From 1a16ebc3f2f1782079701e39c646079cee0ce5cc Mon Sep 17 00:00:00 2001 From: Janko Date: Fri, 26 Aug 2022 22:14:28 +0200 Subject: [PATCH 01/12] ethclient/gethclient: this change modifies the gethclient to properly override the state for the Code property If the code property is not present in the state overrides, it should be skipped or set to null on marshal. Because of the type of the property hexutil.Bytes the empty slice marshals to 0x and the request fails. fixes #25615 --- ethclient/gethclient/gethclient.go | 12 +++- ethclient/gethclient/gethclient_test.go | 83 +++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index a86f4339f425..52bf15d53c96 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -216,16 +216,24 @@ func toOverrideMap(overrides *map[common.Address]OverrideAccount) interface{} { } type overrideAccount struct { Nonce hexutil.Uint64 `json:"nonce"` - Code hexutil.Bytes `json:"code"` + Code []byte `json:"code"` Balance *hexutil.Big `json:"balance"` State map[common.Hash]common.Hash `json:"state"` StateDiff map[common.Hash]common.Hash `json:"stateDiff"` } result := make(map[common.Address]overrideAccount) + for addr, override := range *overrides { + var code []byte + + if len(override.Code) > 0 { + // convert to hexutil.Bytes explicitly in order to marshal/unmarshal as a JSON string with 0x prefix. + code = hexutil.Bytes(override.Code) + } + result[addr] = overrideAccount{ Nonce: hexutil.Uint64(override.Nonce), - Code: override.Code, + Code: code, Balance: (*hexutil.Big)(override.Balance), State: override.State, StateDiff: override.StateDiff, diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index a0f4eaaf5db4..e2a04290722a 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -19,11 +19,13 @@ package gethclient import ( "bytes" "context" + "encoding/json" "math/big" "testing" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -135,6 +137,12 @@ func TestGethClient(t *testing.T) { }, { "TestCallContract", func(t *testing.T) { testCallContract(t, client) }, + }, { + "testCodeOverride", + func(t *testing.T) { testCodeOverride(t) }, + }, { + "testNoCodeOverride", + func(t *testing.T) { testNoCodeOverride(t) }, }, } t.Parallel() @@ -327,3 +335,78 @@ func testCallContract(t *testing.T, client *rpc.Client) { t.Fatalf("unexpected error: %v", err) } } + +func testNoCodeOverride(t *testing.T) { + override := OverrideAccount{} + + mapAcc := make(map[common.Address]OverrideAccount) + mapAcc[testAddr] = override + + encoded := toOverrideMap(&mapAcc) + + type overrideAccount struct { + Nonce hexutil.Uint64 `json:"nonce"` + Code []byte `json:"code"` + Balance *hexutil.Big `json:"balance"` + State map[common.Hash]common.Hash `json:"state"` + StateDiff map[common.Hash]common.Hash `json:"stateDiff"` + } + + var accounts map[common.Address]*overrideAccount + marshalled, err := json.Marshal(encoded) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + err = json.Unmarshal(marshalled, &accounts) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + account := accounts[testAddr] + if account == nil { + t.Fatal("unexpected error") + } + + if account.Code != nil { + t.Fatal("unexpected error") + } +} + +func testCodeOverride(t *testing.T) { + override := OverrideAccount{} + override.Code = []byte{1} + + mapAcc := make(map[common.Address]OverrideAccount) + mapAcc[testAddr] = override + + encoded := toOverrideMap(&mapAcc) + + type overrideAccount struct { + Nonce hexutil.Uint64 `json:"nonce"` + Code []byte `json:"code"` + Balance *hexutil.Big `json:"balance"` + State map[common.Hash]common.Hash `json:"state"` + StateDiff map[common.Hash]common.Hash `json:"stateDiff"` + } + + var accounts map[common.Address]*overrideAccount + marshalled, err := json.Marshal(encoded) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + err = json.Unmarshal(marshalled, &accounts) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + account := accounts[testAddr] + if account == nil { + t.Fatal("unexpected error") + } + + if account.Code == nil { + t.Fatal("unexpected error") + } +} From 06faf1f182c17e159727105c0e409bf6d3afaa75 Mon Sep 17 00:00:00 2001 From: Janko Date: Wed, 31 Aug 2022 12:19:02 +0200 Subject: [PATCH 02/12] ethclient/gethclient: modify test messages --- ethclient/gethclient/gethclient_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index e2a04290722a..93ca4fecba79 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -365,11 +365,11 @@ func testNoCodeOverride(t *testing.T) { account := accounts[testAddr] if account == nil { - t.Fatal("unexpected error") + t.Fatal("Empty account retrieved") } if account.Code != nil { - t.Fatal("unexpected error") + t.Fatal("Code should be empty") } } @@ -403,10 +403,10 @@ func testCodeOverride(t *testing.T) { account := accounts[testAddr] if account == nil { - t.Fatal("unexpected error") + t.Fatal("Empty account retrieved") } if account.Code == nil { - t.Fatal("unexpected error") + t.Fatal("Code should not be empty") } } From 239e93f297c73be2b9d36baef088a5c76d2fb748 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 26 Sep 2022 22:53:58 +0200 Subject: [PATCH 03/12] Update gethclient.go --- ethclient/gethclient/gethclient.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 52bf15d53c96..b3fafa65a61a 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -216,7 +216,7 @@ func toOverrideMap(overrides *map[common.Address]OverrideAccount) interface{} { } type overrideAccount struct { Nonce hexutil.Uint64 `json:"nonce"` - Code []byte `json:"code"` + Code string `json:"code,omitempty"` Balance *hexutil.Big `json:"balance"` State map[common.Hash]common.Hash `json:"state"` StateDiff map[common.Hash]common.Hash `json:"stateDiff"` @@ -224,13 +224,10 @@ func toOverrideMap(overrides *map[common.Address]OverrideAccount) interface{} { result := make(map[common.Address]overrideAccount) for addr, override := range *overrides { - var code []byte - - if len(override.Code) > 0 { - // convert to hexutil.Bytes explicitly in order to marshal/unmarshal as a JSON string with 0x prefix. - code = hexutil.Bytes(override.Code) + var code string + if override.Code != nil { + code = hexutil.Encode(override.Code) } - result[addr] = overrideAccount{ Nonce: hexutil.Uint64(override.Nonce), Code: code, From 650adb66c4802a71e04db08ee094fecf9ba5bb15 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 27 Sep 2022 15:44:37 +0200 Subject: [PATCH 04/12] ethclient/gethclient: simplify test --- ethclient/gethclient/gethclient_test.go | 73 +++++-------------------- 1 file changed, 14 insertions(+), 59 deletions(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 93ca4fecba79..76b8bea85165 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -137,12 +137,6 @@ func TestGethClient(t *testing.T) { }, { "TestCallContract", func(t *testing.T) { testCallContract(t, client) }, - }, { - "testCodeOverride", - func(t *testing.T) { testCodeOverride(t) }, - }, { - "testNoCodeOverride", - func(t *testing.T) { testNoCodeOverride(t) }, }, } t.Parallel() @@ -336,77 +330,38 @@ func testCallContract(t *testing.T, client *rpc.Client) { } } -func testNoCodeOverride(t *testing.T) { - override := OverrideAccount{} - +func TestCodeOverride(t *testing.T) { mapAcc := make(map[common.Address]OverrideAccount) - mapAcc[testAddr] = override - - encoded := toOverrideMap(&mapAcc) - - type overrideAccount struct { - Nonce hexutil.Uint64 `json:"nonce"` - Code []byte `json:"code"` - Balance *hexutil.Big `json:"balance"` - State map[common.Hash]common.Hash `json:"state"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff"` - } - - var accounts map[common.Address]*overrideAccount - marshalled, err := json.Marshal(encoded) - if err != nil { - t.Fatalf("unexpected error: %v", err) + mapAcc[common.Address{0xaa}] = OverrideAccount{} + mapAcc[common.Address{0xbb}] = OverrideAccount{ + Code: []byte{1}, } - - err = json.Unmarshal(marshalled, &accounts) + marshalled, err := json.Marshal(toOverrideMap(&mapAcc)) if err != nil { t.Fatalf("unexpected error: %v", err) } - - account := accounts[testAddr] - if account == nil { - t.Fatal("Empty account retrieved") - } - - if account.Code != nil { - t.Fatal("Code should be empty") - } -} - -func testCodeOverride(t *testing.T) { - override := OverrideAccount{} - override.Code = []byte{1} - - mapAcc := make(map[common.Address]OverrideAccount) - mapAcc[testAddr] = override - - encoded := toOverrideMap(&mapAcc) - type overrideAccount struct { Nonce hexutil.Uint64 `json:"nonce"` - Code []byte `json:"code"` + Code hexutil.Bytes `json:"code"` Balance *hexutil.Big `json:"balance"` State map[common.Hash]common.Hash `json:"state"` StateDiff map[common.Hash]common.Hash `json:"stateDiff"` } - var accounts map[common.Address]*overrideAccount - marshalled, err := json.Marshal(encoded) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - err = json.Unmarshal(marshalled, &accounts) if err != nil { t.Fatalf("unexpected error: %v", err) } - account := accounts[testAddr] - if account == nil { - t.Fatal("Empty account retrieved") + if account, ok := accounts[common.Address{0xaa}]; !ok { + t.Fatal("missing account") + } else if account.Code != nil { + t.Fatalf("code wrong, should be nil, is %v", account.Code) } - if account.Code == nil { - t.Fatal("Code should not be empty") + if account, ok := accounts[common.Address{0xbb}]; !ok { + t.Fatal("missing account") + } else if have, want := account.Code, []byte{1}; !bytes.Equal(have, want) { + t.Fatalf("code wrong, have %x, want %x", have, want) } } From a9bdc2d7f45d773cd8a5d10332e1d4bfdb650731 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 27 Sep 2022 16:07:17 +0200 Subject: [PATCH 05/12] ethclient/gethclient: further simplification --- ethclient/gethclient/gethclient_test.go | 37 ++++++++++++------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 76b8bea85165..76a47ba7f3c7 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -35,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" @@ -331,25 +331,17 @@ func testCallContract(t *testing.T, client *rpc.Client) { } func TestCodeOverride(t *testing.T) { - mapAcc := make(map[common.Address]OverrideAccount) - mapAcc[common.Address{0xaa}] = OverrideAccount{} - mapAcc[common.Address{0xbb}] = OverrideAccount{ - Code: []byte{1}, - } - marshalled, err := json.Marshal(toOverrideMap(&mapAcc)) + marshalled, err := json.Marshal(toOverrideMap(&map[common.Address]OverrideAccount{ + common.Address{0xaa}: OverrideAccount{}, + common.Address{0xbb}: OverrideAccount{ + Code: []byte{1}, + }, + })) if err != nil { t.Fatalf("unexpected error: %v", err) } - type overrideAccount struct { - Nonce hexutil.Uint64 `json:"nonce"` - Code hexutil.Bytes `json:"code"` - Balance *hexutil.Big `json:"balance"` - State map[common.Hash]common.Hash `json:"state"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff"` - } - var accounts map[common.Address]*overrideAccount - err = json.Unmarshal(marshalled, &accounts) - if err != nil { + var accounts map[common.Address]*ethapi.OverrideAccount + if err = json.Unmarshal(marshalled, &accounts); err != nil { t.Fatalf("unexpected error: %v", err) } @@ -361,7 +353,14 @@ func TestCodeOverride(t *testing.T) { if account, ok := accounts[common.Address{0xbb}]; !ok { t.Fatal("missing account") - } else if have, want := account.Code, []byte{1}; !bytes.Equal(have, want) { - t.Fatalf("code wrong, have %x, want %x", have, want) + } else { + if account.Code == nil { + t.Fatal("code wrong, expect non-nil") + } + have := []byte((*account.Code)) + want := []byte{1} + if !bytes.Equal(have, want) { + t.Fatalf("code wrong, have %x, want %x", have, want) + } } } From 37432eaef3a90bc88624859d02112f3ce2b742ef Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 27 Sep 2022 16:30:28 +0200 Subject: [PATCH 06/12] ethclient/gethclient: one more testcase --- ethclient/gethclient/gethclient_test.go | 37 +++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 76a47ba7f3c7..5df069319a75 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -331,12 +331,12 @@ func testCallContract(t *testing.T, client *rpc.Client) { } func TestCodeOverride(t *testing.T) { - marshalled, err := json.Marshal(toOverrideMap(&map[common.Address]OverrideAccount{ + overrides := map[common.Address]OverrideAccount{ common.Address{0xaa}: OverrideAccount{}, - common.Address{0xbb}: OverrideAccount{ - Code: []byte{1}, - }, - })) + common.Address{0xbb}: OverrideAccount{Code: []byte{}}, + common.Address{0xcc}: OverrideAccount{Code: []byte{1}}, + } + marshalled, err := json.Marshal(toOverrideMap(&overrides)) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -344,21 +344,22 @@ func TestCodeOverride(t *testing.T) { if err = json.Unmarshal(marshalled, &accounts); err != nil { t.Fatalf("unexpected error: %v", err) } - - if account, ok := accounts[common.Address{0xaa}]; !ok { - t.Fatal("missing account") - } else if account.Code != nil { - t.Fatalf("code wrong, should be nil, is %v", account.Code) - } - - if account, ok := accounts[common.Address{0xbb}]; !ok { - t.Fatal("missing account") - } else { - if account.Code == nil { - t.Fatal("code wrong, expect non-nil") + for k, v := range overrides { + account, ok := accounts[k] + if !ok { + t.Fatalf("missing account %v", k) + } + if v.Code == nil { + if account.Code != nil { + t.Fatalf("code wrong, should be nil, is %v", account.Code) + } + continue + } + if v.Code != nil && account.Code == nil { + t.Fatalf("code wrong, should be non-nil %v", k) } have := []byte((*account.Code)) - want := []byte{1} + want := v.Code if !bytes.Equal(have, want) { t.Fatalf("code wrong, have %x, want %x", have, want) } From a3dca1b1129f7b08d11dae6e30f8815f699d2baa Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 27 Sep 2022 17:01:49 +0200 Subject: [PATCH 07/12] ethclient/gethclient: more fixes to overrides --- ethclient/gethclient/gethclient.go | 67 +++++++++++------------ ethclient/gethclient/gethclient_test.go | 71 ++++++++++++++----------- 2 files changed, 72 insertions(+), 66 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index b3fafa65a61a..ab12b1bf21e9 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -19,6 +19,7 @@ package gethclient import ( "context" + "encoding/json" "math/big" "runtime" "runtime/debug" @@ -118,15 +119,6 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s return &result, err } -// OverrideAccount specifies the state of an account to be overridden. -type OverrideAccount struct { - Nonce uint64 `json:"nonce"` - Code []byte `json:"code"` - Balance *big.Int `json:"balance"` - State map[common.Hash]common.Hash `json:"state"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff"` -} - // CallContract executes a message call transaction, which is directly executed in the VM // of the node, but never mined into the blockchain. // @@ -141,7 +133,7 @@ func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockN var hex hexutil.Bytes err := ec.c.CallContext( ctx, &hex, "eth_call", toCallArg(msg), - toBlockNumArg(blockNumber), toOverrideMap(overrides), + toBlockNumArg(blockNumber), overrides, ) return hex, err } @@ -210,31 +202,34 @@ func toCallArg(msg ethereum.CallMsg) interface{} { return arg } -func toOverrideMap(overrides *map[common.Address]OverrideAccount) interface{} { - if overrides == nil { - return nil - } - type overrideAccount struct { - Nonce hexutil.Uint64 `json:"nonce"` +// OverrideAccount specifies the state of an account to be overridden. +type OverrideAccount struct { + Nonce uint64 `json:"nonce"` + Code []byte `json:"code"` + Balance *big.Int `json:"balance"` + State map[common.Hash]common.Hash `json:"state"` + StateDiff map[common.Hash]common.Hash `json:"stateDiff"` +} + +func (a OverrideAccount) MarshalJSON() ([]byte, error) { + type acc struct { + Nonce hexutil.Uint64 `json:"nonce,omitempty"` Code string `json:"code,omitempty"` - Balance *hexutil.Big `json:"balance"` - State map[common.Hash]common.Hash `json:"state"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff"` - } - result := make(map[common.Address]overrideAccount) - - for addr, override := range *overrides { - var code string - if override.Code != nil { - code = hexutil.Encode(override.Code) - } - result[addr] = overrideAccount{ - Nonce: hexutil.Uint64(override.Nonce), - Code: code, - Balance: (*hexutil.Big)(override.Balance), - State: override.State, - StateDiff: override.StateDiff, - } - } - return &result + Balance *hexutil.Big `json:"balance,omitempty"` + State interface{} `json:"state,omitempty"` + StateDiff map[common.Hash]common.Hash `json:"stateDiff,omitempty"` + } + + m := acc{ + Nonce: hexutil.Uint64(a.Nonce), + Balance: (*hexutil.Big)(a.Balance), + StateDiff: a.StateDiff, + } + if a.Code != nil { + m.Code = hexutil.Encode(a.Code) + } + if a.State != nil { + m.State = a.State + } + return json.Marshal(m) } diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 5df069319a75..19aeb300efd5 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" @@ -330,38 +329,50 @@ func testCallContract(t *testing.T, client *rpc.Client) { } } -func TestCodeOverride(t *testing.T) { - overrides := map[common.Address]OverrideAccount{ - common.Address{0xaa}: OverrideAccount{}, - common.Address{0xbb}: OverrideAccount{Code: []byte{}}, - common.Address{0xcc}: OverrideAccount{Code: []byte{1}}, +func TestOverrideAccountMarshal(t *testing.T) { + om := map[common.Address]OverrideAccount{ + common.Address{0x11}: OverrideAccount{}, + common.Address{0xaa}: OverrideAccount{ + Nonce: 5, + }, + common.Address{0xbb}: OverrideAccount{ + Code: []byte{1}, + }, + common.Address{0xcc}: OverrideAccount{ + // This one checks that 'code' is set when + // the input is a non-nil but empty slice. + Code: []byte{}, + }, + common.Address{0xdd}: OverrideAccount{ + // This one checks that 'state' is set + // when the input is a non-nil but empty map. + State: map[common.Hash]common.Hash{}, + }, } - marshalled, err := json.Marshal(toOverrideMap(&overrides)) + + marshalled, err := json.MarshalIndent(&om, "", " ") if err != nil { t.Fatalf("unexpected error: %v", err) } - var accounts map[common.Address]*ethapi.OverrideAccount - if err = json.Unmarshal(marshalled, &accounts); err != nil { - t.Fatalf("unexpected error: %v", err) - } - for k, v := range overrides { - account, ok := accounts[k] - if !ok { - t.Fatalf("missing account %v", k) - } - if v.Code == nil { - if account.Code != nil { - t.Fatalf("code wrong, should be nil, is %v", account.Code) - } - continue - } - if v.Code != nil && account.Code == nil { - t.Fatalf("code wrong, should be non-nil %v", k) - } - have := []byte((*account.Code)) - want := v.Code - if !bytes.Equal(have, want) { - t.Fatalf("code wrong, have %x, want %x", have, want) - } + + expected := `{ + "0x1100000000000000000000000000000000000000": {}, + "0xaa00000000000000000000000000000000000000": { + "nonce": "0x5" + }, + "0xbb00000000000000000000000000000000000000": { + "code": "0x01" + }, + "0xcc00000000000000000000000000000000000000": { + "code": "0x" + }, + "0xdd00000000000000000000000000000000000000": { + "state": {} + } +}` + + if string(marshalled) != expected { + t.Error("wrong output:", string(marshalled)) + t.Error("want:", expected) } } From d791544aac00d79e33bc256f325e29daddab0106 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 27 Sep 2022 17:09:42 +0200 Subject: [PATCH 08/12] ethclient/gethclient: improve docs of OverrideAccount --- ethclient/gethclient/gethclient.go | 32 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index ab12b1bf21e9..c5632563ec46 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -204,11 +204,25 @@ func toCallArg(msg ethereum.CallMsg) interface{} { // OverrideAccount specifies the state of an account to be overridden. type OverrideAccount struct { - Nonce uint64 `json:"nonce"` - Code []byte `json:"code"` - Balance *big.Int `json:"balance"` - State map[common.Hash]common.Hash `json:"state"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff"` + // Nonce sets nonce of the account. Note: the nonce override will only + // be applied when it is set to a non-zero value. + Nonce uint64 + + // Code sets the contract code. The override will be applied + // when the code is non-nil, i.e. setting empty code is possible + // using an empty slice. + Code []byte + + // Balance sets the account balance. + Balance *big.Int + + // State sets the complete storage. The override will be applied + // when the given map is non-nil. Using an empty map overrides the + // contract storage to be empty. + State map[common.Hash]common.Hash + + // StateDiff allows overriding individual storage slots. + StateDiff map[common.Hash]common.Hash } func (a OverrideAccount) MarshalJSON() ([]byte, error) { @@ -220,16 +234,16 @@ func (a OverrideAccount) MarshalJSON() ([]byte, error) { StateDiff map[common.Hash]common.Hash `json:"stateDiff,omitempty"` } - m := acc{ + output := acc{ Nonce: hexutil.Uint64(a.Nonce), Balance: (*hexutil.Big)(a.Balance), StateDiff: a.StateDiff, } if a.Code != nil { - m.Code = hexutil.Encode(a.Code) + output.Code = hexutil.Encode(a.Code) } if a.State != nil { - m.State = a.State + output.State = a.State } - return json.Marshal(m) + return json.Marshal(output) } From 57283d179e29b214e58dcbd2af0044539cefbb6f Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 27 Sep 2022 17:16:42 +0200 Subject: [PATCH 09/12] ethclient/gethclient: fixup comment --- ethclient/gethclient/gethclient.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index c5632563ec46..2badceb8129d 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -217,8 +217,8 @@ type OverrideAccount struct { Balance *big.Int // State sets the complete storage. The override will be applied - // when the given map is non-nil. Using an empty map overrides the - // contract storage to be empty. + // when the given map is non-nil. Using an empty map wipes the + // entire contract storage during the call. State map[common.Hash]common.Hash // StateDiff allows overriding individual storage slots. From 0b81a45c3b2d1f1b67fa7273d48eee1b240f2bd3 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 27 Sep 2022 17:51:45 +0200 Subject: [PATCH 10/12] ethclient/gethclient: add test for zero balance --- ethclient/gethclient/gethclient_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 19aeb300efd5..55902bcdb59d 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -348,6 +348,11 @@ func TestOverrideAccountMarshal(t *testing.T) { // when the input is a non-nil but empty map. State: map[common.Hash]common.Hash{}, }, + common.Address{0xee}: OverrideAccount{ + // This one checks that 'balance' is set + // when the input is a non-nil but zero integer. + Balance: big.NewInt(0), + }, } marshalled, err := json.MarshalIndent(&om, "", " ") @@ -368,6 +373,9 @@ func TestOverrideAccountMarshal(t *testing.T) { }, "0xdd00000000000000000000000000000000000000": { "state": {} + }, + "0xee00000000000000000000000000000000000000": { + "balance": "0x0" } }` From 3acdc0a603eb1ead9b2339334c490c30abfb5c82 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 27 Sep 2022 18:26:15 +0200 Subject: [PATCH 11/12] ethclient/gethclient: add zero-nonce --- ethclient/gethclient/gethclient_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 55902bcdb59d..14c67dd79b4b 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -331,7 +331,11 @@ func testCallContract(t *testing.T, client *rpc.Client) { func TestOverrideAccountMarshal(t *testing.T) { om := map[common.Address]OverrideAccount{ - common.Address{0x11}: OverrideAccount{}, + common.Address{0x11}: OverrideAccount{ + // Zero-valued nonce is not overrideden, but simply dropped + // by the encoder. + Nonce: 0, + }, common.Address{0xaa}: OverrideAccount{ Nonce: 5, }, From 0239d8b661c7ba5265397313525eafc2ba3eaa89 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 27 Sep 2022 19:17:31 +0200 Subject: [PATCH 12/12] ethclient/gethclient: add check for stateDiff and compress the test a bit --- ethclient/gethclient/gethclient_test.go | 30 +++++++++---------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 14c67dd79b4b..379fabeea1c0 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -332,8 +332,7 @@ func testCallContract(t *testing.T, client *rpc.Client) { func TestOverrideAccountMarshal(t *testing.T) { om := map[common.Address]OverrideAccount{ common.Address{0x11}: OverrideAccount{ - // Zero-valued nonce is not overrideden, but simply dropped - // by the encoder. + // Zero-valued nonce is not overriddden, but simply dropped by the encoder. Nonce: 0, }, common.Address{0xaa}: OverrideAccount{ @@ -343,19 +342,14 @@ func TestOverrideAccountMarshal(t *testing.T) { Code: []byte{1}, }, common.Address{0xcc}: OverrideAccount{ - // This one checks that 'code' is set when - // the input is a non-nil but empty slice. - Code: []byte{}, - }, - common.Address{0xdd}: OverrideAccount{ - // This one checks that 'state' is set - // when the input is a non-nil but empty map. - State: map[common.Hash]common.Hash{}, - }, - common.Address{0xee}: OverrideAccount{ - // This one checks that 'balance' is set - // when the input is a non-nil but zero integer. + // 'code', 'balance', 'state' should be set when input is + // a non-nil but empty value. + Code: []byte{}, Balance: big.NewInt(0), + State: map[common.Hash]common.Hash{}, + // For 'stateDiff' the behavior is different, empty map + // is ignored because it makes no difference. + StateDiff: map[common.Hash]common.Hash{}, }, } @@ -373,13 +367,9 @@ func TestOverrideAccountMarshal(t *testing.T) { "code": "0x01" }, "0xcc00000000000000000000000000000000000000": { - "code": "0x" - }, - "0xdd00000000000000000000000000000000000000": { + "code": "0x", + "balance": "0x0", "state": {} - }, - "0xee00000000000000000000000000000000000000": { - "balance": "0x0" } }`