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