Skip to content

Commit

Permalink
mock-consensus: ⭐ use transaction plan in tests (#3866)
Browse files Browse the repository at this point in the history
  • Loading branch information
cratelyn authored Feb 26, 2024
1 parent 87a67b8 commit ad7d109
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 52 deletions.
86 changes: 36 additions & 50 deletions crates/core/app/tests/mock_consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ use {
cnidarium::TempStorage,
penumbra_keys::test_keys,
penumbra_mock_client::MockClient,
penumbra_proto::DomainType,
penumbra_sct::component::clock::EpochRead,
penumbra_shielded_pool::SpendPlan,
penumbra_transaction::TransactionPlan,
std::ops::Deref,
tap::Tap,
tracing::{error_span, Instrument},
};

Expand Down Expand Up @@ -78,71 +83,52 @@ async fn mock_consensus_can_send_a_spend_action() -> anyhow::Result<()> {
let mut rng = <rand_chacha::ChaChaRng as rand_core::SeedableRng>::seed_from_u64(0xBEEF);

// Sync the mock client, using the test account's full viewing key, to the latest snapshot.
let MockClient { notes, sct, .. } = MockClient::new(test_keys::FULL_VIEWING_KEY.clone())
let (viewing_key, spend_key) = (&test_keys::FULL_VIEWING_KEY, &test_keys::SPEND_KEY);
let client = MockClient::new(viewing_key.deref().clone())
.with_sync_to_storage(&storage)
.await?;

// Take one of the test account's notes...
let note = notes
.values()
.cloned()
let (commitment, note) = client
.notes
.iter()
.next()
.ok_or_else(|| anyhow!("mock client had no note"))?;
let asset_id = note.asset_id();
let proof = sct
.witness(note.commit())
.ok_or_else(|| anyhow!("index is not witnessed"))?;

// ...and use it to craft a `Spend`.
let (spend, spend_key) = {
use {decaf377_rdsa::SigningKey, penumbra_shielded_pool::SpendPlan};
let spend_plan = SpendPlan::new(&mut rng, note, proof.position());
let auth_sig = test_keys::SPEND_KEY
.spend_auth_key()
.randomize(&spend_plan.randomizer)
.sign(&mut rng, [0u8; 64].as_ref());
let spend = spend_plan.spend(&test_keys::FULL_VIEWING_KEY, auth_sig, proof, sct.root());
let key = SigningKey::from(spend_plan.value_blinding);
(spend, key)
};
.ok_or_else(|| anyhow!("mock client had no note"))?
.tap(|(commitment, note)| {
tracing::info!(?commitment, ?note, "mock client note commitment")
});

// Next, craft a transaction, containing this `Spend`.
// Build a transaction spending this note.
let tx = {
use {
penumbra_asset::Value,
penumbra_fee::Fee,
penumbra_num::Amount,
penumbra_transaction::{Action, Transaction, TransactionBody, TransactionParameters},
penumbra_txhash::AuthorizingData,
};
let transaction_parameters = TransactionParameters {
expiry_height: 0,
chain_id: "i-wonder-if-this-is-load-bearing".to_owned(),
fee: Fee(Value {
amount: Amount::zero(),
asset_id,
}),
};
let transaction_body = TransactionBody {
actions: vec![Action::Spend(spend)],
transaction_parameters,
let position = client
.sct
.witness(*commitment)
.ok_or_else(|| anyhow!("commitment is not witnessed"))?
.position();
let spend = SpendPlan::new(&mut rng, note.clone(), position);
let plan = TransactionPlan {
actions: vec![spend.into()],
..Default::default()
};
let binding_sig = spend_key.sign(rng, transaction_body.auth_hash().as_bytes());
let transaction = Transaction {
transaction_body,
binding_sig,
anchor: sct.root(),
};
<Transaction as penumbra_proto::DomainType>::encode_to_vec(&transaction)
let witness = plan.witness_data(&client.sct)?;
let auth = plan.authorize(rand_core::OsRng, spend_key)?;
plan.build_concurrent(viewing_key, &witness, &auth).await?
};

// Execute the transaction, and sync another mock client up to the latest snapshot.
test_node.block().with_data(vec![tx]).execute().await?;
MockClient::new(test_keys::FULL_VIEWING_KEY.clone())
test_node
.block()
.with_data(vec![tx.encode_to_vec()]) // TODO(kate): add a `with_tx` extension method
.execute()
.await?;

// Sync to the latest storage snapshot once more.
let client = MockClient::new(test_keys::FULL_VIEWING_KEY.clone())
.with_sync_to_storage(&storage)
.await?;

client.notes.get(&commitment).unwrap();

// Free our temporary storage.
drop(storage);
drop(guard);
Expand Down
1 change: 1 addition & 0 deletions crates/core/transaction/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod build;
mod clue;
mod detection_data;
mod memo;
mod spend;

pub use action::ActionPlan;
pub use clue::CluePlan;
Expand Down
21 changes: 21 additions & 0 deletions crates/core/transaction/src/plan/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,25 @@ impl TransactionPlan {
// 4. Return the completed transaction.
Ok(tx)
}

/// Returns a [`WitnessData`], which may be used to build this transaction.
pub fn witness_data(&self, sct: &penumbra_tct::Tree) -> Result<WitnessData, anyhow::Error> {
let anchor = sct.root();

let witness_note = |spend: &penumbra_shielded_pool::SpendPlan| {
let commitment = spend.note.commit();
sct.witness(commitment)
.ok_or_else(|| anyhow::anyhow!("commitment should exist in tree"))
.map(|proof| (commitment, proof))
};
let state_commitment_proofs = self
.spend_plans()
.map(witness_note)
.collect::<Result<_, _>>()?;

Ok(WitnessData {
anchor,
state_commitment_proofs,
})
}
}
2 changes: 2 additions & 0 deletions crates/core/transaction/src/plan/spend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// use penumbra_tct::Tree;
// use {super::*, penumbra_proto::DomainType, penumbra_shielded_pool::SpendPlan};
2 changes: 1 addition & 1 deletion crates/test/mock-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::collections::BTreeMap;
/// A bare-bones mock client for use exercising the state machine.
pub struct MockClient {
latest_height: u64,
fvk: FullViewingKey,
pub fvk: FullViewingKey,
pub notes: BTreeMap<note::StateCommitment, Note>,
swaps: BTreeMap<tct::StateCommitment, SwapPlaintext>,
pub sct: penumbra_tct::Tree,
Expand Down
2 changes: 1 addition & 1 deletion crates/test/mock-consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
//
// see penumbra-zone/penumbra#3588.

pub mod block;
pub mod builder;

mod abci;
mod block;

/// A test node.
///
Expand Down

0 comments on commit ad7d109

Please sign in to comment.