Skip to content

Commit

Permalink
add tests (#82)
Browse files Browse the repository at this point in the history
* add tests

* fix tests

* minor fix

* change to H256

* fmt fix

* test fix

* fix: test cfg and imports

* fix: subxt types change to H256

* fix: cargo fmt

* rm super*

* Remove intermediate copies & use hex for testing (#85)

* Remove intermediate copies & use hex for testing

* test fix on H256

Co-authored-by: Kailas <[email protected]>

* fix readme

* Miguel/ava 349/tests (#86)

* Remove intermediate copies & use hex for testing

* Refactor header builder UTs

Co-authored-by: Prabal Banerjee <[email protected]>
Co-authored-by: Miguel <[email protected]>
  • Loading branch information
3 people authored Sep 20, 2022
1 parent 894fe11 commit fc0f39b
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 34 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions avail-subxt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub struct KateCommitment {
pub cols: u16,
/// The merkle root of the data submissions
#[serde(rename = "dataRoot")]
pub data_root: [u8; 32],
pub data_root: H256,
}

impl MallocSizeOf for KateCommitment {
Expand Down Expand Up @@ -305,7 +305,7 @@ impl Header for DaHeader {
commitment: vec![],
rows: 0,
cols: 0,
data_root: [0; 32],
data_root: H256([0; 32]),
},
digest,
app_data_lookup: DataLookup {
Expand Down
6 changes: 3 additions & 3 deletions pallets/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ mod tests {
commitment: vec![],
rows: 0,
cols: 0,
data_root: [0u8; 32],
data_root: [0u8; 32].into(),
};
let state_root =
hex!("293056F7324B44B6841297FB8076DEDFF6BD04C0F3F7DACBA3781C5CF3B5A80C").into();
Expand Down Expand Up @@ -805,7 +805,7 @@ mod tests {
commitment: vec![],
rows: 0,
cols: 0,
data_root: [0u8; 32],
data_root: [0u8; 32].into(),
};

new_test_ext(1).execute_with(|| {
Expand Down Expand Up @@ -833,7 +833,7 @@ mod tests {
commitment: vec![],
rows: 0,
cols: 0,
data_root: [0u8; 32],
data_root: [0u8; 32].into(),
};

new_test_ext(1).execute_with(|| {
Expand Down
1 change: 1 addition & 0 deletions pallets/system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ sp-runtime-interface = { version = "4.0.0-dev", default-features = false }
[dev-dependencies]
criterion = "0.3.3"
hex-literal = "0.3.1"
test-case = "1.2.3"
sp-externalities = "0.10.0-dev"

[features]
Expand Down
164 changes: 146 additions & 18 deletions pallets/system/src/header_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use frame_support::traits::Randomness;
pub use kate::Seed;
use rs_merkle::{algorithms::Sha256, Hasher, MerkleTree};
use scale_info::TypeInfo;
use sp_core::H256;
use sp_runtime::{traits::Hash, AccountId32, MultiAddress, MultiSignature};
use sp_runtime_interface::{pass_by::PassByCodec, runtime_interface};
use sp_std::vec::Vec;
Expand Down Expand Up @@ -125,24 +126,8 @@ pub trait HostedHeaderBuilder {
(kate_commitment, block_dims, data_index)
};

let extrinsics: Vec<Vec<u8>> = app_extrinsics.into_iter().map(|e| e.data).collect();
let avail_extrinsics = extrinsics
.iter()
.filter_map(|e| <AvailExtrinsic>::decode(&mut &e[..]).ok())
.collect::<Vec<_>>();

let data_root: [u8; 32] = if avail_extrinsics.len() > 0 {
log::debug!("Decoded some avail extrinsics.");
let leaves: Vec<[u8; 32]> = avail_extrinsics
.iter()
.map(|x| Sha256::hash(&x.data))
.collect();

let data_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
data_tree.root().expect("Data Root computation failed")
} else {
Default::default()
};
let extrinsics: Vec<Vec<u8>> = app_extrinsics.clone().into_iter().map(|e| e.data).collect();
let data_root = build_data_root(&app_extrinsics);

log::debug!("Avail Data Root: {:?}\n", data_root);

Expand Down Expand Up @@ -263,3 +248,146 @@ impl Decode for AvailExtrinsic {
})
}
}

fn build_data_root(app_ext: &[AppExtrinsic]) -> H256 {
let mut tree = MerkleTree::<Sha256>::new();

app_ext
.iter()
// NOTE: `AvailExtrinsic` decode fn will filter onlye `Da_Control::submit_data` extrinsics.
// TODO: It implies a circular dependency atm between system & DA control pallets.
.filter_map(|e| AvailExtrinsic::decode(&mut &e.data[..]).ok())
.for_each(|ext| {
let ext_hash = Sha256::hash(&ext.data);
tree.insert(ext_hash);
});

tree.commit();
tree.root().unwrap_or_default().into()
}

#[cfg(test)]
mod tests {
use da_primitives::asdr::AppId;
use hex_literal::hex;
use sp_core::H256;
use test_case::test_case;

use super::*;

fn encoded_timestamp_call() -> AppExtrinsic {
AppExtrinsic {
app_id: 0,
data: hex!("280403000BC26208378301").into(),
}
}

fn encoded_fillblock_call(app_id: AppId) -> AppExtrinsic {
let data = hex!("5D0284001CBD2D43530A44705AD088AF313E18F80B53EF16B36177CD4B77B846F2A5F07C01C44755794EA949E9410390CB4CE07FE2D8068656185B5AB9B43EEF934C3680478968C1F83E360A5D942FE75E9D58E49106A8E8B23601CBC6A633D80E5D089D83A4000400030000001D01A46868616A6B616E636B61206C61682069616B6A206361697568206162206169616A6820612067616861").to_vec();
AppExtrinsic { app_id, data }
}

fn encoded_tx_bob() -> AppExtrinsic {
let data = hex!("490284001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0166de9fcb3903fa119cb6d23dd903b93a67719f76922b2b4c15a2539d11021102b75f4c452595b65b3bacef0e852430bbfa44bd38133b16cd5d48edb45962568204010000000000000600008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4802093d00").to_vec();
AppExtrinsic { app_id: 0, data }
}

fn dr_input_1() -> Vec<AppExtrinsic> {
vec![encoded_timestamp_call(), encoded_fillblock_call(3)]
}

fn dr_output_1() -> H256 {
hex!("DDF368647A902A6F6AB9F53B32245BE28EDC99E92F43F0004BBC2CB359814B2A").into()
}

#[test_case( dr_input_1() => dr_output_1())]
#[test_case( vec![encoded_timestamp_call()] => H256::zero(); "Empty block")]
#[test_case( vec![encoded_tx_bob()] => H256::zero(); "Signed Native Tx")]
fn it_build_data_root(app_extrinsics: Vec<AppExtrinsic>) -> H256 {
build_data_root(&app_extrinsics).into()
}

#[test]
fn test_merkle_proof() {
let avail_data: Vec<Vec<u8>> = vec![
hex!("3033333166613733656565636362653465323235").into(),
hex!("3630646564316635616236373261373132376261").into(),
hex!("3262313166316464333935353666623261623432").into(),
];

let leaves = avail_data
.iter()
.map(|xt| Sha256::hash(&xt))
.collect::<Vec<[u8; 32]>>();

let data_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
let proof = data_tree.proof(&[1usize]);
let root_proof = proof.proof_hashes().to_vec();
assert_eq!(root_proof, vec![
hex!("754B9412E0ED7907BDF4B7CA5D2A22F5E129A03DEB1F4E1C1FE42D322FDEE90E"),
hex!("8D6E30E494D17D7675A94C3C614467FF8CCE35201C1056751A6E9A100515DAF9")
]);
}

#[test]
fn test_single_merkle_proof() {
let empty_vec: Vec<[u8; 32]> = vec![];

let avail_data: Vec<Vec<u8>> =
vec![hex!("3435346666383063303838616137666162396531").to_vec()];

let leaves = avail_data
.iter()
.map(|xt| Sha256::hash(&xt))
.collect::<Vec<[u8; 32]>>();

let data_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
let proof = data_tree.proof(&[0usize]);
let root_proof = proof.proof_hashes().to_vec();
// here the proof is shown empty because the root itself is the proof as there is only one appdata extrinsic
assert_eq!(root_proof, empty_vec);
}

///using rs-merkle proof verify function
#[test]
fn verify_merkle_proof() {
let avail_data: Vec<Vec<u8>> = vec![
hex!("3033333166613733656565636362653465323235").into(),
hex!("3630646564316635616236373261373132376261").into(),
hex!("3262313166316464333935353666623261623432").into(),
hex!("6433326630643762346634306264346563323665").into(),
];
let leaves = avail_data
.iter()
.map(|xt| Sha256::hash(&xt))
.collect::<Vec<[u8; 32]>>();

let merkle_tree = MerkleTree::<Sha256>::from_leaves(&leaves);
let indices_to_prove = vec![3];
let leaves_to_prove = leaves.get(3..4).ok_or("can't get leaves to prove").unwrap();

let proof = merkle_tree.proof(&indices_to_prove);
let root = merkle_tree
.root()
.ok_or("couldn't get the merkle root")
.unwrap();

assert!(proof.verify(root, &indices_to_prove, leaves_to_prove, leaves.len()));
}

#[test]
fn verify_nodata_merkle_proof() {
let avail_data: Vec<Vec<u8>> = vec![];

let leaves = avail_data
.iter()
.map(|xt| Sha256::hash(&xt))
.collect::<Vec<[u8; 32]>>();
let leaves_to_prove = if let Ok(leaves) = leaves.get(0).ok_or("can't get leaves to prove") {
leaves
} else {
&[0u8; 32]
};
assert_eq!(leaves_to_prove, &[0u8; 32]);
}
}
3 changes: 2 additions & 1 deletion primitives/avail/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ mod tests {
data_root: [
63, 191, 50, 39, 146, 108, 250, 63, 65, 103, 119, 30, 90, 217, 28, 250, 44, 45,
112, 144, 102, 124, 224, 30, 145, 28, 169, 11, 79, 49, 91, 17,
],
]
.into(),
};
let data_lookup = DataLookup {
size: 1,
Expand Down
7 changes: 4 additions & 3 deletions primitives/avail/src/kate_commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use codec::{Codec, Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use sp_core::H256;
use sp_runtime::traits::Member;
use sp_std::vec::Vec;

Expand All @@ -22,7 +23,7 @@ pub struct KateCommitment<HashOutput> {
/// Cols
pub cols: u16,
/// The merkle root of the data submitted
pub data_root: [u8; 32],
pub data_root: H256,
}

/// Marker trait for types `T` that can be use as `Hash` in `ExtrinsicsRoot`.
Expand All @@ -37,7 +38,7 @@ impl<HashOutput: KateExtrinsicHash> ExtrinsicsWithCommitment for KateCommitment<

fn commitment(&self) -> &Vec<u8> { &self.commitment }

fn data_root(&self) -> &[u8; 32] { &self.data_root }
fn data_root(&self) -> &H256 { &self.data_root }

fn new(hash: HashOutput) -> Self { hash.into() }

Expand All @@ -46,7 +47,7 @@ impl<HashOutput: KateExtrinsicHash> ExtrinsicsWithCommitment for KateCommitment<
commitment: Vec<u8>,
rows: u16,
cols: u16,
data_root: [u8; 32],
data_root: H256,
) -> Self {
Self {
hash,
Expand Down
4 changes: 2 additions & 2 deletions primitives/avail/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub trait ExtrinsicsWithCommitment {

fn hash(&self) -> &Self::HashOutput;
fn commitment(&self) -> &Vec<u8>;
fn data_root(&self) -> &[u8; 32];
fn data_root(&self) -> &H256;

fn new(hash: Self::HashOutput) -> Self;

Expand All @@ -18,7 +18,7 @@ pub trait ExtrinsicsWithCommitment {
commitment: Vec<u8>,
rows: u16,
cols: u16,
data_root: [u8; 32],
data_root: H256,
) -> Self;
}

Expand Down
1 change: 1 addition & 0 deletions rpc/kate-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ where
data: xt.encode(),
};
let optional_decoded_xt = <AvailExtrinsic>::decode(&mut &avail_extrinsic.data[..]);

match optional_decoded_xt {
Ok(decoded_xt) => leaves.push(Sha256::hash(&decoded_xt.data)),
Err(_) => continue,
Expand Down
2 changes: 1 addition & 1 deletion tests/gsrpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The same procedure of data submission is done here and also listens to the block
>Using SubmitandWatch
```
go run extrinsics/dataSubmitAndWatch/dataSubmitAndWatch.go -- -size 1000
go run extrinsics/dataSubmitAndWatch/dataSubmitAndWatch.go -config config.json
```
The same procedure of data submission is done here. But checks/logs if the data is included in the block. The default APP_ID is 0

Expand Down
2 changes: 1 addition & 1 deletion tests/js_api/src/app_id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async function createApi(): Promise<ApiPromise> {
commitment: 'Vec<u8>',
rows: 'u16',
cols: 'u16',
dataRoot: '[u8;32]',
dataRoot: 'H256',
},
KateHeader: {
parentHash: 'Hash',
Expand Down
2 changes: 1 addition & 1 deletion tests/js_api/src/full.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createApi(): Promise<ApiPromise> {
commitment: 'Vec<u8>',
rows: 'u16',
cols: 'u16',
dataRoot: '[u8;32]',
dataRoot: 'H256',
},
KateHeader: {
parentHash: 'Hash',
Expand Down
2 changes: 1 addition & 1 deletion tests/js_api/src/sub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createApi(): Promise<ApiPromise> {
commitment: 'Vec<u8>',
rows: 'u16',
cols: 'u16',
dataRoot: '[u8;32]',
dataRoot: 'H256',
},
KateHeader: {
parentHash: 'Hash',
Expand Down
2 changes: 1 addition & 1 deletion tests/js_api/src/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createApi(): Promise<ApiPromise> {
commitment: 'Vec<u8>',
rows: 'u16',
cols: 'u16',
dataRoot: '[u8;32]',
dataRoot: 'H256',
},
KateHeader: {
parentHash: 'Hash',
Expand Down

0 comments on commit fc0f39b

Please sign in to comment.