mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Revert "api/bind: add CallOpts.BlockHash to allow calling contracts at a specific block hash (#28084)"
This reverts commit 9f7f4a7bb8.
This commit is contained in:
parent
8c3478e50c
commit
1661204834
7 changed files with 1 additions and 253 deletions
|
|
@ -36,10 +36,6 @@ var (
|
||||||
// on a backend that doesn't implement PendingContractCaller.
|
// on a backend that doesn't implement PendingContractCaller.
|
||||||
ErrNoPendingState = errors.New("backend does not support pending state")
|
ErrNoPendingState = errors.New("backend does not support pending state")
|
||||||
|
|
||||||
// ErrNoBlockHashState is raised when attempting to perform a block hash action
|
|
||||||
// on a backend that doesn't implement BlockHashContractCaller.
|
|
||||||
ErrNoBlockHashState = errors.New("backend does not support block hash state")
|
|
||||||
|
|
||||||
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
||||||
// an empty contract behind.
|
// an empty contract behind.
|
||||||
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
||||||
|
|
@ -68,17 +64,6 @@ type PendingContractCaller interface {
|
||||||
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
|
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
|
|
||||||
// Call will try to discover this interface when access to a block by hash is requested.
|
|
||||||
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
|
|
||||||
type BlockHashContractCaller interface {
|
|
||||||
// CodeAtHash returns the code of the given account in the state at the specified block hash.
|
|
||||||
CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)
|
|
||||||
|
|
||||||
// CallContractAtHash executes an Ethereum contract all against the state at the specified block hash.
|
|
||||||
CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContractTransactor defines the methods needed to allow operating with a contract
|
// ContractTransactor defines the methods needed to allow operating with a contract
|
||||||
// on a write only basis. Besides the transacting method, the remainder are helpers
|
// on a write only basis. Besides the transacting method, the remainder are helpers
|
||||||
// used when the user does not provide some needed values, but rather leaves it up
|
// used when the user does not provide some needed values, but rather leaves it up
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
|
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
|
||||||
errBlockHashUnsupported = errors.New("simulatedBackend cannot access blocks by hash other than the latest block")
|
|
||||||
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
|
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
|
||||||
errTransactionDoesNotExist = errors.New("transaction does not exist")
|
errTransactionDoesNotExist = errors.New("transaction does not exist")
|
||||||
)
|
)
|
||||||
|
|
@ -203,24 +202,6 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address,
|
||||||
return stateDB.GetCode(contract), nil
|
return stateDB.GetCode(contract), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeAtHash returns the code associated with a certain account in the blockchain.
|
|
||||||
func (b *SimulatedBackend) CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
|
|
||||||
header, err := b.headerByHash(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stateDB, err := b.blockchain.StateAt(header.Root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return stateDB.GetCode(contract), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BalanceAt returns the wei balance of a certain account in the blockchain.
|
// BalanceAt returns the wei balance of a certain account in the blockchain.
|
||||||
func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
|
func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
|
|
@ -339,11 +320,7 @@ func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (
|
||||||
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
return b.headerByHash(hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerByHash retrieves a header from the database by hash without Lock.
|
|
||||||
func (b *SimulatedBackend) headerByHash(hash common.Hash) (*types.Header, error) {
|
|
||||||
if hash == b.pendingBlock.Hash() {
|
if hash == b.pendingBlock.Hash() {
|
||||||
return b.pendingBlock.Header(), nil
|
return b.pendingBlock.Header(), nil
|
||||||
}
|
}
|
||||||
|
|
@ -459,22 +436,6 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
|
||||||
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
|
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
|
||||||
return nil, errBlockNumberUnsupported
|
return nil, errBlockNumberUnsupported
|
||||||
}
|
}
|
||||||
return b.callContractAtHead(ctx, call)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallContractAtHash executes a contract call on a specific block hash.
|
|
||||||
func (b *SimulatedBackend) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
|
|
||||||
if blockHash != b.blockchain.CurrentBlock().Hash() {
|
|
||||||
return nil, errBlockHashUnsupported
|
|
||||||
}
|
|
||||||
return b.callContractAtHead(ctx, call)
|
|
||||||
}
|
|
||||||
|
|
||||||
// callContractAtHead executes a contract call against the latest block state.
|
|
||||||
func (b *SimulatedBackend) callContractAtHead(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
|
|
||||||
stateDB, err := b.blockchain.State()
|
stateDB, err := b.blockchain.State()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -996,43 +996,6 @@ func TestCodeAt(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCodeAtHash(t *testing.T) {
|
|
||||||
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
|
||||||
sim := simTestBackend(testAddr)
|
|
||||||
defer sim.Close()
|
|
||||||
bgCtx := context.Background()
|
|
||||||
code, err := sim.CodeAtHash(bgCtx, testAddr, sim.Blockchain().CurrentHeader().Hash())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("could not get code at test addr: %v", err)
|
|
||||||
}
|
|
||||||
if len(code) != 0 {
|
|
||||||
t.Errorf("got code for account that does not have contract code")
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed, err := abi.JSON(strings.NewReader(abiJSON))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("could not get code at test addr: %v", err)
|
|
||||||
}
|
|
||||||
auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
|
|
||||||
contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
|
|
||||||
}
|
|
||||||
|
|
||||||
blockHash := sim.Commit()
|
|
||||||
code, err = sim.CodeAtHash(bgCtx, contractAddr, blockHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("could not get code at test addr: %v", err)
|
|
||||||
}
|
|
||||||
if len(code) == 0 {
|
|
||||||
t.Errorf("did not get code for account that has contract code")
|
|
||||||
}
|
|
||||||
// ensure code received equals code deployed
|
|
||||||
if !bytes.Equal(code, common.FromHex(deployedCode)) {
|
|
||||||
t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
|
// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
|
||||||
//
|
//
|
||||||
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
|
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
|
||||||
|
|
@ -1075,7 +1038,7 @@ func TestPendingAndCallContract(t *testing.T) {
|
||||||
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
blockHash := sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
// make sure you can call the contract
|
// make sure you can call the contract
|
||||||
res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
|
res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
|
||||||
|
|
@ -1093,23 +1056,6 @@ func TestPendingAndCallContract(t *testing.T) {
|
||||||
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
|
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
|
||||||
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure you can call the contract by hash
|
|
||||||
res, err = sim.CallContractAtHash(bgCtx, ethereum.CallMsg{
|
|
||||||
From: testAddr,
|
|
||||||
To: &addr,
|
|
||||||
Data: input,
|
|
||||||
}, blockHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("could not call receive method on contract: %v", err)
|
|
||||||
}
|
|
||||||
if len(res) == 0 {
|
|
||||||
t.Errorf("result of contract call was empty: %v", res)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
|
|
||||||
t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test is based on the following contract:
|
// This test is based on the following contract:
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ type CallOpts struct {
|
||||||
Pending bool // Whether to operate on the pending state or the last known one
|
Pending bool // Whether to operate on the pending state or the last known one
|
||||||
From common.Address // Optional the sender address, otherwise the first account is used
|
From common.Address // Optional the sender address, otherwise the first account is used
|
||||||
BlockNumber *big.Int // Optional the block number on which the call should be performed
|
BlockNumber *big.Int // Optional the block number on which the call should be performed
|
||||||
BlockHash common.Hash // Optional the block hash on which the call should be performed
|
|
||||||
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,23 +189,6 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
|
||||||
return ErrNoCode
|
return ErrNoCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if opts.BlockHash != (common.Hash{}) {
|
|
||||||
bh, ok := c.caller.(BlockHashContractCaller)
|
|
||||||
if !ok {
|
|
||||||
return ErrNoBlockHashState
|
|
||||||
}
|
|
||||||
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(output) == 0 {
|
|
||||||
// Make sure we have a contract to operate on, and bail out otherwise.
|
|
||||||
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(code) == 0 {
|
|
||||||
return ErrNoCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -114,26 +114,6 @@ func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ether
|
||||||
return mc.pendingCallContractBytes, mc.pendingCallContractErr
|
return mc.pendingCallContractBytes, mc.pendingCallContractErr
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockBlockHashCaller struct {
|
|
||||||
*mockCaller
|
|
||||||
codeAtHashBytes []byte
|
|
||||||
codeAtHashErr error
|
|
||||||
codeAtHashCalled bool
|
|
||||||
callContractAtHashCalled bool
|
|
||||||
callContractAtHashBytes []byte
|
|
||||||
callContractAtHashErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) {
|
|
||||||
mc.codeAtHashCalled = true
|
|
||||||
return mc.codeAtHashBytes, mc.codeAtHashErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) {
|
|
||||||
mc.callContractAtHashCalled = true
|
|
||||||
return mc.callContractAtHashBytes, mc.callContractAtHashErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPassingBlockNumber(t *testing.T) {
|
func TestPassingBlockNumber(t *testing.T) {
|
||||||
mc := &mockPendingCaller{
|
mc := &mockPendingCaller{
|
||||||
mockCaller: &mockCaller{
|
mockCaller: &mockCaller{
|
||||||
|
|
@ -420,15 +400,6 @@ func TestCall(t *testing.T) {
|
||||||
Pending: true,
|
Pending: true,
|
||||||
},
|
},
|
||||||
method: method,
|
method: method,
|
||||||
}, {
|
|
||||||
name: "ok hash",
|
|
||||||
mc: &mockBlockHashCaller{
|
|
||||||
codeAtHashBytes: []byte{0},
|
|
||||||
},
|
|
||||||
opts: &bind.CallOpts{
|
|
||||||
BlockHash: common.Hash{0xaa},
|
|
||||||
},
|
|
||||||
method: method,
|
|
||||||
}, {
|
}, {
|
||||||
name: "pack error, no method",
|
name: "pack error, no method",
|
||||||
mc: new(mockCaller),
|
mc: new(mockCaller),
|
||||||
|
|
@ -442,14 +413,6 @@ func TestCall(t *testing.T) {
|
||||||
},
|
},
|
||||||
method: method,
|
method: method,
|
||||||
wantErrExact: bind.ErrNoPendingState,
|
wantErrExact: bind.ErrNoPendingState,
|
||||||
}, {
|
|
||||||
name: "interface error, blockHash but not a BlockHashContractCaller",
|
|
||||||
mc: new(mockCaller),
|
|
||||||
opts: &bind.CallOpts{
|
|
||||||
BlockHash: common.Hash{0xaa},
|
|
||||||
},
|
|
||||||
method: method,
|
|
||||||
wantErrExact: bind.ErrNoBlockHashState,
|
|
||||||
}, {
|
}, {
|
||||||
name: "pending call canceled",
|
name: "pending call canceled",
|
||||||
mc: &mockPendingCaller{
|
mc: &mockPendingCaller{
|
||||||
|
|
@ -497,34 +460,6 @@ func TestCall(t *testing.T) {
|
||||||
mc: new(mockCaller),
|
mc: new(mockCaller),
|
||||||
method: method,
|
method: method,
|
||||||
wantErrExact: bind.ErrNoCode,
|
wantErrExact: bind.ErrNoCode,
|
||||||
}, {
|
|
||||||
name: "call contract at hash error",
|
|
||||||
mc: &mockBlockHashCaller{
|
|
||||||
callContractAtHashErr: context.DeadlineExceeded,
|
|
||||||
},
|
|
||||||
opts: &bind.CallOpts{
|
|
||||||
BlockHash: common.Hash{0xaa},
|
|
||||||
},
|
|
||||||
method: method,
|
|
||||||
wantErrExact: context.DeadlineExceeded,
|
|
||||||
}, {
|
|
||||||
name: "code at error",
|
|
||||||
mc: &mockBlockHashCaller{
|
|
||||||
codeAtHashErr: errors.New(""),
|
|
||||||
},
|
|
||||||
opts: &bind.CallOpts{
|
|
||||||
BlockHash: common.Hash{0xaa},
|
|
||||||
},
|
|
||||||
method: method,
|
|
||||||
wantErr: true,
|
|
||||||
}, {
|
|
||||||
name: "no code at hash",
|
|
||||||
mc: new(mockBlockHashCaller),
|
|
||||||
opts: &bind.CallOpts{
|
|
||||||
BlockHash: common.Hash{0xaa},
|
|
||||||
},
|
|
||||||
method: method,
|
|
||||||
wantErrExact: bind.ErrNoCode,
|
|
||||||
}, {
|
}, {
|
||||||
name: "unpack error missing arg",
|
name: "unpack error missing arg",
|
||||||
mc: &mockCaller{
|
mc: &mockCaller{
|
||||||
|
|
|
||||||
|
|
@ -370,13 +370,6 @@ func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNu
|
||||||
return (*big.Int)(&result), err
|
return (*big.Int)(&result), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceAtHash returns the wei balance of the given account.
|
|
||||||
func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) {
|
|
||||||
var result hexutil.Big
|
|
||||||
err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
|
|
||||||
return (*big.Int)(&result), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorageAt returns the value of key in the contract storage of the given account.
|
// StorageAt returns the value of key in the contract storage of the given account.
|
||||||
// The block number can be nil, in which case the value is taken from the latest known block.
|
// The block number can be nil, in which case the value is taken from the latest known block.
|
||||||
func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
|
func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
|
||||||
|
|
@ -385,13 +378,6 @@ func (ec *Client) StorageAt(ctx context.Context, account common.Address, key com
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageAtHash returns the value of key in the contract storage of the given account.
|
|
||||||
func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) {
|
|
||||||
var result hexutil.Bytes
|
|
||||||
err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false))
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeAt returns the contract code of the given account.
|
// CodeAt returns the contract code of the given account.
|
||||||
// The block number can be nil, in which case the code is taken from the latest known block.
|
// The block number can be nil, in which case the code is taken from the latest known block.
|
||||||
func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
|
func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
|
||||||
|
|
@ -400,13 +386,6 @@ func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumbe
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeAtHash returns the contract code of the given account.
|
|
||||||
func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) {
|
|
||||||
var result hexutil.Bytes
|
|
||||||
err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NonceAt returns the account nonce of the given account.
|
// NonceAt returns the account nonce of the given account.
|
||||||
// The block number can be nil, in which case the nonce is taken from the latest known block.
|
// The block number can be nil, in which case the nonce is taken from the latest known block.
|
||||||
func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
|
func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
|
||||||
|
|
@ -415,13 +394,6 @@ func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumb
|
||||||
return uint64(result), err
|
return uint64(result), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonceAtHash returns the account nonce of the given account.
|
|
||||||
func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) {
|
|
||||||
var result hexutil.Uint64
|
|
||||||
err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
|
|
||||||
return uint64(result), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
// FilterLogs executes a filter query.
|
// FilterLogs executes a filter query.
|
||||||
|
|
|
||||||
|
|
@ -584,11 +584,6 @@ func testCallContract(t *testing.T, client *rpc.Client) {
|
||||||
func testAtFunctions(t *testing.T, client *rpc.Client) {
|
func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
ec := NewClient(client)
|
ec := NewClient(client)
|
||||||
|
|
||||||
block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("BlockByNumber error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// send a transaction for some interesting pending status
|
// send a transaction for some interesting pending status
|
||||||
sendTransaction(ec)
|
sendTransaction(ec)
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
@ -606,13 +601,6 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
hashBalance, err := ec.BalanceAtHash(context.Background(), testAddr, block.Hash())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if balance.Cmp(hashBalance) == 0 {
|
|
||||||
t.Fatalf("unexpected balance at hash: %v %v", balance, hashBalance)
|
|
||||||
}
|
|
||||||
penBalance, err := ec.PendingBalanceAt(context.Background(), testAddr)
|
penBalance, err := ec.PendingBalanceAt(context.Background(), testAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
|
@ -625,13 +613,6 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
hashNonce, err := ec.NonceAtHash(context.Background(), testAddr, block.Hash())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if hashNonce == nonce {
|
|
||||||
t.Fatalf("unexpected nonce at hash: %v %v", nonce, hashNonce)
|
|
||||||
}
|
|
||||||
penNonce, err := ec.PendingNonceAt(context.Background(), testAddr)
|
penNonce, err := ec.PendingNonceAt(context.Background(), testAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
|
@ -644,13 +625,6 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
hashStorage, err := ec.StorageAtHash(context.Background(), testAddr, common.Hash{}, block.Hash())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(storage, hashStorage) {
|
|
||||||
t.Fatalf("unexpected storage at hash: %v %v", storage, hashStorage)
|
|
||||||
}
|
|
||||||
penStorage, err := ec.PendingStorageAt(context.Background(), testAddr, common.Hash{})
|
penStorage, err := ec.PendingStorageAt(context.Background(), testAddr, common.Hash{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
|
@ -663,13 +637,6 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
hashCode, err := ec.CodeAtHash(context.Background(), common.Address{}, block.Hash())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(code, hashCode) {
|
|
||||||
t.Fatalf("unexpected code at hash: %v %v", code, hashCode)
|
|
||||||
}
|
|
||||||
penCode, err := ec.PendingCodeAt(context.Background(), testAddr)
|
penCode, err := ec.PendingCodeAt(context.Background(), testAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue