github.com/puppeth/go-ethereum@v0.8.6-0.20171014130046-e9295163aa25/light/odr.go (about)

     1  // Copyright 2015 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 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/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  // NoOdr is the default context passed to an ODR capable function when the ODR
    34  // service is not required.
    35  var NoOdr = context.Background()
    36  
    37  // OdrBackend is an interface to a backend service that handles ODR retrievals type
    38  type OdrBackend interface {
    39  	Database() ethdb.Database
    40  	Retrieve(ctx context.Context, req OdrRequest) error
    41  }
    42  
    43  // OdrRequest is an interface for retrieval requests
    44  type OdrRequest interface {
    45  	StoreResult(db ethdb.Database)
    46  }
    47  
    48  // TrieID identifies a state or account storage trie
    49  type TrieID struct {
    50  	BlockHash, Root common.Hash
    51  	BlockNumber     uint64
    52  	AccKey          []byte
    53  }
    54  
    55  // StateTrieID returns a TrieID for a state trie belonging to a certain block
    56  // header.
    57  func StateTrieID(header *types.Header) *TrieID {
    58  	return &TrieID{
    59  		BlockHash:   header.Hash(),
    60  		BlockNumber: header.Number.Uint64(),
    61  		AccKey:      nil,
    62  		Root:        header.Root,
    63  	}
    64  }
    65  
    66  // StorageTrieID returns a TrieID for a contract storage trie at a given account
    67  // of a given state trie. It also requires the root hash of the trie for
    68  // checking Merkle proofs.
    69  func StorageTrieID(state *TrieID, addrHash, root common.Hash) *TrieID {
    70  	return &TrieID{
    71  		BlockHash:   state.BlockHash,
    72  		BlockNumber: state.BlockNumber,
    73  		AccKey:      addrHash[:],
    74  		Root:        root,
    75  	}
    76  }
    77  
    78  // TrieRequest is the ODR request type for state/storage trie entries
    79  type TrieRequest struct {
    80  	OdrRequest
    81  	Id    *TrieID
    82  	Key   []byte
    83  	Proof []rlp.RawValue
    84  }
    85  
    86  // StoreResult stores the retrieved data in local database
    87  func (req *TrieRequest) StoreResult(db ethdb.Database) {
    88  	storeProof(db, req.Proof)
    89  }
    90  
    91  // storeProof stores the new trie nodes obtained from a merkle proof in the database
    92  func storeProof(db ethdb.Database, proof []rlp.RawValue) {
    93  	for _, buf := range proof {
    94  		hash := crypto.Keccak256(buf)
    95  		val, _ := db.Get(hash)
    96  		if val == nil {
    97  			db.Put(hash, buf)
    98  		}
    99  	}
   100  }
   101  
   102  // CodeRequest is the ODR request type for retrieving contract code
   103  type CodeRequest struct {
   104  	OdrRequest
   105  	Id   *TrieID // references storage trie of the account
   106  	Hash common.Hash
   107  	Data []byte
   108  }
   109  
   110  // StoreResult stores the retrieved data in local database
   111  func (req *CodeRequest) StoreResult(db ethdb.Database) {
   112  	db.Put(req.Hash[:], req.Data)
   113  }
   114  
   115  // BlockRequest is the ODR request type for retrieving block bodies
   116  type BlockRequest struct {
   117  	OdrRequest
   118  	Hash   common.Hash
   119  	Number uint64
   120  	Rlp    []byte
   121  }
   122  
   123  // StoreResult stores the retrieved data in local database
   124  func (req *BlockRequest) StoreResult(db ethdb.Database) {
   125  	core.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp)
   126  }
   127  
   128  // ReceiptsRequest is the ODR request type for retrieving block bodies
   129  type ReceiptsRequest struct {
   130  	OdrRequest
   131  	Hash     common.Hash
   132  	Number   uint64
   133  	Receipts types.Receipts
   134  }
   135  
   136  // StoreResult stores the retrieved data in local database
   137  func (req *ReceiptsRequest) StoreResult(db ethdb.Database) {
   138  	core.WriteBlockReceipts(db, req.Hash, req.Number, req.Receipts)
   139  }
   140  
   141  // TrieRequest is the ODR request type for state/storage trie entries
   142  type ChtRequest struct {
   143  	OdrRequest
   144  	ChtNum, BlockNum uint64
   145  	ChtRoot          common.Hash
   146  	Header           *types.Header
   147  	Td               *big.Int
   148  	Proof            []rlp.RawValue
   149  }
   150  
   151  // StoreResult stores the retrieved data in local database
   152  func (req *ChtRequest) StoreResult(db ethdb.Database) {
   153  	// if there is a canonical hash, there is a header too
   154  	core.WriteHeader(db, req.Header)
   155  	hash, num := req.Header.Hash(), req.Header.Number.Uint64()
   156  	core.WriteTd(db, hash, num, req.Td)
   157  	core.WriteCanonicalHash(db, hash, num)
   158  	//storeProof(db, req.Proof)
   159  }