Browse Source

Send to address test

master
Aditya Kulkarni 5 years ago
parent
commit
c2f2cf207e
  1. 163
      src/lightwallet/mod.rs

163
src/lightwallet/mod.rs

@ -3,6 +3,8 @@ use std::io::{self, Read, Write};
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
use std::fs::File;
use std::io::{BufReader, BufWriter, Error, ErrorKind};
use log::{info, warn, error};
@ -131,6 +133,27 @@ impl LightWallet {
return 1;
}
fn get_sapling_params(config: &LightClientConfig) -> Result<(Vec<u8>, Vec<u8>), Error> {
// Read Sapling Params
let mut sapling_output = vec![];
let mut f = match File::open(config.get_params_path("sapling-output.params")) {
Ok(file) => file,
Err(_) => return Err(Error::new(ErrorKind::NotFound,
format!("Couldn't read {}", config.get_params_path("sapling-output.params").display())))
};
f.read_to_end(&mut sapling_output)?;
let mut sapling_spend = vec![];
let mut f = match File::open(config.get_params_path("sapling-spend.params")) {
Ok(file) => file,
Err(_) => return Err(Error::new(ErrorKind::NotFound,
format!("Couldn't read {}", config.get_params_path("sapling-spend.params").display())))
};
f.read_to_end(&mut sapling_spend)?;
Ok((sapling_spend, sapling_output))
}
fn get_pk_from_bip39seed(bip39seed: &[u8]) ->
(ExtendedSpendingKey, ExtendedFullViewingKey, PaymentAddress<Bls12>) {
let extsk: ExtendedSpendingKey = ExtendedSpendingKey::from_path(
@ -663,7 +686,6 @@ impl LightWallet {
},
None => {}
};
}
}
}
@ -1087,7 +1109,7 @@ pub mod tests {
use ff::{Field, PrimeField, PrimeFieldRepr};
use pairing::bls12_381::Bls12;
use rand_core::{RngCore, OsRng};
use protobuf::Message;
use protobuf::{Message, UnknownFields, CachedSize, RepeatedField};
use zcash_client_backend::{encoding::encode_payment_address,
proto::compact_formats::{
CompactBlock, CompactOutput, CompactSpend, CompactTx,
@ -1102,6 +1124,7 @@ pub mod tests {
transaction::{
TxId, Transaction, TransactionData,
components::{TxOut, TxIn, OutPoint, Amount,},
components::amount::DEFAULT_FEE,
},
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
JUBJUB,
@ -1141,6 +1164,47 @@ pub mod tests {
BlockHash(self.block.hash[..].try_into().unwrap())
}
fn tx_to_compact_tx(tx: &Transaction, index: u64) -> CompactTx {
let spends = tx.shielded_spends.iter().map(|s| {
let mut c_spend = CompactSpend::default();
c_spend.set_nf(s.nullifier.to_vec());
c_spend
}).collect::<Vec<CompactSpend>>();
let outputs = tx.shielded_outputs.iter().map(|o| {
let mut c_out = CompactOutput::default();
let mut cmu_bytes = vec![];
o.cmu.into_repr().write_le(&mut cmu_bytes).unwrap();
let mut epk_bytes = vec![];
o.ephemeral_key.write(&mut epk_bytes).unwrap();
c_out.set_cmu(cmu_bytes);
c_out.set_epk(epk_bytes);
c_out.set_ciphertext(o.enc_ciphertext[0..52].to_vec());
c_out
}).collect::<Vec<CompactOutput>>();
CompactTx {
index,
hash: tx.txid().0.to_vec(),
fee: 0, // TODO: Get Fee
spends: RepeatedField::from_vec(spends),
outputs: RepeatedField::from_vec(outputs),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
}
}
// Convert the transaction into a CompactTx and add it to this block
fn add_tx(&mut self, tx: &Transaction) {
let ctx = FakeCompactBlock::tx_to_compact_tx(&tx, self.block.vtx.len() as u64);
self.block.vtx.push(ctx);
}
// Add a new tx into the block, paying the given address the amount.
// Returns the nullifier of the new note.
fn add_tx_paying(&mut self, extfvk: ExtendedFullViewingKey, value: u64)
@ -1663,4 +1727,99 @@ pub mod tests {
assert_eq!(txs[&txid2].total_transparent_value_spent, TAMOUNT1);
}
}
#[test]
fn test_z_spend() {
let config = LightClientConfig {
server: "0.0.0.0:0".to_string(),
chain_name: "test".to_string(),
sapling_activation_height: 0
};
let wallet = LightWallet::new(None, &config).unwrap();
const AMOUNT1:u64 = 50000;
// Address is encoded in bech32
let address = Some(encode_payment_address(wallet.config.hrp_sapling_address(),
&wallet.extfvks[0].default_address().unwrap().1));
let mut cb1 = FakeCompactBlock::new(0, BlockHash([0; 32]));
let (_, txid1) = cb1.add_tx_paying(wallet.extfvks[0].clone(), AMOUNT1);
wallet.scan_block(&cb1.as_bytes()).unwrap();
// We have one note
{
let txs = wallet.txs.read().unwrap();
assert_eq!(txs[&txid1].notes.len(), 1);
assert_eq!(txs[&txid1].notes[0].note.value, AMOUNT1);
assert_eq!(txs[&txid1].notes[0].spent, None);
assert_eq!(txs[&txid1].notes[0].unconfirmed_spent, None);
}
assert_eq!(wallet.verified_zbalance(None), AMOUNT1);
// Create a new block so that the note is now verified to be spent
let cb2 = FakeCompactBlock::new(1, cb1.hash());
wallet.scan_block(&cb2.as_bytes()).unwrap();
let fvk = ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[1u8; 32]));
let ext_address = encode_payment_address(wallet.config.hrp_sapling_address(),
&fvk.default_address().unwrap().1);
const AMOUNT_SENT: u64 = 20;
let outgoing_memo = "Outgoing Memo".to_string();
let fee: u64 = DEFAULT_FEE.try_into().unwrap();
let branch_id = u32::from_str_radix("2bb40e60", 16).unwrap();
let (ss, so) = LightWallet::get_sapling_params(&config).unwrap();
// Create a tx and send to address
let raw_tx = wallet.send_to_address(branch_id, &ss, &so,
&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone())).unwrap();
let sent_tx = Transaction::read(&raw_tx[..]).unwrap();
let sent_txid = sent_tx.txid();
// Now, the note should be unconfirmed spent
{
let txs = wallet.txs.read().unwrap();
assert_eq!(txs[&txid1].notes[0].note.value, AMOUNT1);
assert_eq!(txs[&txid1].notes[0].spent, None);
assert_eq!(txs[&txid1].notes[0].unconfirmed_spent, Some(sent_txid));
}
let mut cb3 = FakeCompactBlock::new(2, cb2.hash());
cb3.add_tx(&sent_tx);
wallet.scan_block(&cb3.as_bytes()).unwrap();
// Now this new Spent tx should be in, so the note should be marked confirmed spent
{
let txs = wallet.txs.read().unwrap();
assert_eq!(txs[&txid1].notes.len(), 1);
assert_eq!(txs[&txid1].notes[0].note.value, AMOUNT1);
assert_eq!(txs[&txid1].notes[0].spent, Some(sent_txid));
assert_eq!(txs[&txid1].notes[0].unconfirmed_spent, None);
// The sent tx should generate change
assert_eq!(txs[&sent_txid].notes.len(), 1);
assert_eq!(txs[&sent_txid].notes[0].note.value, AMOUNT1 - AMOUNT_SENT - fee);
assert_eq!(txs[&sent_txid].notes[0].spent, None);
assert_eq!(txs[&sent_txid].notes[0].unconfirmed_spent, None);
}
// Now, full scan the Tx, which should populate the Outgoing Meta data
wallet.scan_full_tx(&sent_tx, 2);
// Check Outgoing Metadata
{
let txs = wallet.txs.read().unwrap();
assert_eq!(txs[&sent_txid].outgoing_metadata.len(), 1);
assert_eq!(txs[&sent_txid].outgoing_metadata[0].address, ext_address);
assert_eq!(txs[&sent_txid].outgoing_metadata[0].value, AMOUNT_SENT);
assert_eq!(txs[&sent_txid].outgoing_metadata[0].memo.to_utf8().unwrap().unwrap(), outgoing_memo);
}
}
}
Loading…
Cancel
Save