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.

227 lines
7.2 KiB

  1. package p2p
  2. import "bytes"
  3. import "encoding/binary"
  4. import "github.com/romana/rlog"
  5. import "github.com/deroproject/derosuite/globals"
  6. import "github.com/deroproject/derosuite/crypto"
  7. /* the data structure which needs to be serialised is defined in cryptonote_protocol_defs.h
  8. * struct request
  9. {
  10. uint64_t start_height;
  11. uint64_t total_height;
  12. uint64_t cumulative_difficulty;
  13. std::list<crypto::hash> m_block_ids;
  14. BEGIN_KV_SERIALIZE_MAP()
  15. KV_SERIALIZE(cumulative_difficulty)
  16. KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_ids)
  17. KV_SERIALIZE(start_height)
  18. KV_SERIALIZE(total_height)
  19. END_KV_SERIALIZE_MAP()
  20. };
  21. */
  22. // This request only comes when we have sent the BC_NOTIFY_REQUEST_CHAIN command
  23. // handle BC_NOTIFY_RESPONSE_CHAIN_ENTRY
  24. func Handle_BC_Notify_Response_Chain_Entry(connection *Connection,
  25. i_command_header *Levin_Header, buf []byte) {
  26. // deserialize data header
  27. var i_data_header Levin_Data_Header // incoming data header
  28. err := i_data_header.DeSerialize(buf)
  29. if err != nil {
  30. //fmt.Printf("We should destroy connection here, data header cnot deserialized")
  31. rlog.Tracef(4, "Data header deserialisation failed. Disconnect peer \n")
  32. connection.Exit = true
  33. return
  34. }
  35. pos := bytes.Index(i_data_header.Data, []byte("cumulative_difficulty")) // at this point to
  36. if pos == -1 {
  37. rlog.Tracef(4, "Cumulative difficulty deserialisation failed. Disconnect peer \n")
  38. connection.Exit = true
  39. return
  40. }
  41. cumulative_difficulty := binary.LittleEndian.Uint64(i_data_header.Data[pos+22:])
  42. rlog.Tracef(4, "Cumalative difficulty %d %x\n", cumulative_difficulty, cumulative_difficulty)
  43. pos = bytes.Index(i_data_header.Data, []byte("start_height")) // at this point to
  44. if pos == -1 {
  45. panic("start_height not found, its mandatory\n")
  46. }
  47. start_height := binary.LittleEndian.Uint64(i_data_header.Data[pos+13:])
  48. rlog.Tracef(4, "start_height %d %x\n", start_height, start_height)
  49. pos = bytes.Index(i_data_header.Data, []byte("m_block_ids")) // at this point to
  50. if pos == -1 {
  51. panic("m_block_ids not found, its mandatory\n")
  52. }
  53. // decode data length ( though we know it from buffer size, but still verify it )
  54. buf = i_data_header.Data[pos+11+1:]
  55. data_length, done := Decode_Boost_Varint(buf)
  56. //fmt.Printf("data length %d , hex %x\n", data_length, buf[:8])
  57. buf = buf[done:]
  58. if data_length == 0 {
  59. rlog.Tracef(4, "Peer says it does not have even genesis block, so disconnect")
  60. connection.Exit = true
  61. return
  62. }
  63. if (data_length % 32) != 0 { // sanity check
  64. rlog.Tracef(2, "We should destroy connection here, packet mismatch")
  65. connection.Exit = true
  66. return
  67. }
  68. rlog.Tracef(4, "Number of Blocks id in chain BC_NOTIFY_RESPONSE_CHAIN_ENTRY %d \n", data_length/32)
  69. var block_list []crypto.Hash
  70. for i := uint64(0); i < data_length/32; i++ {
  71. var bhash crypto.Hash
  72. copy(bhash[:], buf[i*32:(i+1)*32])
  73. // only request block that we donot have
  74. if chain.Get_Height() < 20 {
  75. block_list = append(block_list, bhash)
  76. rlog.Tracef(5, "%2d hash %x\n", i, bhash[:])
  77. } else {
  78. if !chain.Block_Exists(bhash) {
  79. block_list = append(block_list, bhash)
  80. rlog.Tracef(5, "%2d hash %x\n", i, bhash[:])
  81. }
  82. }
  83. }
  84. // server will kill us, if we queue more than 1000 blocks
  85. if len(block_list) > 400 {
  86. block_list = block_list[:399]
  87. }
  88. // make sure the genesis block is same
  89. // if peer provided us a genesis block make sure, its ours
  90. if start_height == 0 && block_list[0] != globals.Config.Genesis_Block_Hash {
  91. rlog.Tracef(4, "Peer's genesis block is different from our, so disconnect")
  92. connection.Exit = true
  93. return
  94. }
  95. // we must queue the hashes so as to fetch them
  96. //block_list = block_list[:0]
  97. var hash crypto.Hash
  98. /*
  99. //big_block ,_ := hex.DecodeString("9ba23efe505f9674dc24c150edbdbe57abc3ec6636aa4c1659e811b389c0b30b") // zero tx
  100. //big_block ,_ := hex.DecodeString("14371eeddca0f3ce9b992b3e2a0e482920497d87dd20002456f3a844b04a3318") // single tx
  101. big_block ,_ := hex.DecodeString("a31a17bb26b2ec37479ee3a02f53dd94860611457811d0c23ce892f4e87e1697") // 4 tx
  102. copy(hash[:],big_block[:32])
  103. block_list = append(block_list, hash)
  104. big_tx, _ := hex.DecodeString("af6f12d56f32f58623a834c4f12c5443976346a2f877ef78798c39496bd00559") // single tx
  105. var tx_list []ringct.Hash
  106. copy(hash[:],big_tx[:32])
  107. tx_list = append(tx_list, hash)
  108. */
  109. _ = hash
  110. var tx_list []crypto.Hash
  111. /*if len(block_list) > 5 {
  112. block_list= block_list[:5]
  113. }*/
  114. Send_BC_Notify_Request_GetObjects(connection, block_list, tx_list[:0])
  115. }
  116. // header from boost packet
  117. /* header bytes
  118. 0000 01 11 01 01 01 01 02 01 01 10 15 63 75 6d 75 6c ...........cumul
  119. 0010 61 74 69 76 65 5f 64 69 66 66 69 63 75 6c 74 79 ative_difficulty
  120. 0020 05 ab 61 00 00 00 00 00 00 0b 6d 5f 62 6c 6f 63 ..a.......m_bloc
  121. 0030 6b 5f 69 64 73 0a 82 72 02 00 63 34 12 de 21 ea k_ids..r..c4..!.
  122. // suffix_bytes
  123. 44d0 4c 16 59 e8 11 b3 89 c0 b3 0b 0c 73 74 61 72 74 L.Y........start
  124. 44e0 5f 68 65 69 67 68 74 05 00 00 00 00 00 00 00 00 _height.........
  125. 44f0 0c 74 6f 74 61 6c 5f 68 65 69 67 68 74 05 e5 04 .total_height...
  126. 4500 00 00 00 00 00 00 ......
  127. */
  128. // send the PEER the blocks he needs to download our version of chain
  129. // this is send every 5 seconds
  130. func Send_BC_Notify_Response_Chain_Entry(connection *Connection, block_list []crypto.Hash, start_height, current_height, diff uint64) {
  131. connection.Lock()
  132. header_bytes := []byte{0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x10, 0x15, 0x63, 0x75, 0x6d, 0x75, 0x6c,
  133. 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79,
  134. 0x05, 0xab, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x6d, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
  135. 0x6b, 0x5f, 0x69, 0x64, 0x73, 0x0a}
  136. suffix_bytes := []byte{0x0c, 0x73, 0x74, 0x61, 0x72, 0x74,
  137. 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  138. 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x05, 0xe5, 0x04,
  139. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  140. binary.LittleEndian.PutUint64(header_bytes[33:], diff)
  141. binary.LittleEndian.PutUint64(suffix_bytes[14:], start_height)
  142. binary.LittleEndian.PutUint64(suffix_bytes[36:], current_height)
  143. // now append boost variant length, and then append all the hashes
  144. buf := make([]byte, 8, 8)
  145. done := Encode_Boost_Varint(buf, uint64(len(block_list)*32)) // encode length of buffer
  146. buf = buf[:done]
  147. var o_command_header Levin_Header
  148. data_bytes := append(header_bytes, buf...)
  149. // convert and append all hashes to bytes
  150. for _, hash := range block_list {
  151. data_bytes = append(data_bytes, hash[:32]...)
  152. }
  153. data_bytes = append(data_bytes, suffix_bytes...)
  154. o_command_header.CB = uint64(len(data_bytes))
  155. o_command_header.Command = BC_NOTIFY_RESPONSE_CHAIN_ENTRY
  156. o_command_header.ReturnData = false
  157. o_command_header.Flags = LEVIN_PACKET_REQUEST
  158. o_command_header_bytes, _ := o_command_header.Serialize()
  159. connection.Conn.Write(o_command_header_bytes)
  160. connection.Conn.Write(data_bytes)
  161. //fmt.Printf("len of command header %d\n", len(o_command_header_bytes))
  162. //fmt.Printf("len of data header %d\n", len(data_bytes))
  163. connection.Unlock()
  164. }