You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
4.6 KiB

  1. // Copyright 2017-2018 DERO Project. All rights reserved.
  2. // Use of this source code in any form is governed by RESEARCH license.
  3. // license can be found in the LICENSE file.
  4. // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
  5. //
  6. //
  7. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  8. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  10. // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  14. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  15. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. package p2pv2
  17. import "net"
  18. import "encoding/binary"
  19. // This file defines the structure for the protocol which is a msgp encoded ( which is standard)
  20. // msgp would cause an easy rewrite of p2p layer even in c, ruby or rust etc as future may demand
  21. // the protocol is length prefixed msgp payload
  22. // though we can use http2 stream features, they may become compilcated as the project evolve
  23. // the prefix length is 4 bytes, little endian encoded ( so a frame can be 4GB in size)
  24. // this is Work-In-Progress
  25. // the reason for writing it from scratch is the mess of boost serialisation
  26. // the p2p package is currently the most complex within the entire project
  27. // the protocol is partly syncronous, partly asyncronous , except for first handshake, so the node remain undetectable to external network scans, the detection cost is to atleast send a handshake packet*/
  28. // these are the commands required to make it completely operational
  29. const V2_COMMAND_HANDSHAKE = 1 // commands are syncronous and must be responded within 10 secs
  30. const V2_COMMAND_SYNC = 2
  31. const V2_COMMAND_CHAIN_REQUEST = 3
  32. const V2_COMMAND_CHAIN_RESPONSE = 4
  33. const V2_COMMAND_OBJECTS_REQUEST = 5
  34. const V2_COMMAND_OBJECTS_RESPONSE = 6
  35. const V2_NOTIFY_NEW_BLOCK = 0x80000000 // Notifications are asyncronous all notifications come here, such as new block, new txs
  36. const V2_NOTIFY_NEW_TX = 0x80000001 // notify tx using this
  37. // used to parse incoming packet for for command , so as a repective command command could be triggered
  38. type Common struct {
  39. Command uint64 `msgpack:"C"`
  40. Height uint64 `msgpack:"H"`
  41. Cumulative_Difficulty uint64 `msgpack:"CD"`
  42. Top_ID [32]byte `msgpack:"TI"` // 32 bytes of Top block
  43. Top_Version uint64 `msgpack:"TV"` // this basically represents the hard fork version
  44. }
  45. // at start, client sends handshake and server will respond to handshake
  46. type Handshake struct {
  47. Common // add all fields of Common
  48. Local_Time int64 `msgpack:"LT"`
  49. Local_Port uint32 `msgpack:"LP"`
  50. PeerID uint64 `msgpack:"PID"`
  51. Network_ID [16]byte `msgpack:"NID"` // 16 bytes
  52. PeerList []Peer_Info `msgpack:"PLIST"`
  53. Extension_List []string `msgpack:"EXT"`
  54. Request bool `msgpack:"REQUEST"` //whether this is a request
  55. }
  56. type Peer_Info struct {
  57. IP net.IP `msgpack:"IP"`
  58. Port uint32 `msgpack:"P"`
  59. ID uint64 `msgpack:"I"`
  60. LastSeen uint64 `msgpack:"LS"`
  61. }
  62. type Sync struct {
  63. Common // add all fields of common
  64. }
  65. type Chain_Request struct {
  66. Block_list [][32]byte `msgpack:"BLIST"`
  67. }
  68. type Chain_Response struct {
  69. Start_height uint64 `msgpack:"SH"`
  70. Block_list [][32]byte `msgpack:"BLIST"`
  71. }
  72. type Object_Request struct {
  73. Block_list [][32]byte `msgpack:"BLIST"`
  74. Tx_list [][32]byte `msgpack:"TXLIST"`
  75. }
  76. type Complete_Block struct {
  77. Block []byte `msgpack:"BLOCK"`
  78. Txs [][]byte `msgpack:"TXS"`
  79. }
  80. type Object_Response struct {
  81. Blocks []Complete_Block `msgpack:"CBLOCKS"`
  82. Txs [][]byte `msgpack:"TXS"`
  83. }
  84. type Notify_New_Objects struct {
  85. Block Complete_Block `msgpack:"CBLOCK"`
  86. Txs [][]byte `msgpack:"TXS"`
  87. }
  88. // each packet has to be parsed twice once for extracting command and then a full parsing
  89. // the message is sent as follows
  90. // assumingin peer lock has already been taken
  91. func (conn *Connection) Send_Message(data_bytes []byte) {
  92. var length_bytes [4]byte
  93. binary.LittleEndian.PutUint32(length_bytes[:], uint32(len(data_bytes)))
  94. // send the length prefix
  95. conn.Conn.Write(length_bytes[:])
  96. conn.Conn.Write(data_bytes) // send the message itself
  97. }