Restore GetNodeData (#469)

* Accept GetNodeData requests

* Implement blockchain client method for node data requests

* Reuse old database read methods for node data

* fmt

* Copy & paste old tests...

* ... and make them work

* fmt
This commit is contained in:
Jochen Müller
2021-07-05 17:06:35 +02:00
committed by GitHub
parent 43ee520904
commit 38e40f649c
12 changed files with 185 additions and 5 deletions

View File

@@ -169,6 +169,7 @@ pub const PAR_PROTOCOL_VERSION_2: (u8, u8) = (2, 0x16);
pub const MAX_BODIES_TO_SEND: usize = 256;
pub const MAX_HEADERS_TO_SEND: usize = 512;
pub const MAX_NODE_DATA_TO_SEND: usize = 1024;
pub const MAX_RECEIPTS_HEADERS_TO_SEND: usize = 256;
pub const MAX_TRANSACTIONS_TO_REQUEST: usize = 256;
const MIN_PEERS_PROPAGATION: usize = 4;

View File

@@ -40,6 +40,7 @@ use super::{
ChainSync, PacketProcessError, RlpResponseResult, SyncHandler, MAX_BODIES_TO_SEND,
MAX_HEADERS_TO_SEND, MAX_RECEIPTS_HEADERS_TO_SEND,
};
use chain::MAX_NODE_DATA_TO_SEND;
use std::borrow::Borrow;
/// The Chain Sync Supplier: answers requests from peers with available data
@@ -88,6 +89,15 @@ impl SyncSupplier {
|e| format!("Error sending block headers: {:?}", e),
),
GetNodeDataPacket => SyncSupplier::return_rlp(
io,
&rlp,
peer,
request_id,
SyncSupplier::return_node_data,
|e| format!("Error sending node data: {:?}", e),
),
GetReceiptsPacket => SyncSupplier::return_rlp(
io,
&rlp,
@@ -340,6 +350,32 @@ impl SyncSupplier {
Ok(Some((BlockBodiesPacket, rlp)))
}
fn return_node_data(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult {
let count = cmp::min(rlp.item_count().unwrap_or(0), MAX_NODE_DATA_TO_SEND);
if count == 0 {
debug!(target: "sync", "Empty GetNodeData request, ignoring.");
return Ok(None);
}
let mut data = Bytes::new();
let mut added = 0usize;
for i in 0..count {
if let Some(ref mut node_data) = io.chain().state_data(&rlp.val_at::<H256>(i)?) {
data.append(node_data);
added += 1;
if data.len() > PAYLOAD_SOFT_LIMIT {
break;
}
}
}
let mut rlp = RlpStream::new_list(added);
rlp.append_raw(&data, added);
trace!(target: "sync", "{} -> GetNodeData: returned {} entries", peer_id, added);
Ok(Some((NodeDataPacket, rlp)))
}
fn return_receipts(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult {
let mut count = rlp.item_count().unwrap_or(0);
trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count);
@@ -723,4 +759,51 @@ mod test {
);
assert_eq!(1, io.packets.len());
}
#[test]
fn return_nodes() {
let mut client = TestBlockChainClient::new();
let queue = RwLock::new(VecDeque::new());
let sync = dummy_sync_with_peer(H256::zero(), &client);
let ss = TestSnapshotService::new();
let mut io = TestIo::new(&mut client, &ss, &queue, None);
let mut node_list = RlpStream::new_list(3);
node_list.append(
&H256::from_str("0000000000000000000000000000000000000000000000005555555555555555")
.unwrap(),
);
node_list.append(
&H256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa")
.unwrap(),
);
node_list.append(
&H256::from_str("aff0000000000000000000000000000000000000000000000000000000000000")
.unwrap(),
);
let node_request = node_list.out();
// it returns rlp ONLY for hashes started with "f"
let result = SyncSupplier::return_node_data(&io, &Rlp::new(&node_request.clone()), 0);
assert!(result.is_ok());
let rlp_result = result.unwrap();
assert!(rlp_result.is_some());
// the length of one rlp-encoded hashe
let rlp = rlp_result.unwrap().1.out();
let rlp = Rlp::new(&rlp);
assert_eq!(Ok(1), rlp.item_count());
io.sender = Some(2usize);
SyncSupplier::dispatch_packet(
&RwLock::new(sync),
&mut io,
0usize,
GetNodeDataPacket.id(),
&node_request,
);
assert_eq!(1, io.packets.len());
}
}

View File

@@ -48,8 +48,8 @@ pub enum SyncPacket {
GetPooledTransactionsPacket = 0x09,
PooledTransactionsPacket = 0x0a,
//GetNodeDataPacket = 0x0d,
//NodeDataPacket = 0x0e,
GetNodeDataPacket = 0x0d,
NodeDataPacket = 0x0e,
GetReceiptsPacket = 0x0f,
ReceiptsPacket = 0x10,
@@ -87,8 +87,8 @@ impl PacketInfo for SyncPacket {
| NewPooledTransactionHashesPacket
| GetPooledTransactionsPacket
| PooledTransactionsPacket
//| GetNodeDataPacket
//| NodeDataPacket
| GetNodeDataPacket
| NodeDataPacket
| GetReceiptsPacket
| ReceiptsPacket => ETH_PROTOCOL,
@@ -105,7 +105,6 @@ impl PacketInfo for SyncPacket {
}
fn has_request_id_in_eth_66(&self) -> bool {
// Note: NodeDataPacket and GetNodeDataPacket also get a request id in eth-66.
match self {
GetBlockHeadersPacket
| BlockHeadersPacket
@@ -113,6 +112,8 @@ impl PacketInfo for SyncPacket {
| BlockBodiesPacket
| GetPooledTransactionsPacket
| PooledTransactionsPacket
| GetNodeDataPacket
| NodeDataPacket
| GetReceiptsPacket
| ReceiptsPacket => true,
_ => false,