mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 20:07:56 +00:00
Child trie storage proof (#2433)
* proof on child trie * higher level api for child storage proof * boilerplate for proof from light fetch * actually check proof on light fetch * Do not break former encoding * tabify * tabify2 * Add child trie root tx to full_storage_root transaction. * Shorten long lines. * Temp rename for audit * Make full_storage a trait method * Name back and replace some code with full_storage where it looks fine. * fix indentations, remove unused import * flush child root to top when calculated * impl +1
This commit is contained in:
@@ -23,7 +23,7 @@ pub use self::generic::{
|
||||
BlockAnnounce, RemoteCallRequest, RemoteReadRequest,
|
||||
RemoteHeaderRequest, RemoteHeaderResponse,
|
||||
RemoteChangesRequest, RemoteChangesResponse,
|
||||
FromBlock
|
||||
FromBlock, RemoteReadChildRequest,
|
||||
};
|
||||
|
||||
/// A unique ID of a request.
|
||||
@@ -129,8 +129,8 @@ pub mod generic {
|
||||
use runtime_primitives::Justification;
|
||||
use crate::config::Roles;
|
||||
use super::{
|
||||
BlockAttributes, RemoteCallResponse, RemoteReadResponse,
|
||||
RequestId, Transactions, Direction, ConsensusEngineId,
|
||||
RemoteReadResponse, Transactions, Direction,
|
||||
RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId,
|
||||
};
|
||||
/// Consensus is mostly opaque to us
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||
@@ -198,6 +198,8 @@ pub mod generic {
|
||||
RemoteChangesRequest(RemoteChangesRequest<Hash>),
|
||||
/// Remote changes reponse.
|
||||
RemoteChangesResponse(RemoteChangesResponse<Number, Hash>),
|
||||
/// Remote child storage read request.
|
||||
RemoteReadChildRequest(RemoteReadChildRequest<Hash>),
|
||||
/// Chain-specific message
|
||||
#[codec(index = "255")]
|
||||
ChainSpecific(Vec<u8>),
|
||||
@@ -291,6 +293,19 @@ pub mod generic {
|
||||
pub key: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||
/// Remote storage read child request.
|
||||
pub struct RemoteReadChildRequest<H> {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Block at which to perform call.
|
||||
pub block: H,
|
||||
/// Child Storage key.
|
||||
pub storage_key: Vec<u8>,
|
||||
/// Storage key.
|
||||
pub key: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||
/// Remote header request.
|
||||
pub struct RemoteHeaderRequest<N> {
|
||||
|
||||
@@ -27,7 +27,8 @@ use linked_hash_map::Entry;
|
||||
use parking_lot::Mutex;
|
||||
use client::error::Error as ClientError;
|
||||
use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest,
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof};
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof,
|
||||
RemoteReadChildRequest};
|
||||
use crate::message;
|
||||
use network_libp2p::PeerId;
|
||||
use crate::config::Roles;
|
||||
@@ -107,6 +108,10 @@ struct Request<Block: BlockT> {
|
||||
enum RequestData<Block: BlockT> {
|
||||
RemoteHeader(RemoteHeaderRequest<Block::Header>, OneShotSender<Result<Block::Header, ClientError>>),
|
||||
RemoteRead(RemoteReadRequest<Block::Header>, OneShotSender<Result<Option<Vec<u8>>, ClientError>>),
|
||||
RemoteReadChild(
|
||||
RemoteReadChildRequest<Block::Header>,
|
||||
OneShotSender<Result<Option<Vec<u8>>, ClientError>>
|
||||
),
|
||||
RemoteCall(RemoteCallRequest<Block::Header>, OneShotSender<Result<Vec<u8>, ClientError>>),
|
||||
RemoteChanges(RemoteChangesRequest<Block::Header>, OneShotSender<Result<Vec<(NumberFor<Block>, u32)>, ClientError>>),
|
||||
}
|
||||
@@ -271,14 +276,30 @@ impl<B> OnDemandService<B> for OnDemand<B> where
|
||||
|
||||
fn on_remote_read_response(&self, peer: PeerId, response: message::RemoteReadResponse) {
|
||||
self.accept_response("read", peer, response.id, |request| match request.data {
|
||||
RequestData::RemoteRead(request, sender) => match self.checker.check_read_proof(&request, response.proof) {
|
||||
Ok(response) => {
|
||||
// we do not bother if receiver has been dropped already
|
||||
let _ = sender.send(Ok(response));
|
||||
Accept::Ok
|
||||
},
|
||||
Err(error) => Accept::CheckFailed(error, RequestData::RemoteRead(request, sender)),
|
||||
},
|
||||
RequestData::RemoteRead(request, sender) => {
|
||||
match self.checker.check_read_proof(&request, response.proof) {
|
||||
Ok(response) => {
|
||||
// we do not bother if receiver has been dropped already
|
||||
let _ = sender.send(Ok(response));
|
||||
Accept::Ok
|
||||
},
|
||||
Err(error) => Accept::CheckFailed(
|
||||
error,
|
||||
RequestData::RemoteRead(request, sender)
|
||||
),
|
||||
}},
|
||||
RequestData::RemoteReadChild(request, sender) => {
|
||||
match self.checker.check_read_child_proof(&request, response.proof) {
|
||||
Ok(response) => {
|
||||
// we do not bother if receiver has been dropped already
|
||||
let _ = sender.send(Ok(response));
|
||||
Accept::Ok
|
||||
},
|
||||
Err(error) => Accept::CheckFailed(
|
||||
error,
|
||||
RequestData::RemoteReadChild(request, sender)
|
||||
),
|
||||
}},
|
||||
data => Accept::Unexpected(data),
|
||||
})
|
||||
}
|
||||
@@ -335,8 +356,23 @@ impl<B> Fetcher<B> for OnDemand<B> where
|
||||
|
||||
fn remote_read(&self, request: RemoteReadRequest<B::Header>) -> Self::RemoteReadResult {
|
||||
let (sender, receiver) = channel();
|
||||
self.schedule_request(request.retry_count.clone(), RequestData::RemoteRead(request, sender),
|
||||
RemoteResponse { receiver })
|
||||
self.schedule_request(
|
||||
request.retry_count.clone(),
|
||||
RequestData::RemoteRead(request, sender),
|
||||
RemoteResponse { receiver }
|
||||
)
|
||||
}
|
||||
|
||||
fn remote_read_child(
|
||||
&self,
|
||||
request: RemoteReadChildRequest<B::Header>
|
||||
) -> Self::RemoteReadResult {
|
||||
let (sender, receiver) = channel();
|
||||
self.schedule_request(
|
||||
request.retry_count.clone(),
|
||||
RequestData::RemoteReadChild(request, sender),
|
||||
RemoteResponse { receiver }
|
||||
)
|
||||
}
|
||||
|
||||
fn remote_call(&self, request: RemoteCallRequest<B::Header>) -> Self::RemoteCallResult {
|
||||
@@ -477,6 +513,7 @@ impl<Block: BlockT> Request<Block> {
|
||||
match self.data {
|
||||
RequestData::RemoteHeader(ref data, _) => data.block,
|
||||
RequestData::RemoteRead(ref data, _) => *data.header.number(),
|
||||
RequestData::RemoteReadChild(ref data, _) => *data.header.number(),
|
||||
RequestData::RemoteCall(ref data, _) => *data.header.number(),
|
||||
RequestData::RemoteChanges(ref data, _) => data.max_block.0,
|
||||
}
|
||||
@@ -495,6 +532,14 @@ impl<Block: BlockT> Request<Block> {
|
||||
block: data.block,
|
||||
key: data.key.clone(),
|
||||
}),
|
||||
RequestData::RemoteReadChild(ref data, _) =>
|
||||
message::generic::Message::RemoteReadChildRequest(
|
||||
message::RemoteReadChildRequest {
|
||||
id: self.id,
|
||||
block: data.block,
|
||||
storage_key: data.storage_key.clone(),
|
||||
key: data.key.clone(),
|
||||
}),
|
||||
RequestData::RemoteCall(ref data, _) =>
|
||||
message::generic::Message::RemoteCallRequest(message::RemoteCallRequest {
|
||||
id: self.id,
|
||||
@@ -522,6 +567,7 @@ impl<Block: BlockT> RequestData<Block> {
|
||||
RequestData::RemoteHeader(_, sender) => { let _ = sender.send(Err(error)); },
|
||||
RequestData::RemoteCall(_, sender) => { let _ = sender.send(Err(error)); },
|
||||
RequestData::RemoteRead(_, sender) => { let _ = sender.send(Err(error)); },
|
||||
RequestData::RemoteReadChild(_, sender) => { let _ = sender.send(Err(error)); },
|
||||
RequestData::RemoteChanges(_, sender) => { let _ = sender.send(Err(error)); },
|
||||
}
|
||||
}
|
||||
@@ -535,7 +581,8 @@ pub mod tests {
|
||||
use runtime_primitives::traits::NumberFor;
|
||||
use client::{error::{Error as ClientError, Result as ClientResult}};
|
||||
use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest,
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof};
|
||||
ChangesProof, RemoteCallRequest, RemoteReadRequest,
|
||||
RemoteReadChildRequest, RemoteChangesRequest};
|
||||
use crate::config::Roles;
|
||||
use crate::message;
|
||||
use network_libp2p::PeerId;
|
||||
@@ -566,6 +613,17 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_read_child_proof(
|
||||
&self,
|
||||
_: &RemoteReadChildRequest<Header>,
|
||||
_: Vec<Vec<u8>>
|
||||
) -> ClientResult<Option<Vec<u8>>> {
|
||||
match self.ok {
|
||||
true => Ok(Some(vec![42])),
|
||||
false => Err(ClientError::Backend("Test error".into())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_execution_proof(&self, _: &RemoteCallRequest<Header>, _: Vec<Vec<u8>>) -> ClientResult<Vec<u8>> {
|
||||
match self.ok {
|
||||
true => Ok(vec![42]),
|
||||
@@ -847,6 +905,34 @@ pub mod tests {
|
||||
thread.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn receives_remote_read_child_response() {
|
||||
let (_x, on_demand) = dummy(true);
|
||||
let (network_sender, _network_port) = network_channel();
|
||||
let peer0 = PeerId::random();
|
||||
on_demand.set_network_sender(network_sender.clone());
|
||||
on_demand.on_connect(peer0.clone(), Roles::FULL, 1000);
|
||||
|
||||
let response = on_demand.remote_read_child(RemoteReadChildRequest {
|
||||
header: dummy_header(),
|
||||
block: Default::default(),
|
||||
storage_key: b":child_storage:sub".to_vec(),
|
||||
key: b":key".to_vec(),
|
||||
retry_count: None,
|
||||
});
|
||||
let thread = ::std::thread::spawn(move || {
|
||||
let result = response.wait().unwrap();
|
||||
assert_eq!(result, Some(vec![42]));
|
||||
});
|
||||
|
||||
on_demand.on_remote_read_response(
|
||||
peer0.clone(), message::RemoteReadResponse {
|
||||
id: 0,
|
||||
proof: vec![vec![2]],
|
||||
});
|
||||
thread.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn receives_remote_header_response() {
|
||||
let (_x, on_demand) = dummy(true);
|
||||
|
||||
Reference in New Issue
Block a user