Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send proposed transactions #26

Open
wants to merge 13 commits into
base: send_proposed_transactions
Choose a base branch
from
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
Loading