Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit c80bb93

Browse files
committed
single scan test
1 parent 86026f9 commit c80bb93

File tree

2 files changed

+111
-13
lines changed

2 files changed

+111
-13
lines changed

lib/src/blaze/test_utils.rs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use tokio::sync::RwLock;
1515
use zcash_primitives::{
1616
block::BlockHash,
1717
constants::SPENDING_KEY_GENERATOR,
18+
keys::OutgoingViewingKey,
1819
memo::Memo,
1920
merkle_tree::{CommitmentTree, Hashable, IncrementalWitness, MerklePath},
2021
note_encryption::SaplingNoteEncryption,
@@ -187,11 +188,13 @@ impl FakeCompactBlockList {
187188
}
188189
}
189190

190-
// Add a new tx into the block, paying the given address the amount.
191-
// Returns the nullifier of the new note.
192-
pub fn add_tx_paying(&mut self, extfvk: &ExtendedFullViewingKey, value: u64) -> (Nullifier, Transaction, u64) {
193-
let to = extfvk.default_address().unwrap().1;
194-
191+
// Create a dummy compact output with given value sending it to 'to', and encode
192+
// the output with the ovk if available
193+
fn create_sapling_output(
194+
value: u64,
195+
ovk: Option<OutgoingViewingKey>,
196+
to: &PaymentAddress,
197+
) -> (CompactTx, Transaction, Note) {
195198
// Create a fake Note for the account
196199
let mut rng = OsRng;
197200
let note = Note {
@@ -200,10 +203,8 @@ impl FakeCompactBlockList {
200203
value,
201204
rseed: Rseed::BeforeZip212(jubjub::Fr::random(rng)),
202205
};
203-
let nf = note.nf(&extfvk.fvk.vk, 0);
204206

205-
let mut encryptor =
206-
SaplingNoteEncryption::new(None, note.clone(), to.clone(), Memo::default().into(), &mut rng);
207+
let mut encryptor = SaplingNoteEncryption::new(ovk, note.clone(), to.clone(), Memo::default().into(), &mut rng);
207208

208209
let mut rng = OsRng;
209210
let rcv = jubjub::Fr::random(&mut rng);
@@ -238,16 +239,49 @@ impl FakeCompactBlockList {
238239
td.shielded_outputs.push(od);
239240
td.binding_sig = Signature::read(&vec![0u8; 64][..]).ok();
240241
let tx = td.freeze().unwrap();
241-
let height = self.next_height;
242-
self.txns.push((tx.clone(), height));
243242

244243
let mut ctx = CompactTx::default();
245244
ctx.hash = tx.txid().clone().0.to_vec();
246245
ctx.outputs.push(cout);
247246

247+
(ctx, tx, note)
248+
}
249+
250+
pub fn add_tx_spending(
251+
&mut self,
252+
nf: &Nullifier,
253+
value: u64,
254+
ovk: &OutgoingViewingKey,
255+
to: &PaymentAddress,
256+
) -> Transaction {
257+
let (mut ctx, tx, _) = Self::create_sapling_output(value, Some(ovk.clone()), to);
258+
259+
println!("Spending nullifier {}", hex::encode(nf.0));
260+
let mut cs = CompactSpend::default();
261+
cs.nf = nf.to_vec();
262+
ctx.spends.push(cs);
263+
264+
// We should be adding the nullifier to the full tx (tx.shielded_spends) as well, but we don't use it,
265+
// so we pretend it doen't exist :)
266+
267+
let height = self.next_height;
268+
self.txns.push((tx.clone(), height));
269+
self.add_empty_block().add_txs(vec![ctx]);
270+
271+
tx
272+
}
273+
274+
// Add a new tx into the block, paying the given address the amount.
275+
// Returns the nullifier of the new note.
276+
pub fn add_tx_paying(&mut self, extfvk: &ExtendedFullViewingKey, value: u64) -> (Transaction, u64, Note) {
277+
let to = extfvk.default_address().unwrap().1;
278+
let (ctx, tx, note) = Self::create_sapling_output(value, None, &to);
279+
280+
let height = self.next_height;
281+
self.txns.push((tx.clone(), height));
248282
self.add_empty_block().add_txs(vec![ctx]);
249283

250-
(nf, tx, height)
284+
(tx, height, note)
251285
}
252286

253287
pub fn add_empty_block(&mut self) -> &'_ mut FakeCompactBlock {

lib/src/lightclient/tests.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ use tokio::task::JoinHandle;
1313
use tonic::transport::{Channel, Server};
1414
use tonic::Request;
1515

16+
use zcash_client_backend::address::RecipientAddress;
17+
use zcash_primitives::consensus::MAIN_NETWORK;
1618
use zcash_primitives::memo::Memo;
19+
use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness};
1720
use zcash_primitives::note_encryption::SaplingNoteEncryption;
1821
use zcash_primitives::primitives::{Note, Rseed, ValueCommitment};
1922
use zcash_primitives::redjubjub::Signature;
23+
use zcash_primitives::sapling::Node;
2024
use zcash_primitives::transaction::components::{OutputDescription, GROTH_PROOF_SIZE};
2125
use zcash_primitives::transaction::TransactionData;
2226

@@ -144,7 +148,7 @@ async fn z_incoming_z_outgoing() {
144148
// 2. Send an incoming tx to fill the wallet
145149
let extfvk1 = lc.wallet.keys().read().await.get_all_extfvks()[0].clone();
146150
let value = 100_000;
147-
let (_nf, tx, _height) = fcbl.add_tx_paying(&extfvk1, value);
151+
let (tx, _height, _) = fcbl.add_tx_paying(&extfvk1, value);
148152
mine_pending_blocks(&mut fcbl, &data, &lc).await;
149153

150154
assert_eq!(lc.wallet.last_scanned_height().await, 101);
@@ -404,7 +408,7 @@ async fn z_incoming_multiz_outgoing() {
404408
// 2. Send an incoming tx to fill the wallet
405409
let extfvk1 = lc.wallet.keys().read().await.get_all_extfvks()[0].clone();
406410
let value = 100_000;
407-
let (_nf, _tx, _height) = fcbl.add_tx_paying(&extfvk1, value);
411+
let (_tx, _height, _) = fcbl.add_tx_paying(&extfvk1, value);
408412
mine_pending_blocks(&mut fcbl, &data, &lc).await;
409413
mine_random_blocks(&mut fcbl, &data, &lc, 5).await;
410414

@@ -443,5 +447,65 @@ async fn z_incoming_multiz_outgoing() {
443447
h1.await.unwrap();
444448
}
445449

450+
#[tokio::test]
451+
async fn z_to_z_scan_together() {
452+
// Create an incoming tx, and then send that tx, and scan everything together, to make sure it works.
453+
let (data, config, ready_rx, stop_tx, h1) = create_test_server().await;
454+
455+
ready_rx.await.unwrap();
456+
457+
let lc = LightClient::test_new(&config, None).await.unwrap();
458+
let mut fcbl = FakeCompactBlockList::new(0);
459+
460+
// 1. Start with 100 blocks that are unmined
461+
fcbl.add_blocks(100);
462+
463+
// 2. Send an incoming tx to fill the wallet
464+
let extfvk1 = lc.wallet.keys().read().await.get_all_extfvks()[0].clone();
465+
let value = 100_000;
466+
let (tx, _height, note) = fcbl.add_tx_paying(&extfvk1, value);
467+
468+
// Calculate witness so we can get the nullifier without it getting mined
469+
let tree = fcbl
470+
.blocks
471+
.iter()
472+
.fold(CommitmentTree::<Node>::empty(), |mut tree, fcb| {
473+
for tx in &fcb.block.vtx {
474+
for co in &tx.outputs {
475+
tree.append(Node::new(co.cmu().unwrap().into())).unwrap();
476+
}
477+
}
478+
479+
tree
480+
});
481+
let witness = IncrementalWitness::from_tree(&tree);
482+
let nf = note.nf(&extfvk1.fvk.vk, witness.position() as u64);
483+
484+
let pa = if let Some(RecipientAddress::Shielded(pa)) = RecipientAddress::decode(&MAIN_NETWORK, EXT_ZADDR) {
485+
pa
486+
} else {
487+
panic!("Couldn't parse address")
488+
};
489+
let spent_tx = fcbl.add_tx_spending(&nf, 100, &extfvk1.fvk.ovk, &pa);
490+
491+
// Mine the blocks and sync the lightwallet
492+
mine_pending_blocks(&mut fcbl, &data, &lc).await;
493+
494+
let list = lc.do_list_transactions(false).await;
495+
496+
assert_eq!(list[0]["block_height"].as_u64().unwrap(), 101);
497+
assert_eq!(list[0]["txid"], tx.txid().to_string());
498+
499+
assert_eq!(list[1]["block_height"].as_u64().unwrap(), 102);
500+
assert_eq!(list[1]["txid"], spent_tx.txid().to_string());
501+
assert_eq!(list[1]["amount"].as_i64().unwrap(), -(value as i64));
502+
assert_eq!(list[1]["outgoing_metadata"][0]["address"], EXT_ZADDR.to_string());
503+
assert_eq!(list[1]["outgoing_metadata"][0]["value"].as_u64().unwrap(), 100);
504+
505+
// Shutdown everything cleanly
506+
stop_tx.send(true).unwrap();
507+
h1.await.unwrap();
508+
}
509+
446510
const EXT_ZADDR: &str = "zs1va5902apnzlhdu0pw9r9q7ca8s4vnsrp2alr6xndt69jnepn2v2qrj9vg3wfcnjyks5pg65g9dc";
447511
const EXT_ZADDR2: &str = "zs1fxgluwznkzm52ux7jkf4st5znwzqay8zyz4cydnyegt2rh9uhr9458z0nk62fdsssx0cqhy6lyv";

0 commit comments

Comments
 (0)