use crate::util::protobuf;
use alloc::{borrow::Cow, vec::Vec};
pub const LIGHT_PROTOCOL_REQUEST_MAX_SIZE: usize = 1024 * 1024;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StorageProofRequestConfig<TKeysIter> {
pub block_hash: [u8; 32],
pub keys: TKeysIter,
}
pub fn build_storage_proof_request<'a>(
config: StorageProofRequestConfig<impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + 'a>,
) -> impl Iterator<Item = impl AsRef<[u8]>> {
protobuf::message_tag_encode(
2,
protobuf::bytes_tag_encode(2, config.block_hash)
.map(either::Left)
.chain(
config
.keys
.flat_map(|key| protobuf::bytes_tag_encode(3, key))
.map(either::Right),
),
)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CallProofRequestConfig<'a, I> {
pub block_hash: [u8; 32],
pub method: Cow<'a, str>,
pub parameter_vectored: I,
}
pub fn build_call_proof_request<'a>(
config: CallProofRequestConfig<'a, impl Iterator<Item = impl AsRef<[u8]> + 'a> + 'a>,
) -> impl Iterator<Item = impl AsRef<[u8]>> {
let parameter = config
.parameter_vectored
.fold(Vec::with_capacity(512), |mut a, b| {
a.extend_from_slice(b.as_ref());
a
});
protobuf::message_tag_encode(
1,
protobuf::bytes_tag_encode(2, config.block_hash)
.map(either::Left)
.chain(
protobuf::string_tag_encode(3, config.method)
.map(either::Left)
.map(either::Right),
)
.chain(
protobuf::bytes_tag_encode(4, parameter)
.map(either::Right)
.map(either::Right),
),
)
}
pub fn decode_storage_or_call_proof_response(
ty: StorageOrCallProof,
response_bytes: &[u8],
) -> Result<Option<&[u8]>, DecodeStorageCallProofResponseError> {
let field_num = match ty {
StorageOrCallProof::CallProof => 1,
StorageOrCallProof::StorageProof | StorageOrCallProof::ChildStorageProof => 2,
};
let mut parser = nom::combinator::all_consuming::<_, nom::error::Error<&[u8]>, _>(
nom::combinator::complete(protobuf::message_decode! {
#[optional] response = field_num => protobuf::message_tag_decode(protobuf::message_decode!{
#[optional] proof = 2 => protobuf::bytes_tag_decode
}),
}),
);
let proof = match nom::Finish::finish(nom::Parser::parse(&mut parser, response_bytes)) {
Ok((_, out)) => out.response.and_then(|r| r.proof),
Err(_) => return Err(DecodeStorageCallProofResponseError::ProtobufDecode),
};
Ok(proof)
}
#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
pub enum DecodeStorageCallProofResponseError {
ProtobufDecode,
BadResponseTy,
ProofDecodeError,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StorageOrCallProof {
StorageProof,
CallProof,
ChildStorageProof,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChildStorageProofRequestConfig<TChildTrie, TKeysIter> {
pub block_hash: [u8; 32],
pub child_trie: TChildTrie,
pub keys: TKeysIter,
}
pub fn build_child_storage_proof_request<'a>(
config: ChildStorageProofRequestConfig<
impl AsRef<[u8]> + Clone + 'a,
impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + 'a,
>,
) -> impl Iterator<Item = impl AsRef<[u8]>> {
protobuf::message_tag_encode(
4,
protobuf::bytes_tag_encode(2, config.block_hash)
.map(either::Left)
.chain(
protobuf::bytes_tag_encode(3, config.child_trie)
.map(either::Left)
.map(either::Right),
)
.chain(
config
.keys
.flat_map(|key| protobuf::bytes_tag_encode(6, key))
.map(either::Right)
.map(either::Right),
),
)
}