diff options
author | Felix Lange <fjl@twurst.com> | 2016-11-29 22:54:06 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2016-12-05 17:57:11 +0800 |
commit | 3bc0fe1ee3183311efe851aca8fd10d5a5433929 (patch) | |
tree | ed6e33c3af93115e02e508f86b993a6bf64f5328 /ethclient | |
parent | fa0cc274009670209fd71b1462dcdde3b431d64f (diff) | |
download | dexon-3bc0fe1ee3183311efe851aca8fd10d5a5433929.tar.gz dexon-3bc0fe1ee3183311efe851aca8fd10d5a5433929.tar.zst dexon-3bc0fe1ee3183311efe851aca8fd10d5a5433929.zip |
ethclient, ethereum: add NotFound, split transactions out of ChainReader
ethclient now returns ethereum.NotFound if the server returns null and
no error while accessing blockchain data.
The light client cannot provide arbitrary transactions. The change to
split transaction access into its own interface emphasizes that
transactions should not be relied on and recommends use of logs.
Diffstat (limited to 'ethclient')
-rw-r--r-- | ethclient/ethclient.go | 49 | ||||
-rw-r--r-- | ethclient/ethclient_test.go | 2 |
2 files changed, 35 insertions, 16 deletions
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index b23e9baa3..4daebda92 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -81,6 +81,8 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface err := ec.c.CallContext(ctx, &raw, method, args...) if err != nil { return nil, err + } else if len(raw) == 0 { + return nil, ethereum.NotFound } // Decode header and transactions. var head *types.Header @@ -135,6 +137,9 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { var head *types.Header err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) + if err == nil && head == nil { + err = ethereum.NotFound + } return head, err } @@ -143,19 +148,31 @@ func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.He func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { var head *types.Header err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) + if err == nil && head == nil { + err = ethereum.NotFound + } return head, err } // TransactionByHash returns the transaction with the given hash. -func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, error) { - var tx *types.Transaction - err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByHash", hash) - if err == nil { - if _, r, _ := tx.RawSignatureValues(); r == nil { - return nil, fmt.Errorf("server returned transaction without signature") - } +func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { + var raw json.RawMessage + err = ec.c.CallContext(ctx, &raw, "eth_getTransactionByHash", hash) + if err != nil { + return nil, false, err + } else if len(raw) == 0 { + return nil, false, ethereum.NotFound } - return tx, err + if err := json.Unmarshal(raw, tx); err != nil { + return nil, false, err + } else if _, r, _ := tx.RawSignatureValues(); r == nil { + return nil, false, fmt.Errorf("server returned transaction without signature") + } + var block struct{ BlockHash *common.Hash } + if err := json.Unmarshal(raw, &block); err != nil { + return nil, false, err + } + return tx, block.BlockHash == nil, nil } // TransactionCount returns the total number of transactions in the given block. @@ -170,11 +187,9 @@ func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, var tx *types.Transaction err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, index) if err == nil { - var signer types.Signer = types.HomesteadSigner{} - if tx.Protected() { - signer = types.NewEIP155Signer(tx.ChainId()) - } - if _, r, _ := types.SignatureValues(signer, tx); r == nil { + if tx == nil { + return nil, ethereum.NotFound + } else if _, r, _ := tx.RawSignatureValues(); r == nil { return nil, fmt.Errorf("server returned transaction without signature") } } @@ -186,8 +201,12 @@ func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { var r *types.Receipt err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) - if err == nil && r != nil && len(r.PostState) == 0 { - return nil, fmt.Errorf("server returned receipt without post state") + if err == nil { + if r == nil { + return nil, ethereum.NotFound + } else if len(r.PostState) == 0 { + return nil, fmt.Errorf("server returned receipt without post state") + } } return r, err } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 102c0d3b2..178eb2be9 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -21,9 +21,9 @@ import "github.com/ethereum/go-ethereum" // Verify that Client implements the ethereum interfaces. var ( _ = ethereum.ChainReader(&Client{}) + _ = ethereum.TransactionReader(&Client{}) _ = ethereum.ChainStateReader(&Client{}) _ = ethereum.ChainSyncReader(&Client{}) - _ = ethereum.ChainHeadEventer(&Client{}) _ = ethereum.ContractCaller(&Client{}) _ = ethereum.GasEstimator(&Client{}) _ = ethereum.GasPricer(&Client{}) |