github.com/ylsGit/go-ethereum@v1.6.5/light/odr_util.go (about) 1 // Copyright 2016 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 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "math/big" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core" 27 "github.com/ethereum/go-ethereum/core/types" 28 "github.com/ethereum/go-ethereum/crypto" 29 "github.com/ethereum/go-ethereum/ethdb" 30 "github.com/ethereum/go-ethereum/rlp" 31 ) 32 33 var sha3_nil = crypto.Keccak256Hash(nil) 34 35 var ( 36 ErrNoTrustedCht = errors.New("No trusted canonical hash trie") 37 ErrNoHeader = errors.New("Header not found") 38 39 ChtFrequency = uint64(4096) 40 ChtConfirmations = uint64(2048) 41 trustedChtKey = []byte("TrustedCHT") 42 ) 43 44 type ChtNode struct { 45 Hash common.Hash 46 Td *big.Int 47 } 48 49 type TrustedCht struct { 50 Number uint64 51 Root common.Hash 52 } 53 54 func GetTrustedCht(db ethdb.Database) TrustedCht { 55 data, _ := db.Get(trustedChtKey) 56 var res TrustedCht 57 if err := rlp.DecodeBytes(data, &res); err != nil { 58 return TrustedCht{0, common.Hash{}} 59 } 60 return res 61 } 62 63 func WriteTrustedCht(db ethdb.Database, cht TrustedCht) { 64 data, _ := rlp.EncodeToBytes(cht) 65 db.Put(trustedChtKey, data) 66 } 67 68 func DeleteTrustedCht(db ethdb.Database) { 69 db.Delete(trustedChtKey) 70 } 71 72 func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { 73 db := odr.Database() 74 hash := core.GetCanonicalHash(db, number) 75 if (hash != common.Hash{}) { 76 // if there is a canonical hash, there is a header too 77 header := core.GetHeader(db, hash, number) 78 if header == nil { 79 panic("Canonical hash present but header not found") 80 } 81 return header, nil 82 } 83 84 cht := GetTrustedCht(db) 85 if number >= cht.Number*ChtFrequency { 86 return nil, ErrNoTrustedCht 87 } 88 89 r := &ChtRequest{ChtRoot: cht.Root, ChtNum: cht.Number, BlockNum: number} 90 if err := odr.Retrieve(ctx, r); err != nil { 91 return nil, err 92 } else { 93 return r.Header, nil 94 } 95 } 96 97 func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) { 98 hash := core.GetCanonicalHash(odr.Database(), number) 99 if (hash != common.Hash{}) { 100 return hash, nil 101 } 102 header, err := GetHeaderByNumber(ctx, odr, number) 103 if header != nil { 104 return header.Hash(), nil 105 } 106 return common.Hash{}, err 107 } 108 109 // retrieveContractCode tries to retrieve the contract code of the given account 110 // with the given hash from the network (id points to the storage trie belonging 111 // to the same account) 112 func retrieveContractCode(ctx context.Context, odr OdrBackend, id *TrieID, hash common.Hash) ([]byte, error) { 113 if hash == sha3_nil { 114 return nil, nil 115 } 116 res, _ := odr.Database().Get(hash[:]) 117 if res != nil { 118 return res, nil 119 } 120 r := &CodeRequest{Id: id, Hash: hash} 121 if err := odr.Retrieve(ctx, r); err != nil { 122 return nil, err 123 } else { 124 return r.Data, nil 125 } 126 } 127 128 // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 129 func GetBodyRLP(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (rlp.RawValue, error) { 130 if data := core.GetBodyRLP(odr.Database(), hash, number); data != nil { 131 return data, nil 132 } 133 r := &BlockRequest{Hash: hash, Number: number} 134 if err := odr.Retrieve(ctx, r); err != nil { 135 return nil, err 136 } else { 137 return r.Rlp, nil 138 } 139 } 140 141 // GetBody retrieves the block body (transactons, uncles) corresponding to the 142 // hash. 143 func GetBody(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Body, error) { 144 data, err := GetBodyRLP(ctx, odr, hash, number) 145 if err != nil { 146 return nil, err 147 } 148 body := new(types.Body) 149 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 150 return nil, err 151 } 152 return body, nil 153 } 154 155 // GetBlock retrieves an entire block corresponding to the hash, assembling it 156 // back from the stored header and body. 157 func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Block, error) { 158 // Retrieve the block header and body contents 159 header := core.GetHeader(odr.Database(), hash, number) 160 if header == nil { 161 return nil, ErrNoHeader 162 } 163 body, err := GetBody(ctx, odr, hash, number) 164 if err != nil { 165 return nil, err 166 } 167 // Reassemble the block and return 168 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles), nil 169 } 170 171 // GetBlockReceipts retrieves the receipts generated by the transactions included 172 // in a block given by its hash. 173 func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) { 174 receipts := core.GetBlockReceipts(odr.Database(), hash, number) 175 if receipts != nil { 176 return receipts, nil 177 } 178 r := &ReceiptsRequest{Hash: hash, Number: number} 179 if err := odr.Retrieve(ctx, r); err != nil { 180 return nil, err 181 } 182 return r.Receipts, nil 183 }