forked from chenzhijie/go-web3
/
block.go
82 lines (77 loc) · 2.62 KB
/
block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package eth
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type rpcBlock struct {
Hash common.Hash `json:"hash"`
Transactions []*types.Transaction `json:"transactions"`
UncleHashes []common.Hash `json:"uncles"`
}
func (e *Eth) getBlock(method string, args ...interface{}) (*types.Block, error) {
var raw json.RawMessage
err := e.c.Call(method, &raw, args...)
if err != nil {
return nil, err
} else if len(raw) == 0 {
return nil, ethereum.NotFound
} else if bytes.Equal([]byte(raw), []byte("null")) {
return nil, ethereum.NotFound
}
// Decode header and transactions.
var head *types.Header
var body rpcBlock
if err := json.Unmarshal(raw, &head); err != nil {
return nil, err
}
if err := json.Unmarshal(raw, &body); err != nil {
return nil, err
}
if head == nil {
return nil, errors.New("json.Unmarshal header failed")
}
if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
return nil, fmt.Errorf("server returned non-empty uncle list but block header indicates no uncles")
}
if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles")
}
if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 {
return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions")
}
if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 {
return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions")
}
// Load uncles because they are not included in the block response.
var uncles []*types.Header
// TODO
// if len(body.UncleHashes) > 0 {
// uncles = make([]*types.Header, len(body.UncleHashes))
// reqs := make([]rpc.BatchElem, len(body.UncleHashes))
// for i := range reqs {
// reqs[i] = rpc.BatchElem{
// Method: "eth_getUncleByBlockHashAndIndex",
// Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
// Result: &uncles[i],
// }
// }
// if err := e.c.BatchCallContext(ctx, reqs); err != nil {
// return nil, err
// }
// for i := range reqs {
// if reqs[i].Error != nil {
// return nil, reqs[i].Error
// }
// if uncles[i] == nil {
// return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
// }
// }
// }
// Fill the sender cache of transactions in the block.
return types.NewBlockWithHeader(head).WithBody(body.Transactions, uncles), nil
}