messages.go 9.8 KB

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