github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/swarm/network/messages.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 network
    18  
    19  import (
    20  	"fmt"
    21  	"net"
    22  	"time"
    23  
    24  	libp2p "github.com/libp2p/go-libp2p-peer"
    25  
    26  	"github.com/vntchain/go-vnt/contracts/chequebook"
    27  	"github.com/vntchain/go-vnt/swarm/network/kademlia"
    28  	"github.com/vntchain/go-vnt/swarm/services/swap"
    29  	"github.com/vntchain/go-vnt/swarm/storage"
    30  	"github.com/vntchain/go-vnt/vntp2p"
    31  )
    32  
    33  /*
    34  BZZ protocol Message Types and Message Data Types
    35  */
    36  
    37  // bzz protocol message codes
    38  const (
    39  	statusMsg          = iota // 0x01
    40  	storeRequestMsg           // 0x02
    41  	retrieveRequestMsg        // 0x03
    42  	peersMsg                  // 0x04
    43  	syncRequestMsg            // 0x05
    44  	deliveryRequestMsg        // 0x06
    45  	unsyncedKeysMsg           // 0x07
    46  	paymentMsg                // 0x08
    47  )
    48  
    49  /*
    50   Handshake
    51  
    52  * Version: 8 byte integer version of the protocol
    53  * ID: arbitrary byte sequence client identifier human readable
    54  * Addr: the address advertised by the node, format similar to DEVp2p wire protocol
    55  * Swap: info for the swarm accounting protocol
    56  * NetworkID: 8 byte integer network identifier
    57  * Caps: swarm-specific capabilities, format identical to devp2p
    58  * SyncState: syncronisation state (db iterator key and address space etc) persisted about the peer
    59  
    60  */
    61  type statusMsgData struct {
    62  	Version   uint64
    63  	ID        string
    64  	Addr      *peerAddr
    65  	Swap      *swap.SwapProfile
    66  	NetworkId uint64
    67  }
    68  
    69  func (self *statusMsgData) String() string {
    70  	return fmt.Sprintf("Status: Version: %v, ID: %v, Addr: %v, Swap: %v, NetworkId: %v", self.Version, self.ID, self.Addr, self.Swap, self.NetworkId)
    71  }
    72  
    73  /*
    74   store requests are forwarded to the peers in their kademlia proximity bin
    75   if they are distant
    76   if they are within our storage radius or have any incentive to store it
    77   then attach your nodeID to the metadata
    78   if the storage request is sufficiently close (within our proxLimit, i. e., the
    79   last row of the routing table)
    80  */
    81  type storeRequestMsgData struct {
    82  	Key   storage.Key // hash of datasize | data
    83  	SData []byte      // the actual chunk Data
    84  	// optional
    85  	Id             uint64     // request ID. if delivery, the ID is retrieve request ID
    86  	requestTimeout *time.Time // expiry for forwarding - [not serialised][not currently used]
    87  	storageTimeout *time.Time // expiry of content - [not serialised][not currently used]
    88  	from           *peer      // [not serialised] protocol registers the requester
    89  }
    90  
    91  func (self storeRequestMsgData) String() string {
    92  	var from string
    93  	if self.from == nil {
    94  		from = "self"
    95  	} else {
    96  		from = self.from.Addr().String()
    97  	}
    98  	end := len(self.SData)
    99  	if len(self.SData) > 10 {
   100  		end = 10
   101  	}
   102  	return fmt.Sprintf("from: %v, Key: %v; ID: %v, requestTimeout: %v, storageTimeout: %v, SData %x", from, self.Key, self.Id, self.requestTimeout, self.storageTimeout, self.SData[:end])
   103  }
   104  
   105  /*
   106  Retrieve request
   107  
   108  Timeout in milliseconds. Note that zero timeout retrieval requests do not request forwarding, but prompt for a peers message response. therefore they serve also
   109  as messages to retrieve peers.
   110  
   111  MaxSize specifies the maximum size that the peer will accept. This is useful in
   112  particular if we allow storage and delivery of multichunk payload representing
   113  the entire or partial subtree unfolding from the requested root key.
   114  So when only interested in limited part of a stream (infinite trees) or only
   115  testing chunk availability etc etc, we can indicate it by limiting the size here.
   116  
   117  Request ID can be newly generated or kept from the request originator.
   118  If request ID Is missing or zero, the request is handled as a lookup only
   119  prompting a peers response but not launching a search. Lookup requests are meant
   120  to be used to bootstrap kademlia tables.
   121  
   122  In the special case that the key is the zero value as well, the remote peer's
   123  address is assumed (the message is to be handled as a self lookup request).
   124  The response is a PeersMsg with the peers in the kademlia proximity bin
   125  corresponding to the address.
   126  */
   127  
   128  type retrieveRequestMsgData struct {
   129  	Key      storage.Key // target Key address of chunk to be retrieved
   130  	Id       uint64      // request id, request is a lookup if missing or zero
   131  	MaxSize  uint64      // maximum size of delivery accepted
   132  	MaxPeers uint64      // maximum number of peers returned
   133  	Timeout  uint64      // the longest time we are expecting a response
   134  	timeout  *time.Time  // [not serialied]
   135  	from     *peer       //
   136  }
   137  
   138  func (self *retrieveRequestMsgData) String() string {
   139  	var from string
   140  	if self.from == nil {
   141  		from = "ourselves"
   142  	} else {
   143  		from = self.from.Addr().String()
   144  	}
   145  	var target []byte
   146  	if len(self.Key) > 3 {
   147  		target = self.Key[:4]
   148  	}
   149  	return fmt.Sprintf("from: %v, Key: %x; ID: %v, MaxSize: %v, MaxPeers: %d", from, target, self.Id, self.MaxSize, self.MaxPeers)
   150  }
   151  
   152  // lookups are encoded by missing request ID
   153  func (self *retrieveRequestMsgData) isLookup() bool {
   154  	return self.Id == 0
   155  }
   156  
   157  // sets timeout fields
   158  func (self *retrieveRequestMsgData) setTimeout(t *time.Time) {
   159  	self.timeout = t
   160  	if t != nil {
   161  		self.Timeout = uint64(t.UnixNano())
   162  	} else {
   163  		self.Timeout = 0
   164  	}
   165  }
   166  
   167  func (self *retrieveRequestMsgData) getTimeout() (t *time.Time) {
   168  	if self.Timeout > 0 && self.timeout == nil {
   169  		timeout := time.Unix(int64(self.Timeout), 0)
   170  		t = &timeout
   171  		self.timeout = t
   172  	}
   173  	return
   174  }
   175  
   176  // peerAddr is sent in StatusMsg as part of the handshake
   177  type peerAddr struct {
   178  	IP   net.IP
   179  	Port uint16
   180  	ID   libp2p.ID // the 64 byte NodeID (ECDSA Public Key)
   181  	Addr kademlia.Address
   182  }
   183  
   184  // peerAddr pretty prints as vnode
   185  func (self *peerAddr) String() string {
   186  	return vntp2p.NewNode(self.ID, self.IP, 0, self.Port).String()
   187  }
   188  
   189  /*
   190  peers Msg is one response to retrieval; it is always encouraged after a retrieval
   191  request to respond with a list of peers in the same kademlia proximity bin.
   192  The encoding of a peer is identical to that in the devp2p base protocol peers
   193  messages: [IP, Port, NodeID]
   194  note that a node's DPA address is not the NodeID but the hash of the NodeID.
   195  
   196  Timeout serves to indicate whether the responder is forwarding the query within
   197  the timeout or not.
   198  
   199  NodeID serves as the owner of payment contracts and signer of proofs of transfer.
   200  
   201  The Key is the target (if response to a retrieval request) or missing (zero value)
   202  peers address (hash of NodeID) if retrieval request was a self lookup.
   203  
   204  Peers message is requested by retrieval requests with a missing or zero value request ID
   205  */
   206  type peersMsgData struct {
   207  	Peers   []*peerAddr //
   208  	Timeout uint64      //
   209  	timeout *time.Time  // indicate whether responder is expected to deliver content
   210  	Key     storage.Key // present if a response to a retrieval request
   211  	Id      uint64      // present if a response to a retrieval request
   212  	from    *peer
   213  }
   214  
   215  // peers msg pretty printer
   216  func (self *peersMsgData) String() string {
   217  	var from string
   218  	if self.from == nil {
   219  		from = "ourselves"
   220  	} else {
   221  		from = self.from.Addr().String()
   222  	}
   223  	var target []byte
   224  	if len(self.Key) > 3 {
   225  		target = self.Key[:4]
   226  	}
   227  	return fmt.Sprintf("from: %v, Key: %x; ID: %v, Peers: %v", from, target, self.Id, self.Peers)
   228  }
   229  
   230  func (self *peersMsgData) setTimeout(t *time.Time) {
   231  	self.timeout = t
   232  	if t != nil {
   233  		self.Timeout = uint64(t.UnixNano())
   234  	} else {
   235  		self.Timeout = 0
   236  	}
   237  }
   238  
   239  /*
   240  syncRequest
   241  
   242  is sent after the handshake to initiate syncing
   243  the syncState of the remote node is persisted in kaddb and set on the
   244  peer/protocol instance when the node is registered by hive as online{
   245  */
   246  
   247  type syncRequestMsgData struct {
   248  	SyncState *syncState `rlp:"nil"`
   249  }
   250  
   251  func (self *syncRequestMsgData) String() string {
   252  	return fmt.Sprintf("%v", self.SyncState)
   253  }
   254  
   255  /*
   256  deliveryRequest
   257  
   258  is sent once a batch of sync keys is filtered. The ones not found are
   259  sent as a list of syncReuest (hash, priority) in the Deliver field.
   260  When the source receives the sync request it continues to iterate
   261  and fetch at most N items as yet unsynced.
   262  At the same time responds with deliveries of the items.
   263  */
   264  type deliveryRequestMsgData struct {
   265  	Deliver []*syncRequest
   266  }
   267  
   268  func (self *deliveryRequestMsgData) String() string {
   269  	return fmt.Sprintf("sync request for new chunks\ndelivery request for %v chunks", len(self.Deliver))
   270  }
   271  
   272  /*
   273  unsyncedKeys
   274  
   275  is sent first after the handshake if SyncState iterator brings up hundreds, thousands?
   276  and subsequently sent as a response to deliveryRequestMsgData.
   277  
   278  Syncing is the iterative process of exchanging unsyncedKeys and deliveryRequestMsgs
   279  both ways.
   280  
   281  State contains the sync state sent by the source. When the source receives the
   282  sync state it continues to iterate and fetch at most N items as yet unsynced.
   283  At the same time responds with deliveries of the items.
   284  */
   285  type unsyncedKeysMsgData struct {
   286  	Unsynced []*syncRequest
   287  	State    *syncState
   288  }
   289  
   290  func (self *unsyncedKeysMsgData) String() string {
   291  	return fmt.Sprintf("sync: keys of %d new chunks (state %v) => synced: %v", len(self.Unsynced), self.State, self.State.Synced)
   292  }
   293  
   294  /*
   295  payment
   296  
   297  is sent when the swap balance is tilted in favour of the remote peer
   298  and in absolute units exceeds the PayAt parameter in the remote peer's profile
   299  */
   300  
   301  type paymentMsgData struct {
   302  	Units   uint               // units actually paid for (checked against amount by swap)
   303  	Promise *chequebook.Cheque // payment with cheque
   304  }
   305  
   306  func (self *paymentMsgData) String() string {
   307  	return fmt.Sprintf("payment for %d units: %v", self.Units, self.Promise)
   308  }