github.com/m3shine/gochain@v2.2.26+incompatible/light/odr.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package light implements on-demand retrieval capable state and chain objects 18 // for the Ethereum Light Client. 19 package light 20 21 import ( 22 "context" 23 "math/big" 24 25 "github.com/gochain-io/gochain/common" 26 "github.com/gochain-io/gochain/core" 27 "github.com/gochain-io/gochain/core/rawdb" 28 "github.com/gochain-io/gochain/core/types" 29 "github.com/gochain-io/gochain/log" 30 ) 31 32 // NoOdr is the default context passed to an ODR capable function when the ODR 33 // service is not required. 34 var NoOdr = context.Background() 35 36 // OdrBackend is an interface to a backend service that handles ODR retrievals type 37 type OdrBackend interface { 38 Database() common.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 is an interface for retrieval requests 46 type OdrRequest interface { 47 StoreResult(db common.Database) 48 } 49 50 // TrieID identifies a state or account storage trie 51 type TrieID struct { 52 BlockHash, Root common.Hash 53 BlockNumber uint64 54 AccKey []byte 55 } 56 57 // StateTrieID returns a TrieID for a state trie belonging to a certain block 58 // header. 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 // StorageTrieID returns a TrieID for a contract storage trie at a given account 69 // of a given state trie. It also requires the root hash of the trie for 70 // checking Merkle proofs. 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 is the ODR request type for state/storage trie entries 81 type TrieRequest struct { 82 OdrRequest 83 Id *TrieID 84 Key []byte 85 Proof *NodeSet 86 } 87 88 // StoreResult stores the retrieved data in local database 89 func (req *TrieRequest) StoreResult(db common.Database) { 90 req.Proof.Store(db.GlobalTable()) 91 } 92 93 // CodeRequest is the ODR request type for retrieving contract code 94 type CodeRequest struct { 95 OdrRequest 96 Id *TrieID // references storage trie of the account 97 Hash common.Hash 98 Data []byte 99 } 100 101 // StoreResult stores the retrieved data in local database 102 func (req *CodeRequest) StoreResult(db common.Database) { 103 if err := db.GlobalTable().Put(req.Hash[:], req.Data); err != nil { 104 log.Error("Cannot store code request result", "err", err) 105 } 106 } 107 108 // BlockRequest is the ODR request type for retrieving block bodies 109 type BlockRequest struct { 110 OdrRequest 111 Hash common.Hash 112 Number uint64 113 Rlp []byte 114 } 115 116 // StoreResult stores the retrieved data in local database 117 func (req *BlockRequest) StoreResult(db common.Database) { 118 rawdb.WriteBodyRLP(db.BodyTable(), req.Hash, req.Number, req.Rlp) 119 } 120 121 // ReceiptsRequest is the ODR request type for retrieving block bodies 122 type ReceiptsRequest struct { 123 OdrRequest 124 Hash common.Hash 125 Number uint64 126 Receipts types.Receipts 127 } 128 129 // StoreResult stores the retrieved data in local database 130 func (req *ReceiptsRequest) StoreResult(db common.Database) { 131 rawdb.WriteReceipts(db.ReceiptTable(), req.Hash, req.Number, req.Receipts) 132 } 133 134 // ChtRequest is the ODR request type for state/storage trie entries 135 type ChtRequest struct { 136 OdrRequest 137 ChtNum, BlockNum uint64 138 ChtRoot common.Hash 139 Header *types.Header 140 Td *big.Int 141 Proof *NodeSet 142 } 143 144 // StoreResult stores the retrieved data in local database 145 func (req *ChtRequest) StoreResult(db common.Database) { 146 // if there is a canonical hash, there is a header too 147 rawdb.WriteHeader(db.GlobalTable(), db.HeaderTable(), req.Header) 148 hash, num := req.Header.Hash(), req.Header.Number.Uint64() 149 rawdb.WriteTd(db.GlobalTable(), hash, num, req.Td) 150 rawdb.WriteCanonicalHash(db, hash, num) 151 } 152 153 // BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure 154 type BloomRequest struct { 155 OdrRequest 156 BloomTrieNum uint64 157 BitIdx uint 158 SectionIdxList []uint64 159 BloomTrieRoot common.Hash 160 BloomBits [][]byte 161 Proofs *NodeSet 162 } 163 164 // StoreResult stores the retrieved data in local database 165 func (req *BloomRequest) StoreResult(db common.Database) { 166 for i, sectionIdx := range req.SectionIdxList { 167 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*BloomTrieFrequency-1) 168 // if we don't have the canonical hash stored for this section head number, we'll still store it under 169 // a key with a zero sectionHead. GetBloomBits will look there too if we still don't have the canonical 170 // hash. In the unlikely case we've retrieved the section head hash since then, we'll just retrieve the 171 // bit vector again from the network. 172 rawdb.WriteBloomBits(db.GlobalTable(), req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) 173 } 174 }