github.com/klaytn/klaytn@v1.12.1/node/cn/snap/peer.go (about)

     1  // Modifications Copyright 2022 The klaytn Authors
     2  // Copyright 2020 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from eth/protocols/snap/peer.go (2022/06/29).
    19  // Modified and improved for the klaytn development.
    20  
    21  package snap
    22  
    23  import (
    24  	"github.com/klaytn/klaytn/common"
    25  	"github.com/klaytn/klaytn/log"
    26  	"github.com/klaytn/klaytn/networks/p2p"
    27  )
    28  
    29  // Peer is a collection of relevant information we have about a `snap` peer.
    30  type Peer struct {
    31  	id string // Unique ID for the peer, cached
    32  
    33  	*p2p.Peer                   // The embedded P2P package peer
    34  	rw        p2p.MsgReadWriter // Input/output streams for snap
    35  	version   uint              // Protocol version negotiated
    36  
    37  	logger log.Logger // Contextual logger with the peer id injected
    38  }
    39  
    40  // NewPeer create a wrapper for a network connection and negotiated  protocol
    41  // version.
    42  func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
    43  	id := p.ID().String()
    44  	return &Peer{
    45  		id:      id[:16],
    46  		Peer:    p,
    47  		rw:      rw,
    48  		version: version,
    49  		logger:  logger.NewWith("peer", id[:16]),
    50  	}
    51  }
    52  
    53  // NewFakePeer create a fake snap peer without a backing p2p peer, for testing purposes.
    54  func NewFakePeer(version uint, id string, rw p2p.MsgReadWriter) *Peer {
    55  	return &Peer{
    56  		id:      id[:16],
    57  		rw:      rw,
    58  		version: version,
    59  		logger:  logger.NewWith("peer", id[:16]),
    60  	}
    61  }
    62  
    63  // ID retrieves the peer's unique identifier.
    64  func (p *Peer) ID() string {
    65  	return p.id
    66  }
    67  
    68  // Version retrieves the peer's negoatiated `snap` protocol version.
    69  func (p *Peer) Version() uint {
    70  	return p.version
    71  }
    72  
    73  // Log overrides the P2P logget with the higher level one containing only the id.
    74  func (p *Peer) Log() log.Logger {
    75  	return p.logger
    76  }
    77  
    78  // RequestAccountRange fetches a batch of accounts rooted in a specific account
    79  // trie, starting with the origin.
    80  func (p *Peer) RequestAccountRange(id uint64, root common.Hash, origin, limit common.Hash, bytes uint64) error {
    81  	p.logger.Trace("Fetching range of accounts", "reqid", id, "root", root, "origin", origin, "limit", limit, "bytes", common.StorageSize(bytes))
    82  
    83  	requestTracker.Track(p.id, p.version, GetAccountRangeMsg, AccountRangeMsg, id)
    84  	return p2p.Send(p.rw, GetAccountRangeMsg, &GetAccountRangePacket{
    85  		ID:     id,
    86  		Root:   root,
    87  		Origin: origin,
    88  		Limit:  limit,
    89  		Bytes:  bytes,
    90  	})
    91  }
    92  
    93  // RequestStorageRanges fetches a batch of storage slots belonging to one or more
    94  // accounts. If slots from only one accout is requested, an origin marker may also
    95  // be used to retrieve from there.
    96  func (p *Peer) RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error {
    97  	if len(accounts) == 1 && origin != nil {
    98  		p.logger.Trace("Fetching range of large storage slots", "reqid", id, "root", root, "account", accounts[0], "origin", common.BytesToHash(origin), "limit", common.BytesToHash(limit), "bytes", common.StorageSize(bytes))
    99  	} else {
   100  		p.logger.Trace("Fetching ranges of small storage slots", "reqid", id, "root", root, "accounts", len(accounts), "first", accounts[0], "bytes", common.StorageSize(bytes))
   101  	}
   102  	requestTracker.Track(p.id, p.version, GetStorageRangesMsg, StorageRangesMsg, id)
   103  	return p2p.Send(p.rw, GetStorageRangesMsg, &GetStorageRangesPacket{
   104  		ID:       id,
   105  		Root:     root,
   106  		Accounts: accounts,
   107  		Origin:   origin,
   108  		Limit:    limit,
   109  		Bytes:    bytes,
   110  	})
   111  }
   112  
   113  // RequestByteCodes fetches a batch of bytecodes by hash.
   114  func (p *Peer) RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error {
   115  	p.logger.Trace("Fetching set of byte codes", "reqid", id, "hashes", len(hashes), "bytes", common.StorageSize(bytes))
   116  
   117  	requestTracker.Track(p.id, p.version, GetByteCodesMsg, ByteCodesMsg, id)
   118  	return p2p.Send(p.rw, GetByteCodesMsg, &GetByteCodesPacket{
   119  		ID:     id,
   120  		Hashes: hashes,
   121  		Bytes:  bytes,
   122  	})
   123  }
   124  
   125  // RequestTrieNodes fetches a batch of account or storage trie nodes rooted in
   126  // a specificstate trie.
   127  func (p *Peer) RequestTrieNodes(id uint64, root common.Hash, paths []TrieNodePathSet, bytes uint64) error {
   128  	p.logger.Trace("Fetching set of trie nodes", "reqid", id, "root", root, "pathsets", len(paths), "bytes", common.StorageSize(bytes))
   129  
   130  	requestTracker.Track(p.id, p.version, GetTrieNodesMsg, TrieNodesMsg, id)
   131  	return p2p.Send(p.rw, GetTrieNodesMsg, &GetTrieNodesPacket{
   132  		ID:    id,
   133  		Root:  root,
   134  		Paths: paths,
   135  		Bytes: bytes,
   136  	})
   137  }