Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request paritytech#119 from subspace/object-mapping-pallet…
Browse files Browse the repository at this point in the history
…-utility

Object mapping pallet utility + tests
  • Loading branch information
nazar-pc authored Nov 8, 2021
2 parents 170ce1b + f4d4c2f commit 0a7c7d7
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 7 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 65 additions & 6 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,54 @@ fn extract_root_block(encoded_extrinsic: Vec<u8>) -> Option<RootBlock> {
None
}

fn extract_feeds_block_object_mapping(
base_offset: u32,
objects: &mut Vec<BlockObject>,
call: &pallet_feeds::Call<Runtime>,
) {
if let Some(call_object_location) = call.extract_object_location() {
objects.push(BlockObject::V0 {
hash: call_object_location.hash,
offset: base_offset + call_object_location.offset,
});
}
}

fn extract_utility_block_object_mapping(
base_offset: u32,
objects: &mut Vec<BlockObject>,
call: &pallet_utility::Call<Runtime>,
) {
// Add enum variant to the offset
let mut base_nested_call_offset = base_offset + 1;

match call {
pallet_utility::Call::batch { calls } | pallet_utility::Call::batch_all { calls } => {
base_nested_call_offset += Compact::compact_len(&(calls.len() as u32)) as u32;

for call in calls {
if let Call::Feeds(call) = call {
// `+1` for enum variant offset
extract_feeds_block_object_mapping(base_nested_call_offset + 1, objects, call);
}

base_nested_call_offset += call.encoded_size() as u32;
}
}
pallet_utility::Call::as_derivative { index, call } => {
base_nested_call_offset += index.encoded_size() as u32;

if let Call::Feeds(call) = call.as_ref() {
// `+1` for enum variant offset
extract_feeds_block_object_mapping(base_nested_call_offset + 1, objects, call);
}
}
pallet_utility::Call::__Ignore(_, _) => {
// Ignore.
}
}
}

fn extract_block_object_mapping(block: Block) -> BlockObjectMapping {
let mut block_object_mapping = BlockObjectMapping::default();
let mut base_offset =
Expand All @@ -486,12 +534,23 @@ fn extract_block_object_mapping(block: Block) -> BlockObjectMapping {
+ signature_size
+ 1;

if let Call::Feeds(call) = &extrinsic.function {
if let Some(call_object_location) = call.extract_object_location() {
block_object_mapping.objects.push(BlockObject::V0 {
hash: call_object_location.hash,
offset: base_extrinsic_offset as u32 + call_object_location.offset,
});
match &extrinsic.function {
Call::Feeds(call) => {
extract_feeds_block_object_mapping(
base_extrinsic_offset as u32,
&mut block_object_mapping.objects,
call,
);
}
Call::Utility(call) => {
extract_utility_block_object_mapping(
base_extrinsic_offset as u32,
&mut block_object_mapping.objects,
call,
);
}
_ => {
// No other pallets store useful data yet.
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/subspace-runtime/tests/integration/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod object_mapping;
130 changes: 130 additions & 0 deletions crates/subspace-runtime/tests/integration/object_mapping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use codec::Encode;
use sp_consensus_subspace::runtime_decl_for_SubspaceApi::SubspaceApi;
use subspace_core_primitives::crypto;
use subspace_core_primitives::objects::BlockObjectMapping;
use subspace_runtime::{Block, Call, Header, Runtime, UncheckedExtrinsic};

#[test]
fn object_mapping() {
let data0: Vec<u8> = (0..=99).collect();
let data1: Vec<u8> = (123..=255).collect();
let data2: Vec<u8> = (0..=99).rev().collect();
let data3: Vec<u8> = (123..=255).rev().collect();
let block = Block {
header: Header {
parent_hash: Default::default(),
number: Default::default(),
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
},
extrinsics: vec![
UncheckedExtrinsic {
signature: None,
function: Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data0.clone(),
metadata: vec![1, 2, 3],
}),
},
UncheckedExtrinsic {
signature: None,
function: Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data1.clone(),
metadata: vec![],
}),
},
UncheckedExtrinsic {
signature: None,
function: Call::Utility(pallet_utility::Call::batch {
calls: vec![
Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data2.clone(),
metadata: vec![1, 2, 3],
}),
Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data3.clone(),
metadata: vec![],
}),
],
}),
},
UncheckedExtrinsic {
signature: None,
function: Call::Utility(pallet_utility::Call::as_derivative {
index: 0,
call: Box::new(Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data0.clone(),
metadata: vec![1, 2, 3],
})),
}),
},
UncheckedExtrinsic {
signature: None,
function: Call::Utility(pallet_utility::Call::batch_all {
calls: vec![
Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data2.clone(),
metadata: vec![1, 2, 3],
}),
Call::Feeds(pallet_feeds::Call::put {
feed_id: 0,
data: data3.clone(),
metadata: vec![],
}),
],
}),
},
],
};

let encoded_block = block.encode();
let BlockObjectMapping { objects } = Runtime::extract_block_object_mapping(block);

// Expect all 7 objects to be mapped.
assert_eq!(objects.len(), 7);

// Hashes shoudl be computed correctly.
assert_eq!(objects[0].hash(), crypto::sha256_hash(&data0));
assert_eq!(objects[1].hash(), crypto::sha256_hash(&data1));
assert_eq!(objects[2].hash(), crypto::sha256_hash(&data2));
assert_eq!(objects[3].hash(), crypto::sha256_hash(&data3));
assert_eq!(objects[4].hash(), crypto::sha256_hash(&data0));
assert_eq!(objects[5].hash(), crypto::sha256_hash(&data2));
assert_eq!(objects[6].hash(), crypto::sha256_hash(&data3));

// Offsets for mapped objects should be correct
assert_eq!(
&encoded_block[objects[0].offset() as usize..][..data0.encoded_size()],
&data0.encode()
);
assert_eq!(
&encoded_block[objects[1].offset() as usize..][..data1.encoded_size()],
&data1.encode()
);
assert_eq!(
&encoded_block[objects[2].offset() as usize..][..data2.encoded_size()],
&data2.encode()
);
assert_eq!(
&encoded_block[objects[3].offset() as usize..][..data3.encoded_size()],
&data3.encode()
);
assert_eq!(
&encoded_block[objects[4].offset() as usize..][..data0.encoded_size()],
&data0.encode()
);
assert_eq!(
&encoded_block[objects[5].offset() as usize..][..data2.encoded_size()],
&data2.encode()
);
assert_eq!(
&encoded_block[objects[6].offset() as usize..][..data3.encoded_size()],
&data3.encode()
);
}

0 comments on commit 0a7c7d7

Please sign in to comment.