github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/light/odr.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:39</date> 10 //</624450096498479104> 11 12 13 //package light实现可按需检索的状态和链对象 14 //对于以太坊Light客户端。 15 package light 16 17 import ( 18 "context" 19 "errors" 20 "math/big" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core" 24 "github.com/ethereum/go-ethereum/core/rawdb" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/ethereum/go-ethereum/ethdb" 27 ) 28 29 //noodr是当odr 30 //不需要服务。 31 var NoOdr = context.Background() 32 33 //如果没有能够为排队请求提供服务的对等方可用,则返回errnopeers。 34 var ErrNoPeers = errors.New("no suitable peers available") 35 36 //odr backend是后端服务的接口,用于处理odr检索类型 37 type OdrBackend interface { 38 Database() ethdb.Database 39 ChtIndexer() *core.ChainIndexer 40 BloomTrieIndexer() *core.ChainIndexer 41 BloomIndexer() *core.ChainIndexer 42 Retrieve(ctx context.Context, req OdrRequest) error 43 IndexerConfig() *IndexerConfig 44 } 45 46 //ODRRequest是一个用于检索请求的接口 47 type OdrRequest interface { 48 StoreResult(db ethdb.Database) 49 } 50 51 //trieid标识状态或帐户存储trie 52 type TrieID struct { 53 BlockHash, Root common.Hash 54 BlockNumber uint64 55 AccKey []byte 56 } 57 58 //state trieid返回属于某个块的state trie的trieid 59 //标题。 60 func StateTrieID(header *types.Header) *TrieID { 61 return &TrieID{ 62 BlockHash: header.Hash(), 63 BlockNumber: header.Number.Uint64(), 64 AccKey: nil, 65 Root: header.Root, 66 } 67 } 68 69 //storage trieid返回给定帐户上合同存储trie的trieid 70 //一个给定的国家的。它还需要trie的根散列 71 //检查Merkle校样。 72 func StorageTrieID(state *TrieID, addrHash, root common.Hash) *TrieID { 73 return &TrieID{ 74 BlockHash: state.BlockHash, 75 BlockNumber: state.BlockNumber, 76 AccKey: addrHash[:], 77 Root: root, 78 } 79 } 80 81 //trieRequest是状态/存储trie项的ODR请求类型 82 type TrieRequest struct { 83 OdrRequest 84 Id *TrieID 85 Key []byte 86 Proof *NodeSet 87 } 88 89 //storeresult将检索到的数据存储在本地数据库中 90 func (req *TrieRequest) StoreResult(db ethdb.Database) { 91 req.Proof.Store(db) 92 } 93 94 //code request是用于检索合同代码的ODR请求类型 95 type CodeRequest struct { 96 OdrRequest 97 Id *TrieID //账户参考存储检索 98 Hash common.Hash 99 Data []byte 100 } 101 102 //storeresult将检索到的数据存储在本地数据库中 103 func (req *CodeRequest) StoreResult(db ethdb.Database) { 104 db.Put(req.Hash[:], req.Data) 105 } 106 107 //BlockRequest是用于检索块体的ODR请求类型 108 type BlockRequest struct { 109 OdrRequest 110 Hash common.Hash 111 Number uint64 112 Rlp []byte 113 } 114 115 //storeresult将检索到的数据存储在本地数据库中 116 func (req *BlockRequest) StoreResult(db ethdb.Database) { 117 rawdb.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp) 118 } 119 120 //ReceiptsRequest是用于检索块体的ODR请求类型 121 type ReceiptsRequest struct { 122 OdrRequest 123 Hash common.Hash 124 Number uint64 125 Receipts types.Receipts 126 } 127 128 //storeresult将检索到的数据存储在本地数据库中 129 func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { 130 rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) 131 } 132 133 //chtRequest是状态/存储trie项的odr请求类型 134 type ChtRequest struct { 135 OdrRequest 136 Config *IndexerConfig 137 ChtNum, BlockNum uint64 138 ChtRoot common.Hash 139 Header *types.Header 140 Td *big.Int 141 Proof *NodeSet 142 } 143 144 //storeresult将检索到的数据存储在本地数据库中 145 func (req *ChtRequest) StoreResult(db ethdb.Database) { 146 hash, num := req.Header.Hash(), req.Header.Number.Uint64() 147 148 rawdb.WriteHeader(db, req.Header) 149 rawdb.WriteTd(db, hash, num, req.Td) 150 rawdb.WriteCanonicalHash(db, hash, num) 151 } 152 153 //BloomRequest是用于从CHT结构检索Bloom筛选器的ODR请求类型。 154 type BloomRequest struct { 155 OdrRequest 156 Config *IndexerConfig 157 BloomTrieNum uint64 158 BitIdx uint 159 SectionIndexList []uint64 160 BloomTrieRoot common.Hash 161 BloomBits [][]byte 162 Proofs *NodeSet 163 } 164 165 //storeresult将检索到的数据存储在本地数据库中 166 func (req *BloomRequest) StoreResult(db ethdb.Database) { 167 for i, sectionIdx := range req.SectionIndexList { 168 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*req.Config.BloomTrieSize-1) 169 //如果没有为此节头编号存储规范散列,我们仍然将其存储在 170 //一个零分区头的键。如果我们仍然没有规范的 171 //搞砸。在不太可能的情况下,我们从那以后就检索到了段头散列,我们只检索 172 //再次从网络中得到位矢量。 173 rawdb.WriteBloomBits(db, req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) 174 } 175 } 176