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 }