Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dbe84f6
store peer data in buckets
ricomateo Jul 10, 2024
1773ba9
add TODO comment
ricomateo Jul 10, 2024
13c8063
add getters for Node fields
ricomateo Jul 10, 2024
03c2db6
change Node fields back to private
ricomateo Jul 10, 2024
7553afa
add getter for NeighborsMessage nodes field
ricomateo Jul 10, 2024
426c852
remove unnecessary getters
ricomateo Jul 10, 2024
08bf1e8
add KademliaTable to hold buckets and peer data
ricomateo Jul 10, 2024
d58a3d8
add PeerData and move table.rs out of types directory (and rename it …
ricomateo Jul 10, 2024
9fbc5c6
move bootnode.rs out of types directory and delete types
ricomateo Jul 10, 2024
3508e70
add ENRRequestMessage decoding
ricomateo Jul 10, 2024
c12004c
Merge branch 'store-peer-data' into enr-request-decoding
ricomateo Jul 10, 2024
5ea9dee
add ENRRequestMessage encoding
ricomateo Jul 10, 2024
cc95747
add ENRResponse decoding (without optional fields)
ricomateo Jul 11, 2024
160a11e
merge enr-request-encoding
ricomateo Jul 11, 2024
8277320
add optional fields decoding
ricomateo Jul 11, 2024
36877db
rename ENRResponseContent to NodeRecord
ricomateo Jul 11, 2024
bbb8485
rename and add documentation to the decode_node_record_optional_field…
ricomateo Jul 11, 2024
9558308
small fix
ricomateo Jul 11, 2024
d3c7f45
add ENRResponseMessage encoding (not working)
ricomateo Jul 11, 2024
ed40380
refactor: optional key value pairs encoding
ricomateo Jul 12, 2024
8c2ea13
refactor: change NodeRecord to hold the optional fields in a vector o…
ricomateo Jul 12, 2024
ee4f8aa
small fixes
ricomateo Jul 12, 2024
057b3de
add some documentation
ricomateo Jul 12, 2024
02f7c04
merge main
ricomateo Jul 12, 2024
8737f96
rename function and add some more documentation
ricomateo Jul 12, 2024
f5ce81b
add 'id' as a required field
ricomateo Jul 12, 2024
7aeee0e
fix linter
ricomateo Jul 15, 2024
534dc2d
merge enr-response-decoding
ricomateo Jul 15, 2024
cf1ccd6
refactor encoding so it stores optional fields as key, value pairs
ricomateo Jul 15, 2024
1001c99
merge main
ricomateo Jul 16, 2024
371942d
small fix
ricomateo Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/core/src/rlp/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::{
error::RLPDecodeError,
};
use bytes::BufMut;
use bytes::Bytes;

/// # Struct decoding helper
///
Expand Down Expand Up @@ -190,6 +191,17 @@ impl<'a> Encoder<'a> {
self
}

/// Stores a (key, value) list where the values are already encoded (i.e. value = RLP prefix || payload)
/// but the keys are not encoded
pub fn encode_key_value_list<T: RLPEncode>(mut self, list: &Vec<(Bytes, Bytes)>) -> Self {
for (key, value) in list {
<Bytes>::encode(key, &mut self.temp_buf);
// value is already encoded
self.temp_buf.put_slice(value);
}
self
}

/// Finishes encoding the struct and writes the result to the buffer.
pub fn finish(self) {
encode_length(self.temp_buf.len(), self.buf);
Expand Down
96 changes: 95 additions & 1 deletion crates/net/src/discv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ impl Message {
Message::Pong(msg) => msg.encode(buf),
Message::FindNode(msg) => msg.encode(buf),
Message::ENRRequest(msg) => msg.encode(buf),
Message::ENRResponse(msg) => msg.encode(buf),
Message::Neighbors(msg) => msg.encode(buf),
_ => todo!(),
}
}

Expand Down Expand Up @@ -514,6 +514,25 @@ impl RLPEncode for ENRRequestMessage {
}
}

impl RLPEncode for ENRResponseMessage {
fn encode(&self, buf: &mut dyn BufMut) {
structs::Encoder::new(buf)
.encode_field(&self.request_hash)
.encode_field(&self.node_record)
.finish();
}
}

impl RLPEncode for NodeRecord {
fn encode(&self, buf: &mut dyn BufMut) {
structs::Encoder::new(buf)
.encode_field(&self.signature)
.encode_field(&self.seq)
.encode_key_value_list::<Bytes>(&self.pairs)
.finish();
}
}

impl RLPEncode for Node {
fn encode(&self, buf: &mut dyn BufMut) {
structs::Encoder::new(buf)
Expand Down Expand Up @@ -719,6 +738,81 @@ mod tests {
assert_eq!(result, expected);
}

#[test]
fn test_encode_enr_response() {
let request_hash =
H256::from_str("ebc0a41dfdf5499552fb7e61799c577360a442170dbed4cb0745d628f06d9f98")
.unwrap();
let signature = H512::from_str("131d8cbc28a2dee4cae36ee3c268c44877e77eb248758d5a204df36b29a13ee53100fd47d3d6fd498ea48349d822d0965904fabcdeeecd9f5133a6062abdfbe3").unwrap();
let seq = 0x018cf3c3bd18;

// define optional fields
let eth: Vec<Vec<u32>> = vec![vec![0x88cf81d9, 0]];
let id = String::from("v4");
let ip = Ipv4Addr::from_str("138.197.51.181").unwrap();
let secp256k1 =
H264::from_str("034e5e92199ee224a01932a377160aa432f31d0b351f84ab413a8e0a42f4f36476")
.unwrap();
let tcp: u16 = 30303;
let udp: u16 = 30303;
let snap: Vec<u32> = vec![];

// declare buffers for optional fields encoding
let mut eth_rlp = Vec::new();
let mut id_rlp = Vec::new();
let mut ip_rlp = Vec::new();
let mut secp256k1_rlp = Vec::new();
let mut tcp_rlp = Vec::new();
let mut udp_rlp = Vec::new();
let mut snap_rlp = Vec::new();

// encode optional fields
eth.encode(&mut eth_rlp);
id.encode(&mut id_rlp);
ip.encode(&mut ip_rlp);
secp256k1.encode(&mut secp256k1_rlp);
tcp.encode(&mut tcp_rlp);
udp.encode(&mut udp_rlp);
snap.encode(&mut snap_rlp);

// initialize vector with (key, value) pairs
let pairs: Vec<(Bytes, Bytes)> = vec![
(String::from("eth").into(), eth_rlp.into()),
(String::from("id").into(), id_rlp.into()),
(String::from("ip").into(), ip_rlp.into()),
(String::from("secp256k1").into(), secp256k1_rlp.into()),
(String::from("snap").into(), snap_rlp.into()),
(String::from("tcp").into(), tcp_rlp.clone().into()),
(String::from("udp").into(), udp_rlp.clone().into()),
];
let node_record = NodeRecord {
signature,
seq,
id: String::from("v4"),
pairs,
};
let msg = Message::ENRResponse(ENRResponseMessage {
request_hash,
node_record,
});

let key_bytes =
H256::from_str("2e6a09427ba14acc853cbbff291c75c3cb57754ac1e3df8df9cac086b3a83aa4")
.unwrap();
let signer = SigningKey::from_slice(key_bytes.as_bytes()).unwrap();
let mut buf = Vec::new();
msg.encode_with_header(&mut buf, &signer);
let result = to_hex(&buf);

let hash = "85e7d3ee8494d23694e2cbcc495be900bb035969366c4b3267ba80eef6cc9b2a";
let signature = "7b714d79b4f8ec780b27329a6a8cb8188b882ecf99be0f89feeab33ebbb76ecb3dcb5ab53a1c7f27a4fc9e6e70220e614de9a351c3f39e100f40b5d0e2a7331501";
let packet_type = "06";
let encoded_msg = "f8c6a0ebc0a41dfdf5499552fb7e61799c577360a442170dbed4cb0745d628f06d9f98f8a3b840131d8cbc28a2dee4cae36ee3c268c44877e77eb248758d5a204df36b29a13ee53100fd47d3d6fd498ea48349d822d0965904fabcdeeecd9f5133a6062abdfbe386018cf3c3bd1883657468c7c68488cf81d980826964827634826970848ac533b589736563703235366b31a1034e5e92199ee224a01932a377160aa432f31d0b351f84ab413a8e0a42f4f3647684736e6170c08374637082765f8375647082765f";
let expected = [hash, signature, packet_type, encoded_msg].concat();

assert_eq!(result, expected);
}

#[test]
fn test_decode_pong_message_with_enr_seq() {
let hash = "2e1fc2a02ad95a1742f6dd41fb7cbff1e08548ba87f63a72221e44026ab1c347";
Expand Down