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.

155 lines
5.5 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 p2p
  17. //import "fmt"
  18. import "bytes"
  19. import "time"
  20. import "encoding/binary"
  21. import "github.com/romana/rlog"
  22. import log "github.com/sirupsen/logrus"
  23. // outgoing response needs to be as follows
  24. /*
  25. 0020 01 11 01 01 01 01 02 01 01 08 0a 6c 6f 63 61 ............loca
  26. 0030 6c 5f 74 69 6d 65 05 c9 ea 45 5a 00 00 00 00 0c l_time...EZ.....
  27. 0040 70 61 79 6c 6f 61 64 5f 64 61 74 61 0c 10 15 63 payload_data...c
  28. 0050 75 6d 75 6c 61 74 69 76 65 5f 64 69 66 66 69 63 umulative_diffic
  29. 0060 75 6c 74 79 05 37 62 00 00 00 00 00 00 0e 63 75 ulty.7b.......cu
  30. 0070 72 72 65 6e 74 5f 68 65 69 67 68 74 05 ec 04 00 rrent_height....
  31. 0080 00 00 00 00 00 06 74 6f 70 5f 69 64 0a 80 85 d9 ......top_id....
  32. 0090 d2 f6 cd ee 1b 87 dd d1 ac 3d 15 db 4d 72 63 ca .........=..Mrc.
  33. 00a0 1c 43 37 db 53 78 7f 03 3b 74 f6 fc 45 0e 0b 74 .C7.Sx..;t..E..t
  34. 00b0 6f 70 5f 76 65 72 73 69 6f 6e 08 06 op_version..
  35. */
  36. // handle P2P_COMMAND_TIMED_SYNC_T
  37. func Handle_P2P_Timed_Sync(connection *Connection,
  38. i_command_header *Levin_Header, buf []byte) {
  39. // deserialize data header
  40. var i_data_header Levin_Data_Header // incoming data header
  41. err := i_data_header.DeSerialize(buf)
  42. if err != nil {
  43. log.Debugf("Invalid P2P_COMMAND_TIMED_SYNC_T, disconnecting peer")
  44. connection.Exit = true
  45. return
  46. }
  47. // parse incoming core data
  48. var peer_core_data CORE_DATA
  49. pos := bytes.Index(i_data_header.Data, []byte("payload_data")) // at this point to node data and should be parsed as such
  50. if pos < 0 {
  51. log.Debugf("Invalid P2P_COMMAND_TIMED_SYNC_T, disconnecting peer")
  52. connection.Exit = true
  53. return
  54. }
  55. err = peer_core_data.DeSerialize(i_data_header.Data[pos-1:])
  56. if err != nil {
  57. log.Debugf("Invalid P2P_COMMAND_TIMED_SYNC_T, disconnecting peer")
  58. connection.Exit = true
  59. return
  60. }
  61. rlog.Trace(5, "Incoming core data %+v \n", peer_core_data)
  62. // TODO if cumulative difficulty at this top mismatches ours start resync
  63. // if height is more than ours, start resync
  64. var our_core_data CORE_DATA
  65. // fill the structure with our chain data
  66. our_core_data.Top_ID = chain.Get_Top_ID()
  67. our_core_data.Cumulative_Difficulty = chain.Load_Block_Cumulative_Difficulty(our_core_data.Top_ID) // get cumulative difficulty for top block
  68. our_core_data.Current_Height = chain.Load_Height_for_BL_ID(our_core_data.Top_ID)
  69. our_core_data.Top_Version = 6
  70. serialised_bytes, _ := our_core_data.Serialize()
  71. header_bytes := []byte{0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
  72. 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x05,
  73. /* time bytes start here */ 0xc9, 0xea, 0x45, 0x5a, 0x00, 0x00, 0x00, 0x00}
  74. binary.LittleEndian.PutUint64(header_bytes[22:], uint64(time.Now().Unix()))
  75. //fmt.Printf("header %x serialised_bytes %x\n", header_bytes, serialised_bytes)
  76. response_bytes := append(serialised_bytes, header_bytes...)
  77. // create a new response header
  78. var o_command_header Levin_Header
  79. //var o_data_header Levin_Data_Header
  80. o_command_header.CB = uint64(len(response_bytes))
  81. o_command_header.Command = P2P_COMMAND_TIMED_SYNC
  82. o_command_header.ReturnData = false
  83. o_command_header.Flags = LEVIN_PACKET_RESPONSE
  84. o_command_header_bytes, _ := o_command_header.Serialize()
  85. connection.Conn.Write(o_command_header_bytes)
  86. connection.Conn.Write(response_bytes[:])
  87. connection.Last_Height = peer_core_data.Current_Height
  88. connection.Top_Version = uint64(peer_core_data.Top_Version)
  89. connection.Top_ID = peer_core_data.Top_ID
  90. connection.Cumulative_Difficulty = peer_core_data.Cumulative_Difficulty
  91. connection.State = ACTIVE
  92. // lets check whether we need to resync with this peer
  93. if chain.IsLagging(peer_core_data.Cumulative_Difficulty, peer_core_data.Current_Height, peer_core_data.Top_ID) {
  94. log.Debugf("We need to resync with the peer")
  95. // set mode to syncronising
  96. Send_BC_Notify_Chain_Command(connection)
  97. }
  98. }
  99. /* we will never send this request, so we donot need to parse response
  100. func Send_P2P_Timed_Sync(connection *Connection){
  101. connection.Lock()
  102. var o_command_header Levin_Header
  103. var o_data_header Levin_Data_Header
  104. o_data_bytes,_ := o_data_header.Serialize()
  105. o_command_header.CB = uint64(len(o_data_bytes))
  106. o_command_header.Command = P2P_COMMAND_REQUEST_SUPPORT_FLAGS
  107. o_command_header.ReturnData = true
  108. o_command_header.Flags = LEVIN_PACKET_REQUEST
  109. o_command_header_bytes,_ := o_command_header.Serialize()
  110. connection.Conn.Write(o_command_header_bytes)
  111. connection.Conn.Write(o_data_bytes)
  112. connection.Command_queue.PushBack(uint32(P2P_COMMAND_REQUEST_SUPPORT_FLAGS))
  113. connection.Unlock()
  114. }
  115. */