Quellcode durchsuchen

contract/money/tests: mint_pay_swap updated and fixed

aggstam vor 3 Jahren
Ursprung
Commit
389838f082
2 geänderte Dateien mit 229 neuen und 263 gelöschten Zeilen
  1. 228 260
      src/contract/money/tests/mint_pay_swap.rs
  2. 1 3
      src/contract/money/tests/verification_bench.rs

+ 228 - 260
src/contract/money/tests/mint_pay_swap.rs

@@ -31,21 +31,19 @@ use darkfi::{tx::Transaction, Result};
 use darkfi_sdk::{
     crypto::{
         merkle_prelude::*, pallas, pasta_prelude::*, poseidon_hash, Coin, MerkleNode, Nullifier,
-        ValueBlind,
+        ValueBlind, MONEY_CONTRACT_ID,
     },
     ContractCall,
 };
-use darkfi_serial::Encodable;
+use darkfi_serial::{deserialize, Encodable};
 use log::info;
 use rand::rngs::OsRng;
 
 use darkfi_money_contract::{
-    client::{
-        mint_v1::MintCallBuilder, swap_v1::SwapCallBuilder, transfer_v1::TransferCallBuilder,
-        MoneyNote, OwnCoin,
-    },
+    client::{swap_v1::SwapCallBuilder, transfer_v1::TransferCallBuilder, MoneyNote, OwnCoin},
     model::MoneyTransferParamsV1 as MoneyTransferParams,
-    MoneyFunction::{MintV1 as MoneyMint, OtcSwapV1 as MoneyOtcSwap, TransferV1 as MoneyTransfer},
+    MoneyFunction::{OtcSwapV1 as MoneyOtcSwap, TransferV1 as MoneyTransfer},
+    MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
 };
 
 mod harness;
@@ -53,7 +51,7 @@ use harness::{init_logger, MoneyTestHarness};
 
 #[async_std::test]
 async fn money_contract_transfer() -> Result<()> {
-    init_logger()?;
+    init_logger();
 
     // Some numbers we want to assert
     const ALICE_INITIAL: u64 = 100;
@@ -66,7 +64,11 @@ async fn money_contract_transfer() -> Result<()> {
     // Bob = 20 BOB + 50 ALICE
     const BOB_FIRST_SEND: u64 = BOB_INITIAL - 20;
 
+    // Initialize harness
     let mut th = MoneyTestHarness::new().await?;
+    let (mint_pk, mint_zkbin) = th.proving_keys.get(&MONEY_CONTRACT_ZKAS_MINT_NS_V1).unwrap();
+    let (burn_pk, burn_zkbin) = th.proving_keys.get(&MONEY_CONTRACT_ZKAS_BURN_NS_V1).unwrap();
+    let contract_id = *MONEY_CONTRACT_ID;
 
     // We're just going to be using a zero spend-hook and user-data
     let rcpt_spend_hook = pallas::Base::zero();
@@ -81,120 +83,80 @@ async fn money_contract_transfer() -> Result<()> {
     let mut alice_owncoins = vec![];
     let mut bob_owncoins = vec![];
 
-    info!(target: "money", "[Alice] ==================================================");
-    info!(target: "money", "[Alice] Building Money::Mint params for Alice's token mint");
-    info!(target: "money", "[Alice] ==================================================");
-    let alice_call_debris = MintCallBuilder {
-        mint_authority: th.alice_kp,
-        recipient: th.alice_kp.public,
-        amount: ALICE_INITIAL,
-        spend_hook: rcpt_spend_hook,
-        user_data: rcpt_user_data,
-        token_mint_zkbin: th.token_mint_zkbin.clone(),
-        token_mint_pk: th.token_mint_pk.clone(),
-    }
-    .build()?;
-    let (alice_params, alice_proofs) = (alice_call_debris.params, alice_call_debris.proofs);
-
-    info!(target: "money", "[Bob] ================================================");
-    info!(target: "money", "[Bob] Building Money::Mint params for Bob's token mint");
-    info!(target: "money", "[Bob] ================================================");
-    let bob_call_debris = MintCallBuilder {
-        mint_authority: th.bob_kp,
-        recipient: th.bob_kp.public,
-        amount: BOB_INITIAL,
-        spend_hook: rcpt_spend_hook,
-        user_data: rcpt_user_data,
-        token_mint_zkbin: th.token_mint_zkbin.clone(),
-        token_mint_pk: th.token_mint_pk.clone(),
-    }
-    .build()?;
-    let (bob_params, bob_proofs) = (bob_call_debris.params, bob_call_debris.proofs);
-
-    info!(target: "money", "[Alice] ========================================");
-    info!(target: "money", "[Alice] Building token mint tx with Alice params");
-    info!(target: "money", "[Alice] ========================================");
-    let mut data = vec![MoneyMint as u8];
-    alice_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
-    let proofs = vec![alice_proofs];
-    let mut alice_mint_tx = Transaction { calls, proofs, signatures: vec![] };
-    let sigs = alice_mint_tx.create_sigs(&mut OsRng, &[th.alice_kp.secret])?;
-    alice_mint_tx.signatures = vec![sigs];
-
-    info!(target: "money", "[Bob] ======================================");
-    info!(target: "money", "[Bob] Building token mint tx with Bob params");
-    info!(target: "money", "[Bob] ======================================");
-    let mut data = vec![MoneyMint as u8];
-    bob_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
-    let proofs = vec![bob_proofs];
-    let mut bob_mint_tx = Transaction { calls, proofs, signatures: vec![] };
-    let sigs = bob_mint_tx.create_sigs(&mut OsRng, &[th.bob_kp.secret])?;
-    bob_mint_tx.signatures = vec![sigs];
+    info!(target: "money", "[Alice] ================================");
+    info!(target: "money", "[Alice] Building token mint tx for Alice");
+    info!(target: "money", "[Alice] ================================");
+    let (alice_mint_tx, alice_params) =
+        th.mint_token(th.alice.keypair, ALICE_INITIAL, th.alice.keypair.public)?;
+
+    info!(target: "money", "[Bob] ==============================");
+    info!(target: "money", "[Bob] Building token mint tx for Bob");
+    info!(target: "money", "[Bob] ==============================");
+    let (bob_mint_tx, bob_params) =
+        th.mint_token(th.bob.keypair, BOB_INITIAL, th.bob.keypair.public)?;
 
     info!(target: "money", "[Faucet] =============================");
     info!(target: "money", "[Faucet] Executing Alice token mint tx");
     info!(target: "money", "[Faucet] =============================");
-    th.faucet_state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
 
     info!(target: "money", "[Faucet] ===========================");
     info!(target: "money", "[Faucet] Executing Bob token mint tx");
     info!(target: "money", "[Faucet] ===========================");
-    th.faucet_state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
 
     info!(target: "money", "[Alice] =============================");
     info!(target: "money", "[Alice] Executing Alice token mint tx");
     info!(target: "money", "[Alice] =============================");
-    th.alice_state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
     // Alice has to witness this coin because it's hers.
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
 
     info!(target: "money", "[Alice] ===========================");
     info!(target: "money", "[Alice] Executing Bob token mint tx");
     info!(target: "money", "[Alice] ===========================");
-    th.alice_state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
 
     info!(target: "money", "[Bob] =============================");
     info!(target: "money", "[Bob] Executing Alice token mint tx");
     info!(target: "money", "[Bob] =============================");
-    th.bob_state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
+    th.bob.state.read().await.verify_transactions(&[alice_mint_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(alice_params.output.coin.inner()));
 
     info!(target: "money", "[Bob] ===========================");
     info!(target: "money", "[Bob] Executing Bob token mint tx");
     info!(target: "money", "[Bob] ===========================");
-    th.bob_state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
+    th.bob.state.read().await.verify_transactions(&[bob_mint_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(bob_params.output.coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Alice builds an `OwnCoin` from her airdrop
-    let note: MoneyNote = alice_params.output.note.decrypt(&th.alice_kp.secret)?;
+    let note: MoneyNote = alice_params.output.note.decrypt(&th.alice.keypair.secret)?;
     let alice_token_id = note.token_id;
     let alice_oc = OwnCoin {
         coin: Coin::from(alice_params.output.coin),
         note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.alice.keypair.secret.inner(), note.serial])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
 
     // Bob too
-    let note: MoneyNote = bob_params.output.note.decrypt(&th.bob_kp.secret)?;
+    let note: MoneyNote = bob_params.output.note.decrypt(&th.bob.keypair.secret)?;
     let bob_token_id = note.token_id;
     let bob_oc = OwnCoin {
         coin: Coin::from(bob_params.output.coin),
         note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);
@@ -204,8 +166,8 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Alice] Building Money::Transfer params for a payment to Bob");
     info!(target: "money", "[Alice] ====================================================");
     let alice2bob_call_debris = TransferCallBuilder {
-        keypair: th.alice_kp,
-        recipient: th.bob_kp.public,
+        keypair: th.alice.keypair,
+        recipient: th.bob.keypair.public,
         value: ALICE_FIRST_SEND,
         token_id: alice_token_id,
         rcpt_spend_hook,
@@ -215,11 +177,11 @@ async fn money_contract_transfer() -> Result<()> {
         change_user_data,
         change_user_data_blind,
         coins: alice_owncoins.clone(),
-        tree: th.alice_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.alice.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
         clear_input: false,
     }
     .build()?;
@@ -241,7 +203,7 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Alice] ==========================");
     let mut data = vec![MoneyTransfer as u8];
     alice2bob_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
+    let calls = vec![ContractCall { contract_id, data }];
     let proofs = vec![alice2bob_proofs];
     let mut alice2bob_tx = Transaction { calls, proofs, signatures: vec![] };
     let sigs = alice2bob_tx.create_sigs(&mut OsRng, &alice2bob_secret_keys)?;
@@ -250,47 +212,47 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Faucet] ==============================");
     info!(target: "money", "[Faucet] Executing Alice2Bob payment tx");
     info!(target: "money", "[Faucet] ==============================");
-    th.faucet_state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
-    th.faucet_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
+    th.faucet.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Alice] ==============================");
     info!(target: "money", "[Alice] Executing Alice2Bob payment tx");
     info!(target: "money", "[Alice] ==============================");
-    th.alice_state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
-    th.alice_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
+    th.alice.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Bob] ==============================");
     info!(target: "money", "[Bob] Executing Alice2Bob payment tx");
     info!(target: "money", "[Bob] ==============================");
-    th.bob_state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
-    th.bob_merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
+    th.bob.state.read().await.verify_transactions(&[alice2bob_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[0].coin.inner()));
+    th.bob.merkle_tree.append(&MerkleNode::from(alice2bob_params.outputs[1].coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Alice should now have one OwnCoin with the change from the above transaction.
-    let note: MoneyNote = alice2bob_params.outputs[0].note.decrypt(&th.alice_kp.secret)?;
+    let note: MoneyNote = alice2bob_params.outputs[0].note.decrypt(&th.alice.keypair.secret)?;
     let alice_oc = OwnCoin {
         coin: Coin::from(alice2bob_params.outputs[0].coin),
         note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.alice.keypair.secret.inner(), note.serial])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
 
     // Bob should have his old one, and this new one.
-    let note: MoneyNote = alice2bob_params.outputs[1].note.decrypt(&th.bob_kp.secret)?;
+    let note: MoneyNote = alice2bob_params.outputs[1].note.decrypt(&th.bob.keypair.secret)?;
     let bob_oc = OwnCoin {
         coin: Coin::from(alice2bob_params.outputs[1].coin),
         note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);
@@ -305,8 +267,8 @@ async fn money_contract_transfer() -> Result<()> {
     let mut bob_owncoins_tmp = bob_owncoins.clone();
     bob_owncoins_tmp.retain(|x| x.note.token_id == bob_token_id);
     let bob2alice_call_debris = TransferCallBuilder {
-        keypair: th.bob_kp,
-        recipient: th.alice_kp.public,
+        keypair: th.bob.keypair,
+        recipient: th.alice.keypair.public,
         value: BOB_FIRST_SEND,
         token_id: bob_token_id,
         rcpt_spend_hook,
@@ -315,12 +277,12 @@ async fn money_contract_transfer() -> Result<()> {
         change_spend_hook,
         change_user_data,
         change_user_data_blind,
-        coins: bob_owncoins.clone(),
-        tree: th.bob_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        coins: bob_owncoins_tmp.clone(),
+        tree: th.bob.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
         clear_input: false,
     }
     .build()?;
@@ -342,7 +304,7 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Bob] ============================");
     let mut data = vec![MoneyTransfer as u8];
     bob2alice_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
+    let calls = vec![ContractCall { contract_id, data }];
     let proofs = vec![bob2alice_proofs];
     let mut bob2alice_tx = Transaction { calls, proofs, signatures: vec![] };
     let sigs = bob2alice_tx.create_sigs(&mut OsRng, &bob2alice_secret_keys)?;
@@ -351,52 +313,52 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Faucet] ==============================");
     info!(target: "money", "[Faucet] Executing Bob2Alice payment tx");
     info!(target: "money", "[Faucet] ==============================");
-    th.faucet_state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
-    th.faucet_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
+    th.faucet.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Alice] ==============================");
     info!(target: "money", "[Alice] Executing Bob2Alice payment tx");
     info!(target: "money", "[Alice] ==============================");
-    th.alice_state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
-    th.alice_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
+    th.alice.state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
+    th.alice.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
 
     info!(target: "money", "[Bob] ==================+===========");
     info!(target: "money", "[Bob] Executing Bob2Alice payment tx");
     info!(target: "money", "[Bob] ==================+===========");
-    th.bob_state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
-    th.bob_merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
+    th.bob.state.read().await.verify_transactions(&[bob2alice_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[0].coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
+    th.bob.merkle_tree.append(&MerkleNode::from(bob2alice_params.outputs[1].coin.inner()));
 
     // Alice should now have two OwnCoins
-    let note: MoneyNote = bob2alice_params.outputs[1].note.decrypt(&th.alice_kp.secret)?;
+    let note: MoneyNote = bob2alice_params.outputs[1].note.decrypt(&th.alice.keypair.secret)?;
     let alice_oc = OwnCoin {
         coin: Coin::from(bob2alice_params.outputs[1].coin),
         note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.alice.keypair.secret.inner(), note.serial])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
 
     // Bob should have two with the change from the above tx
-    let note: MoneyNote = bob2alice_params.outputs[0].note.decrypt(&th.bob_kp.secret)?;
+    let note: MoneyNote = bob2alice_params.outputs[0].note.decrypt(&th.bob.keypair.secret)?;
     let bob_oc = OwnCoin {
         coin: Coin::from(bob2alice_params.outputs[0].coin),
         note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);
 
     assert!(alice_owncoins.len() == 2);
     assert!(bob_owncoins.len() == 2);
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     assert!(alice_owncoins[0].note.value == ALICE_INITIAL - ALICE_FIRST_SEND);
     assert!(alice_owncoins[0].note.token_id == alice_token_id);
@@ -414,13 +376,11 @@ async fn money_contract_transfer() -> Result<()> {
     // Generating  swap blinds
     let value_send_blind = ValueBlind::random(&mut OsRng);
     let value_recv_blind = ValueBlind::random(&mut OsRng);
-    let value_blinds = [value_send_blind, value_recv_blind];
     let token_send_blind = ValueBlind::random(&mut OsRng);
     let token_recv_blind = ValueBlind::random(&mut OsRng);
-    let token_blinds = [token_send_blind, token_recv_blind];
 
     let alice_swap_call_debris = SwapCallBuilder {
-        pubkey: th.alice_kp.public,
+        pubkey: th.alice.keypair.public,
         value_send: BOB_FIRST_SEND,
         token_id_send: bob_token_id,
         value_recv: ALICE_FIRST_SEND,
@@ -428,14 +388,14 @@ async fn money_contract_transfer() -> Result<()> {
         user_data_blind_send: rcpt_user_data_blind,
         spend_hook_recv: rcpt_spend_hook,
         user_data_recv: rcpt_user_data,
-        value_blinds,
-        token_blinds,
+        value_blinds: [value_send_blind, value_recv_blind],
+        token_blinds: [token_send_blind, token_recv_blind],
         coin: alice_owncoins[1].clone(),
-        tree: th.alice_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.alice.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
     }
     .build()?;
     let (alice_swap_params, alice_swap_proofs) =
@@ -449,7 +409,7 @@ async fn money_contract_transfer() -> Result<()> {
     // Alice sends Bob necessary data and he builds his half.
     info!(target: "money", "[Bob] Building OtcSwap half");
     let bob_swap_call_debris = SwapCallBuilder {
-        pubkey: th.bob_kp.public,
+        pubkey: th.bob.keypair.public,
         value_send: ALICE_FIRST_SEND,
         token_id_send: alice_token_id,
         value_recv: BOB_FIRST_SEND,
@@ -457,14 +417,14 @@ async fn money_contract_transfer() -> Result<()> {
         user_data_blind_send: rcpt_user_data_blind,
         spend_hook_recv: rcpt_spend_hook,
         user_data_recv: rcpt_user_data,
-        value_blinds,
-        token_blinds,
+        value_blinds: [value_recv_blind, value_send_blind],
+        token_blinds: [token_recv_blind, token_send_blind],
         coin: bob_owncoins[0].clone(),
-        tree: th.bob_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.bob.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
     }
     .build()?;
     let (bob_swap_params, bob_swap_proofs) =
@@ -493,50 +453,57 @@ async fn money_contract_transfer() -> Result<()> {
     let mut data = vec![MoneyOtcSwap as u8];
     swap_full_params.encode(&mut data)?;
     let mut alicebob_swap_tx = Transaction {
-        calls: vec![ContractCall { contract_id: th.money_contract_id, data }],
+        calls: vec![ContractCall { contract_id, data }],
         proofs: vec![swap_full_proofs],
         signatures: vec![],
     };
-    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[th.bob_kp.secret])?;
+    let bob_note: MoneyNote = swap_full_params.outputs[1].note.decrypt(&th.bob.keypair.secret)?;
+    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[deserialize(&bob_note.memo)?])?;
     alicebob_swap_tx.signatures = vec![sigs];
 
     // Alice gets the partially signed transaction and adds her signature
-    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[th.alice_kp.secret])?;
+    let alice_note: MoneyNote =
+        swap_full_params.outputs[0].note.decrypt(&th.alice.keypair.secret)?;
+    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[deserialize(&alice_note.memo)?])?;
     alicebob_swap_tx.signatures[0].insert(0, sigs[0]);
 
     info!(target: "money", "[Faucet] ==========================");
     info!(target: "money", "[Faucet] Executing AliceBob swap tx");
     info!(target: "money", "[Faucet] ==========================");
-    th.faucet_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    th.faucet_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    th.faucet.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Alice] ==========================");
     info!(target: "money", "[Alice] Executing AliceBob swap tx");
     info!(target: "money", "[Alice] ==========================");
-    th.alice_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
-    th.alice_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
+    th.alice.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Bob] ==========================");
     info!(target: "money", "[Bob] Executing AliceBob swap tx");
     info!(target: "money", "[Bob] ==========================");
-    th.bob_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    th.bob_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
+    th.bob.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    th.bob.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Alice should now have two OwnCoins with the same token ID (ALICE)
-    let note: MoneyNote = swap_full_params.outputs[0].note.decrypt(&th.alice_kp.secret)?;
+    let alice_note: MoneyNote =
+        swap_full_params.outputs[0].note.decrypt(&th.alice.keypair.secret)?;
     let alice_oc = OwnCoin {
         coin: Coin::from(swap_full_params.outputs[0].coin),
-        note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        note: alice_note.clone(),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([
+            th.alice.keypair.secret.inner(),
+            alice_note.serial,
+        ])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
@@ -546,12 +513,11 @@ async fn money_contract_transfer() -> Result<()> {
     assert!(alice_owncoins[1].note.token_id == alice_token_id);
 
     // Same for Bob with BOB tokens
-    let note: MoneyNote = swap_full_params.outputs[1].note.decrypt(&th.bob_kp.secret)?;
     let bob_oc = OwnCoin {
         coin: Coin::from(swap_full_params.outputs[1].coin),
-        note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        note: bob_note.clone(),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), bob_note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);
@@ -565,8 +531,8 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Alice] Building Money::Transfer params for a payment to Alice");
     info!(target: "money", "[Alice] =======================================================");
     let alice2alice_call_debris = TransferCallBuilder {
-        keypair: th.alice_kp,
-        recipient: th.alice_kp.public,
+        keypair: th.alice.keypair,
+        recipient: th.alice.keypair.public,
         value: ALICE_INITIAL,
         token_id: alice_token_id,
         rcpt_spend_hook,
@@ -576,11 +542,11 @@ async fn money_contract_transfer() -> Result<()> {
         change_user_data,
         change_user_data_blind,
         coins: alice_owncoins.clone(),
-        tree: th.alice_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.alice.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
         clear_input: false,
     }
     .build()?;
@@ -603,7 +569,7 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Alice] ============================");
     let mut data = vec![MoneyTransfer as u8];
     alice2alice_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
+    let calls = vec![ContractCall { contract_id, data }];
     let proofs = vec![alice2alice_proofs];
     let mut alice2alice_tx = Transaction { calls, proofs, signatures: vec![] };
     let sigs = alice2alice_tx.create_sigs(&mut OsRng, &alice2alice_secret_keys)?;
@@ -612,32 +578,32 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Faucet] ================================");
     info!(target: "money", "[Faucet] Executing Alice2Alice payment tx");
     info!(target: "money", "[Faucet] ================================");
-    th.faucet_state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
 
     info!(target: "money", "[Alice] ================================");
     info!(target: "money", "[Alice] Executing Alice2Alice payment tx");
     info!(target: "money", "[Alice] ================================");
-    th.alice_state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
+    th.alice.state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
 
     info!(target: "money", "[Bob] ================================");
     info!(target: "money", "[Bob] Executing Alice2Alice payment tx");
     info!(target: "money", "[Bob] ================================");
-    th.bob_state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
+    th.bob.state.read().await.verify_transactions(&[alice2alice_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(alice2alice_params.outputs[0].coin.inner()));
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Alice should now have a single OwnCoin with her initial airdrop
-    let note: MoneyNote = alice2alice_params.outputs[0].note.decrypt(&th.alice_kp.secret)?;
+    let note: MoneyNote = alice2alice_params.outputs[0].note.decrypt(&th.alice.keypair.secret)?;
     let alice_oc = OwnCoin {
         coin: Coin::from(alice2alice_params.outputs[0].coin),
         note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.alice.keypair.secret.inner(), note.serial])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
@@ -651,8 +617,8 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Bob] Building Money::Transfer params for a payment to Bob");
     info!(target: "money", "[Bob] ====================================================");
     let bob2bob_call_debris = TransferCallBuilder {
-        keypair: th.bob_kp,
-        recipient: th.bob_kp.public,
+        keypair: th.bob.keypair,
+        recipient: th.bob.keypair.public,
         value: BOB_INITIAL,
         token_id: bob_token_id,
         rcpt_spend_hook,
@@ -662,11 +628,11 @@ async fn money_contract_transfer() -> Result<()> {
         change_user_data,
         change_user_data_blind,
         coins: bob_owncoins.clone(),
-        tree: th.bob_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.bob.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
         clear_input: false,
     }
     .build()?;
@@ -689,7 +655,7 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Bob] ==========================");
     let mut data = vec![MoneyTransfer as u8];
     bob2bob_params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.money_contract_id, data }];
+    let calls = vec![ContractCall { contract_id, data }];
     let proofs = vec![bob2bob_proofs];
     let mut bob2bob_tx = Transaction { calls, proofs, signatures: vec![] };
     let sigs = bob2bob_tx.create_sigs(&mut OsRng, &bob2bob_secret_keys)?;
@@ -698,32 +664,32 @@ async fn money_contract_transfer() -> Result<()> {
     info!(target: "money", "[Faucet] ============================");
     info!(target: "money", "[Faucet] Executing Bob2Bob payment tx");
     info!(target: "money", "[Faucet] ============================");
-    th.faucet_state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
 
     info!(target: "money", "[Alice] ============================");
     info!(target: "money", "[Alice] Executing Bob2Bob payment tx");
     info!(target: "money", "[Alice] ============================");
-    th.alice_state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
 
     info!(target: "money", "[Bob] ============================");
     info!(target: "money", "[Bob] Executing Bob2Bob payment tx");
     info!(target: "money", "[Bob] ============================");
-    th.bob_state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
+    th.bob.state.read().await.verify_transactions(&[bob2bob_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(bob2bob_params.outputs[0].coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Bob should now have a single OwnCoin with her initial airdrop
-    let note: MoneyNote = bob2bob_params.outputs[0].note.decrypt(&th.bob_kp.secret)?;
+    let note: MoneyNote = bob2bob_params.outputs[0].note.decrypt(&th.bob.keypair.secret)?;
     let bob_oc = OwnCoin {
         coin: Coin::from(bob2bob_params.outputs[0].coin),
         note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);
@@ -737,13 +703,11 @@ async fn money_contract_transfer() -> Result<()> {
     // Generating  swap blinds
     let value_send_blind = ValueBlind::random(&mut OsRng);
     let value_recv_blind = ValueBlind::random(&mut OsRng);
-    let value_blinds = [value_send_blind, value_recv_blind];
     let token_send_blind = ValueBlind::random(&mut OsRng);
     let token_recv_blind = ValueBlind::random(&mut OsRng);
-    let token_blinds = [token_send_blind, token_recv_blind];
 
     let alice_swap_call_debris = SwapCallBuilder {
-        pubkey: th.alice_kp.public,
+        pubkey: th.alice.keypair.public,
         value_send: ALICE_INITIAL,
         token_id_send: alice_token_id,
         value_recv: BOB_INITIAL,
@@ -751,14 +715,14 @@ async fn money_contract_transfer() -> Result<()> {
         user_data_blind_send: rcpt_user_data_blind,
         spend_hook_recv: rcpt_spend_hook,
         user_data_recv: rcpt_user_data,
-        value_blinds,
-        token_blinds,
+        value_blinds: [value_send_blind, value_recv_blind],
+        token_blinds: [token_send_blind, token_recv_blind],
         coin: alice_owncoins[0].clone(),
-        tree: th.alice_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.alice.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
     }
     .build()?;
     let (alice_swap_params, alice_swap_proofs) =
@@ -771,7 +735,7 @@ async fn money_contract_transfer() -> Result<()> {
 
     info!(target: "money", "[Bob] Building OtcSwap half");
     let bob_swap_call_debris = SwapCallBuilder {
-        pubkey: th.bob_kp.public,
+        pubkey: th.bob.keypair.public,
         value_send: BOB_INITIAL,
         token_id_send: bob_token_id,
         value_recv: ALICE_INITIAL,
@@ -779,14 +743,14 @@ async fn money_contract_transfer() -> Result<()> {
         user_data_blind_send: rcpt_user_data_blind,
         spend_hook_recv: rcpt_spend_hook,
         user_data_recv: rcpt_user_data,
-        value_blinds,
-        token_blinds,
+        value_blinds: [value_recv_blind, value_send_blind],
+        token_blinds: [token_recv_blind, token_send_blind],
         coin: bob_owncoins[0].clone(),
-        tree: th.bob_merkle_tree.clone(),
-        mint_zkbin: th.mint_zkbin.clone(),
-        mint_pk: th.mint_pk.clone(),
-        burn_zkbin: th.burn_zkbin.clone(),
-        burn_pk: th.burn_pk.clone(),
+        tree: th.bob.merkle_tree.clone(),
+        mint_zkbin: mint_zkbin.clone(),
+        mint_pk: mint_pk.clone(),
+        burn_zkbin: burn_zkbin.clone(),
+        burn_pk: burn_pk.clone(),
     }
     .build()?;
     let (bob_swap_params, bob_swap_proofs) =
@@ -814,50 +778,55 @@ async fn money_contract_transfer() -> Result<()> {
     let mut data = vec![MoneyOtcSwap as u8];
     swap_full_params.encode(&mut data)?;
     let mut alicebob_swap_tx = Transaction {
-        calls: vec![ContractCall { contract_id: th.money_contract_id, data }],
+        calls: vec![ContractCall { contract_id, data }],
         proofs: vec![swap_full_proofs],
         signatures: vec![],
     };
-    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[th.bob_kp.secret])?;
+    let bob_note: MoneyNote = swap_full_params.outputs[1].note.decrypt(&th.bob.keypair.secret)?;
+    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[deserialize(&bob_note.memo)?])?;
     alicebob_swap_tx.signatures = vec![sigs];
 
     // Alice gets the partially signed transaction and adds her signature
-    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[th.alice_kp.secret])?;
+    let alice_note: MoneyNote =
+        swap_full_params.outputs[0].note.decrypt(&th.alice.keypair.secret)?;
+    let sigs = alicebob_swap_tx.create_sigs(&mut OsRng, &[deserialize(&alice_note.memo)?])?;
     alicebob_swap_tx.signatures[0].insert(0, sigs[0]);
 
     info!(target: "money", "[Faucet] ==========================");
     info!(target: "money", "[Faucet] Executing AliceBob swap tx");
     info!(target: "money", "[Faucet] ==========================");
-    th.faucet_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.faucet_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    th.faucet_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    th.faucet.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.faucet.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    th.faucet.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Alice] ==========================");
     info!(target: "money", "[Alice] Executing AliceBob swap tx");
     info!(target: "money", "[Alice] ==========================");
-    th.alice_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.alice_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    let alice_leaf_pos = th.alice_merkle_tree.witness().unwrap();
-    th.alice_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    th.alice.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.alice.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    let alice_leaf_pos = th.alice.merkle_tree.witness().unwrap();
+    th.alice.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
 
     info!(target: "money", "[Bob] ==========================");
     info!(target: "money", "[Bob] Executing AliceBob swap tx");
     info!(target: "money", "[Bob] ==========================");
-    th.bob_state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
-    th.bob_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
-    th.bob_merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
-    let bob_leaf_pos = th.bob_merkle_tree.witness().unwrap();
+    th.bob.state.read().await.verify_transactions(&[alicebob_swap_tx.clone()], true).await?;
+    th.bob.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[0].coin.inner()));
+    th.bob.merkle_tree.append(&MerkleNode::from(swap_full_params.outputs[1].coin.inner()));
+    let bob_leaf_pos = th.bob.merkle_tree.witness().unwrap();
 
-    assert!(th.alice_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
-    assert!(th.faucet_merkle_tree.root(0).unwrap() == th.bob_merkle_tree.root(0).unwrap());
+    assert!(th.alice.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
+    assert!(th.faucet.merkle_tree.root(0).unwrap() == th.bob.merkle_tree.root(0).unwrap());
 
     // Alice should now have Bob's BOB tokens
-    let note: MoneyNote = swap_full_params.outputs[0].note.decrypt(&th.alice_kp.secret)?;
     let alice_oc = OwnCoin {
         coin: Coin::from(swap_full_params.outputs[0].coin),
-        note: note.clone(),
-        secret: th.alice_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.alice_kp.secret.inner(), note.serial])),
+        note: alice_note.clone(),
+        secret: th.alice.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([
+            th.alice.keypair.secret.inner(),
+            alice_note.serial,
+        ])),
         leaf_position: alice_leaf_pos,
     };
     alice_owncoins.push(alice_oc);
@@ -867,12 +836,11 @@ async fn money_contract_transfer() -> Result<()> {
     assert!(alice_owncoins[0].note.token_id == bob_token_id);
 
     // And Bob should have Alice's ALICE tokens
-    let note: MoneyNote = swap_full_params.outputs[1].note.decrypt(&th.bob_kp.secret)?;
     let bob_oc = OwnCoin {
         coin: Coin::from(swap_full_params.outputs[1].coin),
-        note: note.clone(),
-        secret: th.bob_kp.secret, // <-- What should this be?
-        nullifier: Nullifier::from(poseidon_hash([th.bob_kp.secret.inner(), note.serial])),
+        note: bob_note.clone(),
+        secret: th.bob.keypair.secret, // <-- What should this be?
+        nullifier: Nullifier::from(poseidon_hash([th.bob.keypair.secret.inner(), bob_note.serial])),
         leaf_position: bob_leaf_pos,
     };
     bob_owncoins.push(bob_oc);

+ 1 - 3
src/contract/money/tests/verification_bench.rs

@@ -213,11 +213,9 @@ async fn alice2alice_random_amounts_multiplecoins() -> Result<()> {
     let mut minted_amounts = vec![];
     let mut owncoins = vec![];
     for i in 0..10 {
-        let token_id = TokenId::from(pallas::Base::random(&mut OsRng));
         let amount = rand::thread_rng().gen_range(1..1000);
-
         info!(target: "money", "[Faucet] ===================================================");
-        info!(target: "money", "[Faucet] Building Money::Mint params for Alice's mint for token {}: ID {} - amount {}", i, token_id, amount);
+        info!(target: "money", "[Faucet] Building Money::Mint params for Alice's mint for token {} and amount {}", i, amount);
         info!(target: "money", "[Faucet] ===================================================");
         let (mint_tx, mint_params) =
             th.mint_token(th.alice.keypair, amount, th.alice.keypair.public)?;