github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:41</date> 10 //</624342645627424768> 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 } 44 45 //ODRRequest是一个用于检索请求的接口 46 type OdrRequest interface { 47 StoreResult(db ethdb.Database) 48 } 49 50 //trieid标识状态或帐户存储trie 51 type TrieID struct { 52 BlockHash, Root common.Hash 53 BlockNumber uint64 54 AccKey []byte 55 } 56 57 //state trieid返回属于某个块的state trie的trieid 58 //标题。 59 func StateTrieID(header *types.Header) *TrieID { 60 return &TrieID{ 61 BlockHash: header.Hash(), 62 BlockNumber: header.Number.Uint64(), 63 AccKey: nil, 64 Root: header.Root, 65 } 66 } 67 68 //storage trieid返回给定帐户上合同存储trie的trieid 69 //一个给定的国家的。它还需要trie的根散列 70 //检查Merkle校样。 71 func StorageTrieID(state *TrieID, addrHash, root common.Hash) *TrieID { 72 return &TrieID{ 73 BlockHash: state.BlockHash, 74 BlockNumber: state.BlockNumber, 75 AccKey: addrHash[:], 76 Root: root, 77 } 78 } 79 80 //trieRequest是状态/存储trie项的ODR请求类型 81 type TrieRequest struct { 82 OdrRequest 83 Id *TrieID 84 Key []byte 85 Proof *NodeSet 86 } 87 88 //storeresult将检索到的数据存储在本地数据库中 89 func (req *TrieRequest) StoreResult(db ethdb.Database) { 90 req.Proof.Store(db) 91 } 92 93 //code request是用于检索合同代码的ODR请求类型 94 type CodeRequest struct { 95 OdrRequest 96 Id *TrieID //账户参考存储检索 97 Hash common.Hash 98 Data []byte 99 } 100 101 //storeresult将检索到的数据存储在本地数据库中 102 func (req *CodeRequest) StoreResult(db ethdb.Database) { 103 db.Put(req.Hash[:], req.Data) 104 } 105 106 //BlockRequest是用于检索块体的ODR请求类型 107 type BlockRequest struct { 108 OdrRequest 109 Hash common.Hash 110 Number uint64 111 Rlp []byte 112 } 113 114 //storeresult将检索到的数据存储在本地数据库中 115 func (req *BlockRequest) StoreResult(db ethdb.Database) { 116 rawdb.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp) 117 } 118 119 //ReceiptsRequest是用于检索块体的ODR请求类型 120 type ReceiptsRequest struct { 121 OdrRequest 122 Hash common.Hash 123 Number uint64 124 Receipts types.Receipts 125 } 126 127 //storeresult将检索到的数据存储在本地数据库中 128 func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { 129 rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) 130 } 131 132 //chtRequest是状态/存储trie项的odr请求类型 133 type ChtRequest struct { 134 OdrRequest 135 ChtNum, BlockNum uint64 136 ChtRoot common.Hash 137 Header *types.Header 138 Td *big.Int 139 Proof *NodeSet 140 } 141 142 //storeresult将检索到的数据存储在本地数据库中 143 func (req *ChtRequest) StoreResult(db ethdb.Database) { 144 hash, num := req.Header.Hash(), req.Header.Number.Uint64() 145 146 rawdb.WriteHeader(db, req.Header) 147 rawdb.WriteTd(db, hash, num, req.Td) 148 rawdb.WriteCanonicalHash(db, hash, num) 149 } 150 151 //BloomRequest是用于从CHT结构检索Bloom筛选器的ODR请求类型。 152 type BloomRequest struct { 153 OdrRequest 154 BloomTrieNum uint64 155 BitIdx uint 156 SectionIdxList []uint64 157 BloomTrieRoot common.Hash 158 BloomBits [][]byte 159 Proofs *NodeSet 160 } 161 162 //storeresult将检索到的数据存储在本地数据库中 163 func (req *BloomRequest) StoreResult(db ethdb.Database) { 164 for i, sectionIdx := range req.SectionIdxList { 165 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*BloomTrieFrequency-1) 166 //如果没有为此节头编号存储规范散列,我们仍然将其存储在 167 //一个零分区头的键。如果我们仍然没有规范的 168 //搞砸。在不太可能的情况下,我们从那以后就检索到了段头散列,我们只检索 169 //再次从网络中得到位矢量。 170 rawdb.WriteBloomBits(db, req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) 171 } 172 } 173