Skip to content

Commit

Permalink
Add description field to test vectors and validate in workflow tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dmidem committed Dec 24, 2024
1 parent 2bc3ba4 commit 33ae89f
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 15 deletions.
2 changes: 1 addition & 1 deletion zebra-chain/src/orchard_zsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod burn;
mod issuance;

pub(crate) use burn::{Burn, NoBurn};
pub(crate) use issuance::IssueData;
pub use issuance::IssueData;

pub use burn::BurnItem;

Expand Down
38 changes: 24 additions & 14 deletions zebra-consensus/src/orchard_zsa/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ use zebra_test::{

use crate::{block::Request, Config};

mod block_description;

use block_description::build_block_description;

type TranscriptItem = (Request, Result<Hash, ExpectedTranscriptError>);

/// Processes orchard burns, decreasing asset supply.
Expand Down Expand Up @@ -125,21 +129,27 @@ fn calc_asset_supply_info<'a, I: IntoIterator<Item = &'a TranscriptItem>>(
fn create_transcript_data<'a, I: IntoIterator<Item = &'a OrchardZSABlock>>(
serialized_blocks: I,
) -> impl Iterator<Item = TranscriptItem> + use<'a, I> {
let workflow_blocks =
serialized_blocks
.into_iter()
.map(|OrchardZSABlock { bytes, is_valid }| {
(
Arc::new(
Block::zcash_deserialize(&bytes[..]).expect("block should deserialize"),
),
*is_valid,
)
});

std::iter::once((regtest_genesis_block(), true))
let workflow_blocks = serialized_blocks.into_iter().map(
|OrchardZSABlock {
description,
bytes,
is_valid,
}| {
(
description,
Arc::new(Block::zcash_deserialize(&bytes[..]).expect("block should deserialize")),
*is_valid,
)
},
);

std::iter::once((&None, regtest_genesis_block(), true))
.chain(workflow_blocks)
.map(|(block, is_valid)| {
.map(|(description, block, is_valid)| {
if let Some(description) = description {
assert_eq!(description, &build_block_description(&block))
}

(
Request::Commit(block.clone()),
if is_valid {
Expand Down
108 changes: 108 additions & 0 deletions zebra-consensus/src/orchard_zsa/tests/block_description.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use orchard::note::AssetBase;

use zebra_chain::{
block::Block,
orchard::{OrchardZSA, ShieldedData},
orchard_zsa::{BurnItem, IssueData},
transaction::Transaction,
};

use hex::encode as encode_hex;

fn format_asset(asset: &AssetBase) -> String {
encode_hex(asset.to_bytes()).chars().take(6).collect()
}

fn format_array(strings: impl IntoIterator<Item = String>) -> String {
let text = strings.into_iter().collect::<Vec<_>>().join(", ");

if text.is_empty() {
"[]".to_string()
} else {
format!("[ {text} ]")
}
}

fn format_transfer(n_actions: usize) -> Option<String> {
(n_actions > 0).then(|| format!("Transfer: {}", n_actions))
}

fn format_burn(burn_items: &[BurnItem]) -> Option<String> {
(!burn_items.is_empty()).then(|| {
let burn = burn_items
.iter()
.map(|b| format!("({}, {})", format_asset(&b.asset()), b.raw_amount()));
format!("Burn: {}", format_array(burn))
})
}

fn format_issue(issue_data: &IssueData) -> Option<String> {
let ik = issue_data.inner().ik();

let issue = issue_data.actions().map(|action| {
let asset = format_asset(&AssetBase::derive(ik, action.asset_desc()));
let is_finalized = action.is_finalized();
let notes = action
.notes()
.iter()
.map(|note| note.value().inner().to_string());
format!("({}, {}, {})", asset, is_finalized, format_array(notes))
});

Some(format!("Issue: {}", format_array(issue)))
}

fn format_tx_v6(
shielded_data: &Option<ShieldedData<OrchardZSA>>,
issue_data: &Option<IssueData>,
) -> String {
let transfer = shielded_data
.as_ref()
.and_then(|shielded_data| format_transfer(shielded_data.actions.len()));

let burn = shielded_data
.as_ref()
.and_then(|shielded_data| format_burn(shielded_data.burn.as_ref()));

let issue = issue_data
.as_ref()
.and_then(|issue_data| format_issue(issue_data));

format!(
"V6 {{ {} }}",
[transfer, burn, issue]
.into_iter()
.filter_map(|part| part)
.collect::<Vec<String>>()
.join(", ")
)
}

pub(super) fn build_block_description(block: &Block) -> String {
let height = block
.coinbase_height()
.expect("block has coinbase_height")
.next()
.expect("block has next coinbase_height")
.0;

let hash = &block.hash().to_string()[..6];

let transactions = format_array(block.transactions.iter().map(|tx| match tx.as_ref() {
Transaction::V1 { .. } => "V1".to_string(),
Transaction::V2 { .. } => "V2".to_string(),
Transaction::V3 { .. } => "V3".to_string(),
Transaction::V4 { .. } => "V4".to_string(),
Transaction::V5 { .. } => "V5".to_string(),
Transaction::V6 {
orchard_shielded_data,
orchard_zsa_issue_data,
..
} => format_tx_v6(orchard_shielded_data, orchard_zsa_issue_data),
}));

format!(
"Header: ({}, {}), Transactions: {}",
height, hash, transactions
)
}
7 changes: 7 additions & 0 deletions zebra-test/src/vectors/orchard_zsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use lazy_static::lazy_static;

/// Represents a serialized ZSA block and its validity status.
pub struct OrchardZSABlock {
/// Description of the cointent of the block
pub description: Option<&'static str>,
/// Serialized byte data of the block.
pub bytes: Vec<u8>,
/// Indicates whether the block is valid.
Expand All @@ -20,22 +22,27 @@ fn decode_bytes(hex: &str) -> Vec<u8> {
lazy_static! {
pub static ref ORCHARD_ZSA_WORKFLOW_BLOCKS: [Vec<OrchardZSABlock>; 1] = [vec![
OrchardZSABlock {
description: Some("Header: (2, 5fe240), Transactions: [ V4, V6 { Transfer: 2, Issue: [ (444bd8, false, [ 1000 ]) ] } ]"),
bytes: decode_bytes(include_str!("orchard-zsa-0-0.txt")),
is_valid: true
},
OrchardZSABlock {
description: Some("Header: (3, 4450db), Transactions: [ V4, V6 { Transfer: 2 } ]"),
bytes: decode_bytes(include_str!("orchard-zsa-0-1.txt")),
is_valid: true
},
OrchardZSABlock {
description: Some("Header: (4, a1d3c5), Transactions: [ V4, V6 { Transfer: 2, Burn: [ (444bd8, 7) ] }, V6 { Transfer: 2, Burn: [ (444bd8, 2) ] } ]"),
bytes: decode_bytes(include_str!("orchard-zsa-0-2.txt")),
is_valid: true
},
OrchardZSABlock {
description: Some("Header: (5, 854bf0), Transactions: [ V4, V6 { Transfer: 2, Issue: [ (444bd8, true, []) ] } ]"),
bytes: decode_bytes(include_str!("orchard-zsa-0-3.txt")),
is_valid: true
},
OrchardZSABlock {
description: Some("Header: (6, 84f6a1), Transactions: [ V4, V6 { Transfer: 2, Issue: [ (444bd8, false, [ 2000 ]) ] } ]"),
bytes: decode_bytes(include_str!("orchard-zsa-0-4.txt")),
is_valid: false
},
Expand Down

0 comments on commit 33ae89f

Please sign in to comment.