Skip to content
163 changes: 84 additions & 79 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions zingolib/src/blaze/block_management_reorg_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,9 @@ mod tests {
.handle_reorgs_and_populate_block_mangement_data(
start_block,
end_block,
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())),
Arc::new(RwLock::new(
TxMapAndMaybeTrees::new_with_witness_trees_address_free(),
)),
reorg_transmitter,
)
.await;
Expand Down Expand Up @@ -890,7 +892,9 @@ mod tests {
.handle_reorgs_and_populate_block_mangement_data(
start_block,
end_block,
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())),
Arc::new(RwLock::new(
TxMapAndMaybeTrees::new_with_witness_trees_address_free(),
)),
reorg_transmitter,
)
.await;
Expand Down Expand Up @@ -986,7 +990,9 @@ mod tests {
.handle_reorgs_and_populate_block_mangement_data(
start_block,
end_block,
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees())),
Arc::new(RwLock::new(
TxMapAndMaybeTrees::new_with_witness_trees_address_free(),
)),
reorg_transmitter,
)
.await;
Expand Down
28 changes: 7 additions & 21 deletions zingolib/src/lightclient/propose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,33 +170,20 @@ impl LightClient {
)
.map_err(DoProposeError::Proposal)?;

let mut latest_proposal_lock = self.latest_proposal.write().await;
*latest_proposal_lock = Some(crate::data::proposal::ZingoProposal::Transfer(
proposal.clone(),
));
self.update_latest_proposal(ZingoProposal::Transfer(proposal.clone()))
.await;
Ok(proposal)
}

fn get_transparent_addresses(
&self,
) -> Result<Vec<zcash_primitives::legacy::TransparentAddress>, DoProposeError> {
let secp = secp256k1::Secp256k1::new();
Ok(self
.wallet
.wallet_capability()
.transparent_child_keys()
.map_err(|_e| {
DoProposeError::ShieldProposal(
zcash_client_backend::data_api::error::Error::DataSource(
TxMapAndMaybeTreesTraitError::NoSpendCapability,
),
)
})?
.transparent_child_addresses()
.iter()
.map(|(_index, sk)| {
#[allow(deprecated)]
zcash_primitives::legacy::keys::pubkey_to_address(&sk.public_key(&secp))
})
.map(|(_index, sk)| *sk)
.collect::<Vec<_>>())
}
/// The shield operation consumes a proposal that transfers value
Expand Down Expand Up @@ -239,16 +226,15 @@ impl LightClient {
&input_selector,
// don't shield dust
NonNegativeAmount::const_from_u64(10_000),
&self.get_transparent_addresses()?,
&dbg!(self.get_transparent_addresses()?),
// review! do we want to require confirmations?
// make it configurable?
0,
)
.map_err(DoProposeError::ShieldProposal)?;

*self.latest_proposal.write().await = Some(crate::data::proposal::ZingoProposal::Shield(
proposed_shield.clone(),
));
self.update_latest_proposal(ZingoProposal::Shield(proposed_shield.clone()))
.await;
Ok(proposed_shield)
}
/// A helper method that standardizes latest_proposal update
Expand Down
143 changes: 84 additions & 59 deletions zingolib/src/lightclient/send.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
//! TODO: Add Mod Description Here!
use std::ops::DerefMut;

use nonempty::NonEmpty;

use sapling_crypto::prover::OutputProver;
use sapling_crypto::prover::SpendProver;

use zcash_keys::keys::UnifiedSpendingKey;

use zcash_client_backend::{proposal::Proposal, zip321::TransactionRequest};
use zcash_primitives::{consensus::BlockHeight, transaction::TxId};
use zcash_proofs::prover::LocalTxProver;
Expand All @@ -33,38 +27,57 @@ impl LightClient {
})
}

async fn iterate_proposal_send_scan<NoteRef>(
async fn update_tmamt_and_return_step_result<N>(
&self,
proposal: &Proposal<zcash_primitives::transaction::fees::zip317::FeeRule, N>,
step: zcash_client_backend::proposal::Step<N>,
step_results: &[(
&zcash_client_backend::proposal::Step<N>,
zcash_primitives::transaction::builder::BuildResult,
)],
) -> Result<zcash_primitives::transaction::builder::BuildResult, DoSendProposedError> {
let fee_rule = proposal.fee_rule();
let min_target_height = proposal.min_target_height();
let unified_spend_key = zcash_keys::keys::UnifiedSpendingKey::try_from(
self.wallet.wallet_capability().as_ref(),
)
.map_err(DoSendProposedError::UnifiedSpendKey)?;
let (sapling_output, sapling_spend) = self
.read_sapling_params()
.map_err(DoSendProposedError::SaplingParams)?;
let sapling_prover = LocalTxProver::from_bytes(&sapling_spend, &sapling_output);
zcash_client_backend::data_api::wallet::calculate_proposed_transaction(
std::ops::DerefMut::deref_mut(
&mut self
.wallet
.transaction_context
.transaction_metadata_set
.write()
.await,
),
&self.wallet.transaction_context.config.chain,
&sapling_prover,
&sapling_prover,
&unified_spend_key,
zcash_client_backend::wallet::OvkPolicy::Sender,
fee_rule,
min_target_height,
step_results,
&step,
)
.map_err(DoSendProposedError::Calculation)
}
async fn iterate_proposal_send_scan<NoteRef: Sized + Clone>(
&self,
proposal: &Proposal<zcash_primitives::transaction::fees::zip317::FeeRule, NoteRef>,
sapling_prover: &(impl SpendProver + OutputProver),
unified_spend_key: &UnifiedSpendingKey,
submission_height: BlockHeight,
) -> Result<NonEmpty<TxId>, DoSendProposedError> {
let mut step_results = Vec::with_capacity(proposal.steps().len());
let mut txids = Vec::with_capacity(proposal.steps().len());
for step in proposal.steps() {
let step_result = {
let mut tmamt = self
.wallet
.transaction_context
.transaction_metadata_set
.write()
.await;

zcash_client_backend::data_api::wallet::calculate_proposed_transaction(
tmamt.deref_mut(),
&self.wallet.transaction_context.config.chain,
sapling_prover,
sapling_prover,
unified_spend_key,
zcash_client_backend::wallet::OvkPolicy::Sender,
proposal.fee_rule(),
proposal.min_target_height(),
&step_results,
step,
)
.map_err(DoSendProposedError::Calculation)?
};
let step_result = self
.update_tmamt_and_return_step_result(proposal, step.clone(), &step_results)
.await?;

let txid = self
.wallet
Expand Down Expand Up @@ -108,32 +121,14 @@ impl LightClient {
.await
.map_err(DoSendProposedError::SubmissionHeight)?;

let (sapling_output, sapling_spend) = self
.read_sapling_params()
.map_err(DoSendProposedError::SaplingParams)?;
let sapling_prover = LocalTxProver::from_bytes(&sapling_spend, &sapling_output);
let unified_spend_key =
UnifiedSpendingKey::try_from(self.wallet.wallet_capability().as_ref())
.map_err(DoSendProposedError::UnifiedSpendKey)?;

match proposal {
crate::lightclient::ZingoProposal::Transfer(transfer_proposal) => {
self.iterate_proposal_send_scan(
transfer_proposal,
&sapling_prover,
&unified_spend_key,
submission_height,
)
.await
self.iterate_proposal_send_scan(transfer_proposal, submission_height)
.await
}
crate::lightclient::ZingoProposal::Shield(shield_proposal) => {
self.iterate_proposal_send_scan(
shield_proposal,
&sapling_prover,
&unified_spend_key,
submission_height,
)
.await
self.iterate_proposal_send_scan(shield_proposal, submission_height)
.await
}
}
} else {
Expand Down Expand Up @@ -163,10 +158,13 @@ mod test {
use zingo_testvectors::seeds::HOSPITAL_MUSEUM_SEED;
use zingoconfig::ZingoConfigBuilder;

use crate::{lightclient::LightClient, test_framework::mocks::ProposalBuilder};
use crate::{
lightclient::{send::DoSendProposedError, LightClient},
test_framework::mocks::{ProposalBuilder, StepBuilder},
};

#[tokio::test]
async fn update_tmamt_and_return_step_result() {
async fn update_tmamt_and_return_step_result_no_receipts() {
let config = ZingoConfigBuilder::default().create();
let client = LightClient::create_unconnected(
&config,
Expand All @@ -175,12 +173,39 @@ mod test {
)
.await
.expect("A client!");
let proposal = ProposalBuilder::new().build();
let step = zcash_client_backend::proposal::Step::from_parts();
let proposal = ProposalBuilder::default().build();
let step = StepBuilder::default().build();
let step_results: Vec<(
&zcash_client_backend::proposal::Step<zcash_client_backend::wallet::NoteId>,
zcash_primitives::transaction::builder::BuildResult,
)> = vec![];
let step_result = client
.update_tmamt_and_return_step_result(&proposal, step, step_results)
.update_tmamt_and_return_step_result(&proposal, step, &step_results)
.await;
dbg!(&step_result);
if let Err(DoSendProposedError::Calculation(e)) = step_result {
if let zcash_client_backend::data_api::error::Error::CommitmentTree(e2) = e {
if let shardtree::error::ShardTreeError::Query(e3) = e2 {
assert_eq!(e3, shardtree::error::QueryError::CheckpointPruned);
} else {
panic!("Wrong Error in layer 3.");
};
} else {
panic!("Wrong zcash_api error!");
}
} else {
panic!("Wrong state!");
}
}
/*
match step_result {
Err(DoSendProposedError::Calculation(e)) => {
match e {
zcash_client_backend::data_api::error::Error::CommitmentTree(e)
}
}
_ => panic!(),
*/
}

/// Errors that can result from do_send_proposed
Expand Down Expand Up @@ -216,6 +241,6 @@ pub enum DoSendProposedError {
pub enum DoQuickSendProposedError {
#[error("propose {0}")]
Propose(crate::lightclient::propose::DoProposeError),
#[error("No proposal. Call do_propose first.")]
#[error("Can't QuickSend! No proposal. Call do_propose first.")]
Send(DoSendProposedError),
}
8 changes: 6 additions & 2 deletions zingolib/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,13 @@ impl LightWallet {
));
};
let transaction_metadata_set = if wc.can_spend_from_all_pools() {
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees()))
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_with_witness_trees(
wc.transparent_child_addresses().clone(),
)))
} else {
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_treeless()))
Arc::new(RwLock::new(TxMapAndMaybeTrees::new_treeless(
wc.transparent_child_addresses().clone(),
)))
};
let transaction_context =
TransactionContext::new(&config, Arc::new(wc), transaction_metadata_set);
Expand Down
10 changes: 5 additions & 5 deletions zingolib/src/wallet/keys/extended_transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ impl KeyIndex {
}

/// Generate KeyIndex from raw index value.
pub fn from_index(i: u32) -> Result<Self, Error> {
pub fn from_index(i: u32) -> Self {
if i < HARDENED_KEY_START_INDEX {
Ok(KeyIndex::Normal(i))
KeyIndex::Normal(i)
} else {
Ok(KeyIndex::Hardened(i))
KeyIndex::Hardened(i)
}
}
}

impl From<u32> for KeyIndex {
fn from(index: u32) -> Self {
KeyIndex::from_index(index).expect("KeyIndex")
KeyIndex::from_index(index)
}
}

Expand Down Expand Up @@ -278,7 +278,7 @@ fn test_commutativity_of_key_derivation_mechanisms() {
// pk ---> pk_i

// initial key derivation material
let i = KeyIndex::from_index(42).unwrap();
let i = KeyIndex::from_index(42);
let sk = ExtendedPrivKey::with_seed(&[0xcd; 64]).unwrap();

// sk -> sk_i -> pk_i derivation
Expand Down
Loading