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.

121 lines
3.4 KiB

  1. package p2p
  2. import "bytes"
  3. import "encoding/binary"
  4. import "github.com/romana/rlog"
  5. import "github.com/deroproject/derosuite/blockchain"
  6. // FIXME this code can also be shared by NOTIFY_NEW_BLOCK, NOTIFY_NEW_TRANSACTIONS, Handle_BC_Notify_Response_GetObjects
  7. // this code handles a new block floating in the network
  8. func Handle_BC_Notify_New_Block(connection *Connection,
  9. i_command_header *Levin_Header, buf []byte) {
  10. var bl blockchain.Block
  11. connection.logger.Debugf("Incoming NOTIFY_NEW_BLOCK")
  12. // deserialize data header
  13. var i_data_header Levin_Data_Header // incoming data header
  14. err := i_data_header.DeSerialize(buf)
  15. if err != nil {
  16. connection.logger.Debugf("We should destroy connection here, data header cnot deserialized")
  17. return
  18. }
  19. buf = i_data_header.Data
  20. pos := bytes.Index(buf, []byte("block"))
  21. // find inner position of block
  22. pos = pos + 6 // jump to varint length position and decode
  23. buf = buf[pos:]
  24. block_length, done := Decode_Boost_Varint(buf)
  25. rlog.Tracef(2, "Block length %d %x\n", block_length, buf[:8])
  26. buf = buf[done:]
  27. block_buf := buf[:block_length]
  28. err = bl.Deserialize(block_buf)
  29. if err != nil {
  30. connection.logger.Warnf("Block could not be deserialized successfully err %s\n", err)
  31. connection.logger.Debugf("We should destroy connection here, block not deserialized")
  32. return
  33. }
  34. hash := bl.GetHash()
  35. rlog.Tracef(1, "Block deserialized successfully %x\n", hash[:32])
  36. rlog.Tracef(1, "Tx hash length %d\n", len(bl.Tx_hashes))
  37. for i := range bl.Tx_hashes {
  38. rlog.Tracef(2, "%d tx %x\n", i, bl.Tx_hashes[i][:32])
  39. }
  40. // point buffer to check whether any more tx exist
  41. buf = buf[block_length:]
  42. pos = bytes.Index(buf, []byte("\x03txs\x8a")) // at this point to
  43. if pos > -1 {
  44. rlog.Tracef(3, "txt pos %d\n", pos)
  45. buf = buf[pos+5:]
  46. // decode remain data length ( though we know it from buffer size, but still verify it )
  47. tx_count, done := Decode_Boost_Varint(buf)
  48. buf = buf[done:]
  49. for i := uint64(0); i < tx_count; i++ {
  50. var tx blockchain.Transaction
  51. tx_len, done := Decode_Boost_Varint(buf)
  52. buf = buf[done:]
  53. rlog.Tracef(3, "tx count %d i %d tx_len %d\n", tx_count, i, tx_len)
  54. tx_bytes := buf[:tx_len]
  55. // deserialize and verrify transaction
  56. err = tx.DeserializeHeader(tx_bytes)
  57. if err != nil {
  58. connection.logger.Warnf("Transaction could not be deserialized\n")
  59. } else {
  60. hash := tx.GetHash()
  61. rlog.Tracef(2, "Transaction deserialised successfully hash %x\n", hash[:32])
  62. // add tx to block chain, we must verify that the tx has been mined
  63. // add all transaction to TX pool , if not added
  64. chain.Add_TX(&tx)
  65. }
  66. buf = buf[tx_len:] // setup for next tx
  67. }
  68. }
  69. height_string := []byte("\x19current_blockchain_height\x05")
  70. pos = bytes.Index(buf, height_string) // at this point to
  71. if pos < 0 {
  72. connection.logger.Debugf("We should destroy connection here, block not deserialized")
  73. return
  74. }
  75. pos = pos + len(height_string)
  76. buf = buf[pos:]
  77. current_peer_height := binary.LittleEndian.Uint64(buf)
  78. connection.Last_Height = current_peer_height
  79. //connection.logger.Infof("buffer height %x current height %d complete %d\n", buf, connection.Last_Height, complete_block)
  80. // at this point, if it's a block we should try to add it to block chain
  81. // try to add block to chain
  82. connection.logger.Debugf("Found new block adding it to chain %x", bl.GetHash())
  83. chain.Chain_Add(&bl)
  84. }