Class: Ciri::P2P::Discovery::Protocol::Message
- Inherits:
-
Object
- Object
- Ciri::P2P::Discovery::Protocol::Message
- Defined in:
- lib/ciri/p2p/discovery/protocol.rb
Overview
implement the DiscV4 protocol github.com/ethereum/devp2p/blob/master/discv4.md
Constant Summary collapse
- MAX_LEN =
1280
Instance Attribute Summary collapse
-
#message_hash ⇒ Object
readonly
Returns the value of attribute message_hash.
-
#packet_data ⇒ Object
readonly
Returns the value of attribute packet_data.
-
#packet_type ⇒ Object
readonly
Returns the value of attribute packet_type.
Class Method Summary collapse
-
.decode_message(raw_bytes) ⇒ Object
return a Message.
-
.pack(packet, private_key:) ⇒ Object
return a new message instance include packet.
Instance Method Summary collapse
-
#encode_message ⇒ Object
encode message to string.
-
#initialize(message_hash:, signature:, packet_type:, packet_data:) ⇒ Message
constructor
A new instance of Message.
- #packet ⇒ Object
-
#sender ⇒ Object
compute key and return NodeID.
-
#validate ⇒ Object
validate message hash and signature.
Constructor Details
#initialize(message_hash:, signature:, packet_type:, packet_data:) ⇒ Message
Returns a new instance of Message.
45 46 47 48 49 50 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 45 def initialize(message_hash:, signature:, packet_type:, packet_data:) @message_hash = @signature = signature @packet_type = packet_type @packet_data = packet_data end |
Instance Attribute Details
#message_hash ⇒ Object (readonly)
Returns the value of attribute message_hash.
43 44 45 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 43 def @message_hash end |
#packet_data ⇒ Object (readonly)
Returns the value of attribute packet_data.
43 44 45 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 43 def packet_data @packet_data end |
#packet_type ⇒ Object (readonly)
Returns the value of attribute packet_type.
43 44 45 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 43 def packet_type @packet_type end |
Class Method Details
.decode_message(raw_bytes) ⇒ Object
return a Message
102 103 104 105 106 107 108 109 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 102 def (raw_bytes) hash = raw_bytes[0...32] # signature is 65 length r,s,v signature = raw_bytes[32...97] packet_type = Utils.big_endian_decode raw_bytes[97] packet_data = raw_bytes[98..-1] Message.new(message_hash: hash, signature: signature, packet_type: packet_type, packet_data: packet_data) end |
.pack(packet, private_key:) ⇒ Object
return a new message instance include packet
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 112 def pack(packet, private_key:) packet_data = Ciri::RLP.encode(packet) packet_type = packet.class.code encoded_packet_type = Utils.big_endian_encode(packet_type) signature = private_key.ecdsa_signature(Utils.keccak(encoded_packet_type + packet_data)).to_s hash = Utils.keccak(signature + encoded_packet_type + packet_data) if (msg_size=hash.size + signature.size + encoded_packet_type.size + packet_data.size) > MAX_LEN raise InvalidMessageError.new("failed to pack, message size is too long, size: #{msg_size}, max_len: #{MAX_LEN}") end Message.new(message_hash: hash, signature: signature, packet_type: packet_type, packet_data: packet_data) end |
Instance Method Details
#encode_message ⇒ Object
encode message to string
91 92 93 94 95 96 97 98 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 91 def buf = String.new buf << buf << @signature buf << packet_type buf << packet_data buf end |
#packet ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 61 def packet packet_class = case @packet_type when Ping::CODE Ping when Pong::CODE Pong when FindNode::CODE FindNode when Neighbors::CODE Neighbors else raise UnknownMessageCodeError.new("unkonwn discovery message code: #{@packet_type}") end # TODO according discv4 protocol, rlp_decode should support ignore additional elements # we should support ignore_extra_data option in Ciri::RLP packet_class.rlp_decode @packet_data end |
#sender ⇒ Object
compute key and return NodeID
53 54 55 56 57 58 59 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 53 def sender @sender ||= begin encoded_packet_type = Utils.big_endian_encode(packet_type) public_key = Key.ecdsa_recover(Utils.keccak(encoded_packet_type + packet_data), @signature) NodeID.new(public_key) end end |
#validate ⇒ Object
validate message hash and signature
80 81 82 83 84 85 86 87 88 |
# File 'lib/ciri/p2p/discovery/protocol.rb', line 80 def validate encoded_packet_type = Utils.big_endian_encode(packet_type) raise InvalidMessageError.new("mismatch hash") if != Utils.keccak(@signature + encoded_packet_type + packet_data) begin sender rescue StandardError => e raise InvalidMessageError.new("recover sender error: #{e}") end end |