Skip to content

Commit

Permalink
Constrained the range of MASP test vectors generated for correctness.
Browse files Browse the repository at this point in the history
  • Loading branch information
murisi committed Jan 22, 2024
1 parent 413160d commit 9b8a9de
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 33 deletions.
55 changes: 47 additions & 8 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ pub mod testing {
use sha2::Digest;

use super::*;
use crate::core::types::address::MASP;
use crate::core::types::chain::ChainId;
use crate::core::types::eth_bridge_pool::testing::arb_pending_transfer;
use crate::core::types::key::testing::arb_common_pk;
Expand All @@ -814,7 +815,9 @@ pub mod testing {
use crate::core::types::transaction::{
DecryptedTx, Fee, TxType, WrapperTx,
};
use crate::masp::testing::arb_masp_transfer;
use crate::masp::testing::{
arb_deshielding_transfer, arb_shielded_transfer, arb_shielding_transfer,
};
use crate::proto::{Code, Commitment, Header, MaspBuilder, Section};

#[derive(Debug)]
Expand Down Expand Up @@ -992,26 +995,62 @@ pub mod testing {
TransparentAddress(hash.into())
}

// Maximum number of notes to include in a transaction
const MAX_ASSETS: usize = 10;

// Type of MASP transaction
#[derive(Debug, Clone)]
enum MaspTxType {
// Shielded transaction
Shielded,
// Shielding transaction
Shielding,
// Deshielding transaction
Deshielding,
}

prop_compose! {
// Generate an arbitrary transfer transaction
pub fn arb_masp_transfer_tx()(transfer in arb_transfer())(
mut header in arb_header(),
wrapper in arb_wrapper_tx(),
code_hash in arb_hash(),
(shielded_transfer, asset_types) in arb_masp_transfer(
encode_address(&transfer.source),
encode_address(&transfer.target),
),
(masp_tx_type, (shielded_transfer, asset_types)) in prop_oneof![
(Just(MaspTxType::Shielded), arb_shielded_transfer(0..MAX_ASSETS)),
(Just(MaspTxType::Shielding), arb_shielding_transfer(encode_address(&transfer.source), 1)),
(Just(MaspTxType::Deshielding), arb_deshielding_transfer(encode_address(&transfer.target), 1)),
],
mut transfer in Just(transfer),
) -> (Tx, TxData) {
header.tx_type = TxType::Wrapper(Box::new(wrapper));
let mut tx = Tx { header, sections: vec![] };
tx.add_data(transfer.clone());
tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned()));
match masp_tx_type {
MaspTxType::Shielded => {
transfer.source = MASP;
transfer.target = MASP;
transfer.amount = token::Amount::zero().into();
},
MaspTxType::Shielding => {
transfer.target = MASP;
// Set the transparent amount and token
let ((addr, denom, _epoch), value) = asset_types.iter().next().unwrap();
transfer.amount = DenominatedAmount::native(token::Amount::from_masp_denominated(*value, *denom));
transfer.token = addr.clone();
},
MaspTxType::Deshielding => {
transfer.source = MASP;
// Set the transparent amount and token
let ((addr, denom, _epoch), value) = asset_types.iter().next().unwrap();
transfer.amount = DenominatedAmount::native(token::Amount::from_masp_denominated(*value, *denom));
transfer.token = addr.clone();
},
}
let masp_tx_hash = tx.add_masp_tx_section(shielded_transfer.masp_tx).1;
transfer.shielded = Some(masp_tx_hash);
tx.add_data(transfer.clone());
tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned()));
tx.add_masp_builder(MaspBuilder {
asset_types,
asset_types: asset_types.into_keys().collect(),
// Store how the Info objects map to Descriptors/Outputs
metadata: shielded_transfer.metadata,
// Store the data that was used to construct the Transaction
Expand Down
96 changes: 74 additions & 22 deletions sdk/src/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2231,6 +2231,7 @@ pub mod testing {
Diversifier, Node, PaymentAddress, ProofGenerationKey, Rseed,
};
use masp_primitives::transaction::components::{I128Sum, GROTH_PROOF_SIZE};
use proptest::collection::SizeRange;
use proptest::prelude::*;
use proptest::test_runner::TestRng;
use proptest::{collection, option, prop_compose};
Expand Down Expand Up @@ -2606,8 +2607,6 @@ pub mod testing {
const MAX_MONEY: u64 = 100;
// Maximum number of partitions for a note
const MAX_SPLITS: usize = 10;
// Maximum number of notes to include in a transaction
const MAX_ASSETS: usize = 10;

prop_compose! {
// Arbitrarily partition the given vector of integers into sets and sum
Expand Down Expand Up @@ -2695,11 +2694,11 @@ pub mod testing {

prop_compose! {
// Generate an arbitrary shielded MASP transaction builder
pub fn arb_shielded_builder()(
pub fn arb_shielded_builder(asset_range: impl Into<SizeRange>)(
assets in collection::hash_map(
(arb_address(), arb_masp_denom(), option::of(arb_epoch())),
collection::vec(..MAX_MONEY, ..MAX_SPLITS),
..MAX_ASSETS,
asset_range,
),
)(
expiration_height in arb_height(BranchId::MASP, &TestNetwork),
Expand All @@ -2715,7 +2714,7 @@ pub mod testing {
assets in Just(assets),
) -> (
Builder::<TestNetwork, TestCsprng<TestRng>>,
HashSet<(Address, MaspDenom, Option<Epoch>)>,
HashMap<(Address, MaspDenom, Option<Epoch>), u64>,
) {
let mut builder = Builder::<TestNetwork, _>::new_with_rng(
NETWORK,
Expand All @@ -2738,17 +2737,20 @@ pub mod testing {
for (ovk, payment_addr, asset_type, value, memo) in output_descriptions.into_iter().flatten() {
builder.add_sapling_output(ovk, payment_addr, asset_type, value, memo).unwrap();
}
(builder, assets.into_keys().collect())
(builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect())
}
}

prop_compose! {
// Generate an arbitrary shielding MASP transaction builder
pub fn arb_shielding_builder(source: TransparentAddress)(
pub fn arb_shielding_builder(
source: TransparentAddress,
asset_range: impl Into<SizeRange>,
)(
assets in collection::hash_map(
(arb_address(), arb_masp_denom(), option::of(arb_epoch())),
collection::vec(..MAX_MONEY, ..MAX_SPLITS),
..MAX_ASSETS,
asset_range,
),
)(
expiration_height in arb_height(BranchId::MASP, &TestNetwork),
Expand All @@ -2764,7 +2766,7 @@ pub mod testing {
assets in Just(assets),
) -> (
Builder::<TestNetwork, TestCsprng<TestRng>>,
HashSet<(Address, MaspDenom, Option<Epoch>)>,
HashMap<(Address, MaspDenom, Option<Epoch>), u64>,
) {
let mut builder = Builder::<TestNetwork, _>::new_with_rng(
NETWORK,
Expand All @@ -2780,17 +2782,20 @@ pub mod testing {
for (ovk, payment_addr, asset_type, value, memo) in output_descriptions.into_iter().flatten() {
builder.add_sapling_output(ovk, payment_addr, asset_type, value, memo).unwrap();
}
(builder, assets.into_keys().collect())
(builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect())
}
}

prop_compose! {
// Generate an arbitrary deshielding MASP transaction builder
pub fn arb_deshielding_builder(target: TransparentAddress)(
pub fn arb_deshielding_builder(
target: TransparentAddress,
asset_range: impl Into<SizeRange>,
)(
assets in collection::hash_map(
(arb_address(), arb_masp_denom(), option::of(arb_epoch())),
collection::vec(..MAX_MONEY, ..MAX_SPLITS),
..MAX_ASSETS,
asset_range,
),
)(
expiration_height in arb_height(BranchId::MASP, &TestNetwork),
Expand All @@ -2806,7 +2811,7 @@ pub mod testing {
assets in Just(assets),
) -> (
Builder::<TestNetwork, TestCsprng<TestRng>>,
HashSet<(Address, MaspDenom, Option<Epoch>)>,
HashMap<(Address, MaspDenom, Option<Epoch>), u64>,
) {
let mut builder = Builder::<TestNetwork, _>::new_with_rng(
NETWORK,
Expand All @@ -2829,24 +2834,71 @@ pub mod testing {
for txout in txouts.into_iter().flatten() {
builder.add_transparent_output(&txout.address, txout.asset_type, txout.value).unwrap();
}
(builder, assets.into_keys().collect())
(builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect())
}
}

prop_compose! {
// Generate an arbitrary MASP shielded transfer
pub fn arb_shielded_transfer(
asset_range: impl Into<SizeRange>,
)(asset_range in Just(asset_range.into()))(
(builder, asset_types) in arb_shielded_builder(asset_range),
epoch in arb_epoch(),
rng in arb_rng().prop_map(TestCsprng),
) -> (ShieldedTransfer, HashMap<(Address, MaspDenom, Option<Epoch>), u64>) {
let (masp_tx, metadata) = builder.clone().build(
&MockTxProver(Mutex::new(rng)),
&FeeRule::non_standard(U64Sum::zero()),
).unwrap();
(ShieldedTransfer {
builder: builder.map_builder(WalletMap),
metadata,
masp_tx,
epoch,
}, asset_types)
}
}

prop_compose! {
// Generate an arbitrary MASP shielded transfer
pub fn arb_masp_transfer(
pub fn arb_shielding_transfer(
source: TransparentAddress,
asset_range: impl Into<SizeRange>,
)(asset_range in Just(asset_range.into()))(
(builder, asset_types) in arb_shielding_builder(
source,
asset_range,
),
epoch in arb_epoch(),
rng in arb_rng().prop_map(TestCsprng),
) -> (ShieldedTransfer, HashMap<(Address, MaspDenom, Option<Epoch>), u64>) {
let (masp_tx, metadata) = builder.clone().build(
&MockTxProver(Mutex::new(rng)),
&FeeRule::non_standard(U64Sum::zero()),
).unwrap();
(ShieldedTransfer {
builder: builder.map_builder(WalletMap),
metadata,
masp_tx,
epoch,
}, asset_types)
}
}

prop_compose! {
// Generate an arbitrary MASP shielded transfer
pub fn arb_deshielding_transfer(
target: TransparentAddress,
)(
(builder, asset_types) in prop_oneof![
arb_shielded_builder(),
arb_shielding_builder(source),
arb_deshielding_builder(target),
],
asset_range: impl Into<SizeRange>,
)(asset_range in Just(asset_range.into()))(
(builder, asset_types) in arb_deshielding_builder(
target,
asset_range,
),
epoch in arb_epoch(),
rng in arb_rng().prop_map(TestCsprng),
) -> (ShieldedTransfer, HashSet<(Address, MaspDenom, Option<Epoch>)>) {
) -> (ShieldedTransfer, HashMap<(Address, MaspDenom, Option<Epoch>), u64>) {
let (masp_tx, metadata) = builder.clone().build(
&MockTxProver(Mutex::new(rng)),
&FeeRule::non_standard(U64Sum::zero()),
Expand Down
10 changes: 7 additions & 3 deletions sdk/src/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,19 +729,23 @@ async fn make_ledger_amount_asset(
assets: &HashMap<AssetType, (Address, MaspDenom, Option<Epoch>)>,
prefix: &str,
) {
if let Some((token, _, _epoch)) = assets.get(token) {
if let Some((token, denom, _epoch)) = assets.get(token) {
// If the AssetType can be decoded, then at least display Addressees
if let Some(token) = tokens.get(token) {
output.push(format!(
"{}Amount : {} {}",
prefix,
token.to_uppercase(),
amount,
token::Amount::from_masp_denominated(amount, *denom),
));
} else {
output.extend(vec![
format!("{}Token : {}", prefix, token),
format!("{}Amount : {}", prefix, amount,),
format!(
"{}Amount : {}",
prefix,
token::Amount::from_masp_denominated(amount, *denom)
),
]);
}
} else {
Expand Down

0 comments on commit 9b8a9de

Please sign in to comment.