github.com/ebakus/go-ebakus@v1.0.5-0.20200520105415-dbccef9ec421/light/odr.go (about) 1 // Copyright 2019 The ebakus/go-ebakus Authors 2 // This file is part of the ebakus/go-ebakus library. 3 // 4 // The ebakus/go-ebakus 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 ebakus/go-ebakus 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 ebakus/go-ebakus library. If not, see <http://www.gnu.org/licenses/>. 16 17 package light 18 19 import ( 20 "context" 21 "errors" 22 "math/big" 23 24 "github.com/ebakus/go-ebakus/common" 25 "github.com/ebakus/go-ebakus/core" 26 "github.com/ebakus/go-ebakus/core/rawdb" 27 "github.com/ebakus/go-ebakus/core/types" 28 "github.com/ebakus/go-ebakus/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 // ErrNoPeers is returned if no peers capable of serving a queued request are available 36 var ErrNoPeers = errors.New("no suitable peers available") 37 38 // OdrBackend is an interface to a backend service that handles ODR retrievals type 39 type OdrBackend interface { 40 Database() ethdb.Database 41 ChtIndexer() *core.ChainIndexer 42 BloomTrieIndexer() *core.ChainIndexer 43 BloomIndexer() *core.ChainIndexer 44 Retrieve(ctx context.Context, req OdrRequest) error 45 IndexerConfig() *IndexerConfig 46 } 47 48 // OdrRequest is an interface for retrieval requests 49 type OdrRequest interface { 50 StoreResult(db ethdb.Database) 51 } 52 53 // TrieID identifies a state or account storage trie 54 type TrieID struct { 55 BlockHash, Root common.Hash 56 BlockNumber uint64 57 AccKey []byte 58 } 59 60 // StateTrieID returns a TrieID for a state trie belonging to a certain block 61 // header. 62 func StateTrieID(header *types.Header) *TrieID { 63 return &TrieID{ 64 BlockHash: header.Hash(), 65 BlockNumber: header.Number.Uint64(), 66 AccKey: nil, 67 Root: header.Root, 68 } 69 } 70 71 // StorageTrieID returns a TrieID for a contract storage trie at a given account 72 // of a given state trie. It also requires the root hash of the trie for 73 // checking Merkle proofs. 74 func StorageTrieID(state *TrieID, addrHash, root common.Hash) *TrieID { 75 return &TrieID{ 76 BlockHash: state.BlockHash, 77 BlockNumber: state.BlockNumber, 78 AccKey: addrHash[:], 79 Root: root, 80 } 81 } 82 83 // TrieRequest is the ODR request type for state/storage trie entries 84 type TrieRequest struct { 85 OdrRequest 86 Id *TrieID 87 Key []byte 88 Proof *NodeSet 89 } 90 91 // StoreResult stores the retrieved data in local database 92 func (req *TrieRequest) StoreResult(db ethdb.Database) { 93 req.Proof.Store(db) 94 } 95 96 // CodeRequest is the ODR request type for retrieving contract code 97 type CodeRequest struct { 98 OdrRequest 99 Id *TrieID // references storage trie of the account 100 Hash common.Hash 101 Data []byte 102 } 103 104 // StoreResult stores the retrieved data in local database 105 func (req *CodeRequest) StoreResult(db ethdb.Database) { 106 db.Put(req.Hash[:], req.Data) 107 } 108 109 // BlockRequest is the ODR request type for retrieving block bodies 110 type BlockRequest struct { 111 OdrRequest 112 Hash common.Hash 113 Number uint64 114 Rlp []byte 115 } 116 117 // StoreResult stores the retrieved data in local database 118 func (req *BlockRequest) StoreResult(db ethdb.Database) { 119 rawdb.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp) 120 } 121 122 // ReceiptsRequest is the ODR request type for retrieving block bodies 123 type ReceiptsRequest struct { 124 OdrRequest 125 Untrusted bool // Indicator whether the result retrieved is trusted or not 126 Hash common.Hash 127 Number uint64 128 Header *types.Header 129 Receipts types.Receipts 130 } 131 132 // StoreResult stores the retrieved data in local database 133 func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { 134 if !req.Untrusted { 135 rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) 136 } 137 } 138 139 // ChtRequest is the ODR request type for state/storage trie entries 140 type ChtRequest struct { 141 OdrRequest 142 Untrusted bool // Indicator whether the result retrieved is trusted or not 143 PeerId string // The specified peer id from which to retrieve data. 144 Config *IndexerConfig 145 ChtNum, BlockNum uint64 146 ChtRoot common.Hash 147 Header *types.Header 148 Td *big.Int 149 Proof *NodeSet 150 } 151 152 // StoreResult stores the retrieved data in local database 153 func (req *ChtRequest) StoreResult(db ethdb.Database) { 154 hash, num := req.Header.Hash(), req.Header.Number.Uint64() 155 156 if !req.Untrusted { 157 rawdb.WriteHeader(db, req.Header) 158 rawdb.WriteCanonicalHash(db, hash, num) 159 } 160 } 161 162 // BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure 163 type BloomRequest struct { 164 OdrRequest 165 Config *IndexerConfig 166 BloomTrieNum uint64 167 BitIdx uint 168 SectionIndexList []uint64 169 BloomTrieRoot common.Hash 170 BloomBits [][]byte 171 Proofs *NodeSet 172 } 173 174 // StoreResult stores the retrieved data in local database 175 func (req *BloomRequest) StoreResult(db ethdb.Database) { 176 for i, sectionIdx := range req.SectionIndexList { 177 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*req.Config.BloomTrieSize-1) 178 // if we don't have the canonical hash stored for this section head number, we'll still store it under 179 // a key with a zero sectionHead. GetBloomBits will look there too if we still don't have the canonical 180 // hash. In the unlikely case we've retrieved the section head hash since then, we'll just retrieve the 181 // bit vector again from the network. 182 rawdb.WriteBloomBits(db, req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) 183 } 184 } 185 186 // TxStatus describes the status of a transaction 187 type TxStatus struct { 188 Status core.TxStatus 189 Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"` 190 Error string 191 } 192 193 // TxStatusRequest is the ODR request type for retrieving transaction status 194 type TxStatusRequest struct { 195 OdrRequest 196 Hashes []common.Hash 197 Status []TxStatus 198 } 199 200 // StoreResult stores the retrieved data in local database 201 func (req *TxStatusRequest) StoreResult(db ethdb.Database) {}