github.com/etherbanking/go-etherbanking@v1.7.1-0.20181009210156-cf649bca5aba/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/etherbanking/go-etherbanking/common" 26 "github.com/etherbanking/go-etherbanking/core" 27 "github.com/etherbanking/go-etherbanking/core/types" 28 "github.com/etherbanking/go-etherbanking/crypto" 29 "github.com/etherbanking/go-etherbanking/ethdb" 30 "github.com/etherbanking/go-etherbanking/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 // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 110 func GetBodyRLP(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (rlp.RawValue, error) { 111 if data := core.GetBodyRLP(odr.Database(), hash, number); data != nil { 112 return data, nil 113 } 114 r := &BlockRequest{Hash: hash, Number: number} 115 if err := odr.Retrieve(ctx, r); err != nil { 116 return nil, err 117 } else { 118 return r.Rlp, nil 119 } 120 } 121 122 // GetBody retrieves the block body (transactons, uncles) corresponding to the 123 // hash. 124 func GetBody(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Body, error) { 125 data, err := GetBodyRLP(ctx, odr, hash, number) 126 if err != nil { 127 return nil, err 128 } 129 body := new(types.Body) 130 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 131 return nil, err 132 } 133 return body, nil 134 } 135 136 // GetBlock retrieves an entire block corresponding to the hash, assembling it 137 // back from the stored header and body. 138 func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (*types.Block, error) { 139 // Retrieve the block header and body contents 140 header := core.GetHeader(odr.Database(), hash, number) 141 if header == nil { 142 return nil, ErrNoHeader 143 } 144 body, err := GetBody(ctx, odr, hash, number) 145 if err != nil { 146 return nil, err 147 } 148 // Reassemble the block and return 149 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles), nil 150 } 151 152 // GetBlockReceipts retrieves the receipts generated by the transactions included 153 // in a block given by its hash. 154 func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) { 155 receipts := core.GetBlockReceipts(odr.Database(), hash, number) 156 if receipts != nil { 157 return receipts, nil 158 } 159 r := &ReceiptsRequest{Hash: hash, Number: number} 160 if err := odr.Retrieve(ctx, r); err != nil { 161 return nil, err 162 } 163 return r.Receipts, nil 164 }