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  }