github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/light/odr.go (about) 1 // Copyright 2015 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum 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/SmartMeshFoundation/Spectrum/common" 26 "github.com/SmartMeshFoundation/Spectrum/core" 27 "github.com/SmartMeshFoundation/Spectrum/core/types" 28 "github.com/SmartMeshFoundation/Spectrum/ethdb" 29 ) 30 31 // NoOdr is the default context passed to an ODR capable function when the ODR 32 // service is not required. 33 var NoOdr = context.Background() 34 35 // OdrBackend is an interface to a backend service that handles ODR retrievals type 36 type OdrBackend interface { 37 Database() ethdb.Database 38 ChtIndexer() *core.ChainIndexer 39 BloomTrieIndexer() *core.ChainIndexer 40 BloomIndexer() *core.ChainIndexer 41 Retrieve(ctx context.Context, req OdrRequest) error 42 } 43 44 // OdrRequest is an interface for retrieval requests 45 type OdrRequest interface { 46 StoreResult(db ethdb.Database) 47 } 48 49 // TrieID identifies a state or account storage trie 50 type TrieID struct { 51 BlockHash, Root common.Hash 52 BlockNumber uint64 53 AccKey []byte 54 } 55 56 // StateTrieID returns a TrieID for a state trie belonging to a certain block 57 // header. 58 func StateTrieID(header *types.Header) *TrieID { 59 return &TrieID{ 60 BlockHash: header.Hash(), 61 BlockNumber: header.Number.Uint64(), 62 AccKey: nil, 63 Root: header.Root, 64 } 65 } 66 67 // StorageTrieID returns a TrieID for a contract storage trie at a given account 68 // of a given state trie. It also requires the root hash of the trie for 69 // checking Merkle proofs. 70 func StorageTrieID(state *TrieID, addrHash, root common.Hash) *TrieID { 71 return &TrieID{ 72 BlockHash: state.BlockHash, 73 BlockNumber: state.BlockNumber, 74 AccKey: addrHash[:], 75 Root: root, 76 } 77 } 78 79 // TrieRequest is the ODR request type for state/storage trie entries 80 type TrieRequest struct { 81 OdrRequest 82 Id *TrieID 83 Key []byte 84 Proof *NodeSet 85 } 86 87 // StoreResult stores the retrieved data in local database 88 func (req *TrieRequest) StoreResult(db ethdb.Database) { 89 req.Proof.Store(db) 90 } 91 92 // CodeRequest is the ODR request type for retrieving contract code 93 type CodeRequest struct { 94 OdrRequest 95 Id *TrieID // references storage trie of the account 96 Hash common.Hash 97 Data []byte 98 } 99 100 // StoreResult stores the retrieved data in local database 101 func (req *CodeRequest) StoreResult(db ethdb.Database) { 102 db.Put(req.Hash[:], req.Data) 103 } 104 105 // BlockRequest is the ODR request type for retrieving block bodies 106 type BlockRequest struct { 107 OdrRequest 108 Hash common.Hash 109 Number uint64 110 Rlp []byte 111 } 112 113 // StoreResult stores the retrieved data in local database 114 func (req *BlockRequest) StoreResult(db ethdb.Database) { 115 core.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp) 116 } 117 118 // ReceiptsRequest is the ODR request type for retrieving block bodies 119 type ReceiptsRequest struct { 120 OdrRequest 121 Hash common.Hash 122 Number uint64 123 Receipts types.Receipts 124 } 125 126 // StoreResult stores the retrieved data in local database 127 func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { 128 core.WriteBlockReceipts(db, req.Hash, req.Number, req.Receipts) 129 } 130 131 // ChtRequest is the ODR request type for state/storage trie entries 132 type ChtRequest struct { 133 OdrRequest 134 ChtNum, BlockNum uint64 135 ChtRoot common.Hash 136 Header *types.Header 137 Td *big.Int 138 Proof *NodeSet 139 } 140 141 // StoreResult stores the retrieved data in local database 142 func (req *ChtRequest) StoreResult(db ethdb.Database) { 143 // if there is a canonical hash, there is a header too 144 core.WriteHeader(db, req.Header) 145 hash, num := req.Header.Hash(), req.Header.Number.Uint64() 146 core.WriteTd(db, hash, num, req.Td) 147 core.WriteCanonicalHash(db, hash, num) 148 } 149 150 // BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure 151 type BloomRequest struct { 152 OdrRequest 153 BloomTrieNum uint64 154 BitIdx uint 155 SectionIdxList []uint64 156 BloomTrieRoot common.Hash 157 BloomBits [][]byte 158 Proofs *NodeSet 159 } 160 161 // StoreResult stores the retrieved data in local database 162 func (req *BloomRequest) StoreResult(db ethdb.Database) { 163 for i, sectionIdx := range req.SectionIdxList { 164 sectionHead := core.GetCanonicalHash(db, (sectionIdx+1)*BloomTrieFrequency-1) 165 // if we don't have the canonical hash stored for this section head number, we'll still store it under 166 // a key with a zero sectionHead. GetBloomBits will look there too if we still don't have the canonical 167 // hash. In the unlikely case we've retrieved the section head hash since then, we'll just retrieve the 168 // bit vector again from the network. 169 core.WriteBloomBits(db, req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) 170 } 171 }