From 2b546660187e8b693b6bbe5ec0fc74bfc008d1d3 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 11 Jun 2019 13:12:33 +0200 Subject: [PATCH] ethclient, internal/ethapi: add support for EIP-695 (eth_chainId) (#19694) EIP-695 was written in 2017. Parity and Infura have support for this method and we should, too. --- ethclient/ethclient.go | 10 ++++++++++ ethclient/ethclient_test.go | 16 ++++++++++++++++ internal/ethapi/api.go | 5 +++++ 3 files changed, 31 insertions(+) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index aedf2814a..0a6f73ab5 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -61,6 +61,16 @@ func (ec *Client) Close() { // Blockchain Access +// ChainId retrieves the current chain ID for transaction replay protection. +func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { + var result hexutil.Big + err := ec.c.CallContext(ctx, &result, "eth_chainId") + if err != nil { + return nil, err + } + return (*big.Int)(&result), err +} + // BlockByHash returns the given full block. // // Note that loading full blocks requires two requests. Use HeaderByHash diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 2e464cd42..3576d4870 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -319,3 +319,19 @@ func TestTransactionInBlockInterrupted(t *testing.T) { t.Fatal("error should not be nil") } } + +func TestChainID(t *testing.T) { + backend, _ := newTestBackend(t) + client, _ := backend.Attach() + defer backend.Stop() + defer client.Close() + ec := NewClient(client) + + id, err := ec.ChainID(context.Background()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 { + t.Fatalf("ChainID returned wrong number: %+v", id) + } +} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 07142d66b..4132ff144 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -529,6 +529,11 @@ func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI { return &PublicBlockChainAPI{b} } +// ChainId returns the chainID value for transaction replay protection. +func (s *PublicBlockChainAPI) ChainId() *hexutil.Big { + return (*hexutil.Big)(s.b.ChainConfig().ChainID) +} + // BlockNumber returns the block number of the chain head. func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 { header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available