Update librustzcash

This commit is contained in:
Hanh 2022-03-15 10:40:08 +08:00
parent f8f9a2bf29
commit f6d35b4d41
9 changed files with 76 additions and 55 deletions

View File

@ -43,10 +43,10 @@ rayon = "1.5.1"
tiny-bip39 = "0.8" tiny-bip39 = "0.8"
rand = "0.8.4" rand = "0.8.4"
rusqlite = { version = "^0.24", features = ["bundled"] } rusqlite = { version = "^0.24", features = ["bundled"] }
jubjub = "^0.6" jubjub = "0.8.0"
bls12_381 = "^0.4.0" bls12_381 = "0.6"
ff = "^0.9" ff = "0.11"
group = "0.9.0" group = "0.11"
byteorder = "^1.4" byteorder = "^1.4"
secp256k1 = "0.20.2" secp256k1 = "0.20.2"
tiny-hderive = "0.3.0" tiny-hderive = "0.3.0"
@ -69,23 +69,31 @@ base64 = "^0.13"
[dependencies.zcash_client_backend] [dependencies.zcash_client_backend]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "71b6227a4d96faab2c838159f54b69e6ab034147" rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
[dependencies.zcash_primitives] [dependencies.zcash_primitives]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "71b6227a4d96faab2c838159f54b69e6ab034147" rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
features = [ "transparent-inputs" ] features = [ "transparent-inputs" ]
[dependencies.zcash_proofs] [dependencies.zcash_proofs]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "71b6227a4d96faab2c838159f54b69e6ab034147" rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
[dependencies.zcash_params] [dependencies.zcash_params]
path = "../zcash-params" path = "../zcash-params"
[dependencies.zcash_address] [dependencies.zcash_address]
git = "https://github.com/hhanh00/librustzcash.git" git = "https://github.com/hhanh00/librustzcash.git"
rev = "19a97f16945c68c33aedcc89f2a4f4d398658b05" rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
[dependencies.zcash_encoding]
git = "https://github.com/hhanh00/librustzcash.git"
rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
[dependencies.zcash_note_encryption]
git = "https://github.com/hhanh00/librustzcash.git"
rev = "a25bb7aaa9bf35669280a2c1b7d6fb8b52f30b2d"
[build-dependencies] [build-dependencies]
tonic-build = "0.4.2" tonic-build = "0.4.2"

View File

@ -4,7 +4,6 @@ use crate::lw_rpc::compact_tx_streamer_client::CompactTxStreamerClient;
use crate::lw_rpc::*; use crate::lw_rpc::*;
use crate::advance_tree; use crate::advance_tree;
use ff::PrimeField; use ff::PrimeField;
use group::GroupEncoding;
use log::info; use log::info;
use rayon::prelude::*; use rayon::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
@ -18,6 +17,7 @@ use zcash_primitives::sapling::note_encryption::try_sapling_compact_note_decrypt
use zcash_primitives::sapling::{Node, Note, PaymentAddress}; use zcash_primitives::sapling::{Node, Note, PaymentAddress};
use zcash_primitives::transaction::components::sapling::CompactOutputDescription; use zcash_primitives::transaction::components::sapling::CompactOutputDescription;
use zcash_primitives::zip32::ExtendedFullViewingKey; use zcash_primitives::zip32::ExtendedFullViewingKey;
use zcash_note_encryption::EphemeralKeyBytes;
const MAX_CHUNK: u32 = 50000; const MAX_CHUNK: u32 = 50000;
@ -119,11 +119,13 @@ pub fn to_output_description(co: &CompactOutput) -> CompactOutputDescription {
let cmu = bls12_381::Scalar::from_repr(cmu).unwrap(); let cmu = bls12_381::Scalar::from_repr(cmu).unwrap();
let mut epk = [0u8; 32]; let mut epk = [0u8; 32];
epk.copy_from_slice(&co.epk); epk.copy_from_slice(&co.epk);
let epk = jubjub::ExtendedPoint::from_bytes(&epk).unwrap(); // let epk = jubjub::ExtendedPoint::from_bytes(&epk).unwrap();
let mut enc_ciphertext = [0u8; 52];
enc_ciphertext.copy_from_slice(&co.ciphertext);
let od = CompactOutputDescription { let od = CompactOutputDescription {
epk, ephemeral_key: EphemeralKeyBytes::from(epk),
cmu, cmu,
enc_ciphertext: co.ciphertext.to_vec(), enc_ciphertext,
}; };
od od
} }
@ -144,6 +146,11 @@ fn decrypt_notes<'a, N: Parameters>(
spends.push(Nf(nf)); spends.push(Nf(nf));
} }
// let _epks: Vec<_> = vtx.outputs.iter().map(|o| {
// &o.epk
// }).collect();
for (output_index, co) in vtx.outputs.iter().enumerate() { for (output_index, co) in vtx.outputs.iter().enumerate() {
let od = to_output_description(co); let od = to_output_description(co);
for (&account, vk) in vks.iter() { for (&account, vk) in vks.iter() {

View File

@ -3,7 +3,7 @@ use byteorder::WriteBytesExt;
use std::io::{Read, Write}; use std::io::{Read, Write};
use zcash_primitives::merkle_tree::{CommitmentTree, Hashable}; use zcash_primitives::merkle_tree::{CommitmentTree, Hashable};
use zcash_primitives::sapling::Node; use zcash_primitives::sapling::Node;
use zcash_primitives::serialize::{Optional, Vector}; use zcash_encoding::{Optional, Vector};
/* /*
Same behavior and structure as CommitmentTree<Node> from librustzcash Same behavior and structure as CommitmentTree<Node> from librustzcash
@ -139,10 +139,10 @@ impl CTree {
} }
pub fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> { pub fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
Optional::write(&mut writer, &self.left, |w, n| n.write(w))?; Optional::write(&mut writer, self.left, |w, n| n.write(w))?;
Optional::write(&mut writer, &self.right, |w, n| n.write(w))?; Optional::write(&mut writer, self.right, |w, n| n.write(w))?;
Vector::write(&mut writer, &self.parents, |w, e| { Vector::write(&mut writer, &self.parents, |w, e| {
Optional::write(w, e, |w, n| n.write(w)) Optional::write(w, *e, |w, n| n.write(w))
}) })
} }

View File

@ -90,7 +90,7 @@ impl KeyHelpers {
pub fn derive_address(&self, fvk: &ExtendedFullViewingKey) -> anyhow::Result<String> { pub fn derive_address(&self, fvk: &ExtendedFullViewingKey) -> anyhow::Result<String> {
let network = self.chain().network(); let network = self.chain().network();
let (_, payment_address) = fvk.default_address().unwrap(); let (_, payment_address) = fvk.default_address();
let address = encode_payment_address(network.hrp_sapling_payment_address(), &payment_address); let address = encode_payment_address(network.hrp_sapling_payment_address(), &payment_address);
Ok(address) Ok(address)
} }

View File

@ -6,7 +6,6 @@ use rusqlite::NO_PARAMS;
use sync::{ use sync::{
pedersen_hash, print_witness2, ChainError, DbAdapter, RecipientMemo, Wallet, Witness, LWD_URL, pedersen_hash, print_witness2, ChainError, DbAdapter, RecipientMemo, Wallet, Witness, LWD_URL,
}; };
use zcash_client_backend::data_api::wallet::ANCHOR_OFFSET;
use zcash_primitives::memo::Memo; use zcash_primitives::memo::Memo;
use zcash_primitives::merkle_tree::Hashable; use zcash_primitives::merkle_tree::Hashable;
use zcash_primitives::sapling::Node; use zcash_primitives::sapling::Node;
@ -38,7 +37,7 @@ async fn test() -> anyhow::Result<()> {
// wallet.new_account_with_key("test", &seed2).unwrap(); // wallet.new_account_with_key("test", &seed2).unwrap();
// wallet.new_account_with_key("zecpages", &ivk).unwrap(); // wallet.new_account_with_key("zecpages", &ivk).unwrap();
let res = wallet.sync(true, ANCHOR_OFFSET, progress).await; let res = wallet.sync(true, 10, progress).await;
if let Err(err) = res { if let Err(err) = res {
if let Some(_) = err.downcast_ref::<ChainError>() { if let Some(_) = err.downcast_ref::<ChainError>() {
println!("REORG"); println!("REORG");
@ -98,7 +97,7 @@ async fn test_sync() {
let mut wallet = Wallet::new(CoinType::Zcash, DB_NAME); let mut wallet = Wallet::new(CoinType::Zcash, DB_NAME);
wallet.set_lwd_url(LWD_URL).unwrap(); wallet.set_lwd_url(LWD_URL).unwrap();
wallet.sync(true, ANCHOR_OFFSET, progress).await.unwrap(); wallet.sync(true, 10, progress).await.unwrap();
} }
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -1,7 +1,7 @@
use crate::db::SpendableNote; use crate::db::SpendableNote;
use crate::wallet::RecipientMemo; use crate::wallet::RecipientMemo;
use crate::{ use crate::{
connect_lightwalletd, get_branch, get_latest_height, hex_to_hash, GetAddressUtxosReply, connect_lightwalletd, get_latest_height, hex_to_hash, GetAddressUtxosReply,
RawTransaction RawTransaction
}; };
use jubjub::Fr; use jubjub::Fr;
@ -10,6 +10,7 @@ use rand::rngs::OsRng;
use secp256k1::SecretKey; use secp256k1::SecretKey;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::mpsc; use std::sync::mpsc;
use anyhow::anyhow;
use tonic::Request; use tonic::Request;
use zcash_client_backend::address::RecipientAddress; use zcash_client_backend::address::RecipientAddress;
use zcash_client_backend::encoding::{ use zcash_client_backend::encoding::{
@ -20,7 +21,7 @@ use zcash_primitives::consensus::{BlockHeight, Parameters};
use zcash_primitives::legacy::Script; use zcash_primitives::legacy::Script;
use zcash_primitives::memo::{Memo, MemoBytes}; use zcash_primitives::memo::{Memo, MemoBytes};
use zcash_primitives::merkle_tree::IncrementalWitness; use zcash_primitives::merkle_tree::IncrementalWitness;
use zcash_primitives::sapling::keys::OutgoingViewingKey; use zcash_primitives::keys::OutgoingViewingKey;
use zcash_primitives::sapling::prover::TxProver; use zcash_primitives::sapling::prover::TxProver;
use zcash_primitives::sapling::{Diversifier, Node, PaymentAddress, Rseed}; use zcash_primitives::sapling::{Diversifier, Node, PaymentAddress, Rseed};
use zcash_primitives::transaction::builder::{Builder, Progress}; use zcash_primitives::transaction::builder::{Builder, Progress};
@ -187,10 +188,10 @@ impl TxBuilder {
t_amount += Amount::from_i64(utxo.value_zat).unwrap(); t_amount += Amount::from_i64(utxo.value_zat).unwrap();
} }
} }
let target_amount_with_fee = target_amount + DEFAULT_FEE; let target_amount_with_fee = (target_amount + DEFAULT_FEE).ok_or(anyhow!("Invalid amount"))?;
if target_amount_with_fee > t_amount { if target_amount_with_fee > t_amount {
// We need to use some shielded notes because the transparent balance is not enough // We need to use some shielded notes because the transparent balance is not enough
let mut amount = target_amount_with_fee - t_amount; let mut amount = (target_amount_with_fee - t_amount).unwrap();
// Pick spendable notes until we exceed the target_amount_with_fee or we ran out of notes // Pick spendable notes until we exceed the target_amount_with_fee or we ran out of notes
let mut notes = notes.to_vec(); let mut notes = notes.to_vec();
@ -242,7 +243,7 @@ impl TxBuilder {
recipients: &[RecipientMemo], recipients: &[RecipientMemo],
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let ovk = &fvk.fvk.ovk; let ovk = &fvk.fvk.ovk;
let (_, change) = fvk.default_address().unwrap(); let (_, change) = fvk.default_address();
self.set_change(&ovk, &change)?; self.set_change(&ovk, &change)?;
for r in recipients.iter() { for r in recipients.iter() {
@ -291,7 +292,7 @@ impl Tx {
&self, &self,
tsk: Option<SecretKey>, tsk: Option<SecretKey>,
zsk: &ExtendedSpendingKey, zsk: &ExtendedSpendingKey,
prover: &impl TxProver<OsRng>, prover: &impl TxProver,
progress_callback: impl Fn(Progress) + Send + 'static, progress_callback: impl Fn(Progress) + Send + 'static,
) -> anyhow::Result<Vec<u8>> { ) -> anyhow::Result<Vec<u8>> {
let chain = get_coin_chain(self.coin_type); let chain = get_coin_chain(self.coin_type);
@ -361,7 +362,7 @@ impl Tx {
let m = hex::decode(&txout.memo)?; let m = hex::decode(&txout.memo)?;
memo[..m.len()].copy_from_slice(&m); memo[..m.len()].copy_from_slice(&m);
let memo = MemoBytes::from_bytes(&memo)?; let memo = MemoBytes::from_bytes(&memo)?;
builder.add_sapling_output(Some(ovk), pa, amount, Some(memo))?; builder.add_sapling_output(Some(ovk), pa, amount, memo)?;
} }
} }
} }
@ -375,8 +376,7 @@ impl Tx {
progress_callback(progress); progress_callback(progress);
} }
}); });
let consensus_branch_id = get_branch(chain.network(), u32::from(last_height)); let (tx, _) = builder.build(prover)?;
let (tx, _) = builder.build(consensus_branch_id, prover)?;
let mut raw_tx = vec![]; let mut raw_tx = vec![];
tx.write(&mut raw_tx)?; tx.write(&mut raw_tx)?;

View File

@ -5,6 +5,7 @@ use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::mpsc::SyncSender; use std::sync::mpsc::SyncSender;
use anyhow::anyhow;
use tonic::transport::Channel; use tonic::transport::Channel;
use tonic::Request; use tonic::Request;
use zcash_client_backend::encoding::{ use zcash_client_backend::encoding::{
@ -17,7 +18,7 @@ use zcash_primitives::sapling::note_encryption::{
}; };
use zcash_primitives::transaction::Transaction; use zcash_primitives::transaction::Transaction;
use zcash_primitives::zip32::ExtendedFullViewingKey; use zcash_primitives::zip32::ExtendedFullViewingKey;
use zcash_params::coin::{CoinType, get_coin_chain}; use zcash_params::coin::{CoinType, get_coin_chain, get_branch};
#[derive(Debug)] #[derive(Debug)]
pub struct TransactionInfo { pub struct TransactionInfo {
@ -28,7 +29,7 @@ pub struct TransactionInfo {
pub address: String, pub address: String,
pub memo: String, pub memo: String,
pub amount: i64, pub amount: i64,
pub fee: u64, // pub fee: u64,
pub contacts: Vec<Contact>, pub contacts: Vec<Contact>,
} }
@ -50,6 +51,7 @@ pub async fn decode_transaction(
height: u32, height: u32,
index: u32, index: u32,
) -> anyhow::Result<TransactionInfo> { ) -> anyhow::Result<TransactionInfo> {
let consensus_branch_id = get_branch(network, u32::from(height));
let ivk = fvk.fvk.vk.ivk(); let ivk = fvk.fvk.vk.ivk();
let ovk = fvk.fvk.ovk; let ovk = fvk.fvk.ovk;
@ -62,24 +64,27 @@ pub async fn decode_transaction(
.get_transaction(Request::new(tx_filter)) .get_transaction(Request::new(tx_filter))
.await? .await?
.into_inner(); .into_inner();
let tx = Transaction::read(&*raw_tx.data)?; let tx = Transaction::read(&*raw_tx.data, consensus_branch_id)?;
let height = BlockHeight::from_u32(height); let height = BlockHeight::from_u32(height);
let mut amount = 0i64; let mut amount = 0i64;
let mut taddress = String::new(); let mut taddress = String::new();
let mut zaddress = String::new(); let mut zaddress = String::new();
for spend in tx.shielded_spends.iter() {
let tx = tx.into_data();
let sapling_bundle = tx.sapling_bundle().ok_or(anyhow!("No sapling bundle"))?;
for spend in sapling_bundle.shielded_spends.iter() {
let nf = spend.nullifier.to_vec(); let nf = spend.nullifier.to_vec();
if let Some(&v) = nfs.get(&(account, nf)) { if let Some(&v) = nfs.get(&(account, nf)) {
amount -= v as i64; amount -= v as i64;
} }
} }
let mut contact_decoder = ContactDecoder::new(tx.shielded_outputs.len()); let mut contact_decoder = ContactDecoder::new(tx.sapling_bundle().unwrap().shielded_outputs.len());
let mut tx_memo: Memo = Memo::Empty; let mut tx_memo: Memo = Memo::Empty;
for output in tx.vout.iter() { for output in tx.transparent_bundle().ok_or(anyhow!("No transparent bundle"))?.vout.iter() {
if let Some(taddr) = output.script_pubkey.address() { if let Some(taddr) = output.script_pubkey.address() {
taddress = encode_transparent_address( taddress = encode_transparent_address(
&network.b58_pubkey_address_prefix(), &network.b58_pubkey_address_prefix(),
@ -89,7 +94,7 @@ pub async fn decode_transaction(
} }
} }
for output in tx.shielded_outputs.iter() { for output in sapling_bundle.shielded_outputs.iter() {
if let Some((note, pa, memo)) = try_sapling_note_decryption(network, height, &ivk, output) if let Some((note, pa, memo)) = try_sapling_note_decryption(network, height, &ivk, output)
{ {
amount += note.value as i64; // change or self transfer amount += note.value as i64; // change or self transfer
@ -112,7 +117,9 @@ pub async fn decode_transaction(
} }
} }
let fee = u64::from(tx.value_balance); // let fee =
// u64::from() +
// u64::from(tx.sapling_bundle().unwrap().value_balance);
// zaddress must be one of ours // zaddress must be one of ours
// taddress is not always ours // taddress is not always ours
@ -135,7 +142,7 @@ pub async fn decode_transaction(
address, address,
memo, memo,
amount, amount,
fee, // fee,
contacts, contacts,
}; };

View File

@ -1,5 +1,4 @@
use std::convert::TryFrom; use zcash_address::unified::{Address, Container, Receiver};
use zcash_address::unified::{Address, Receiver};
use zcash_address::{FromAddress, Network, ToAddress, UnsupportedAddress, ZcashAddress}; use zcash_address::{FromAddress, Network, ToAddress, UnsupportedAddress, ZcashAddress};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -17,7 +16,7 @@ impl FromAddress for MyReceiver {
} }
fn from_unified(net: Network, data: Address) -> Result<Self, UnsupportedAddress> { fn from_unified(net: Network, data: Address) -> Result<Self, UnsupportedAddress> {
for r in data.receivers().iter() { for r in data.items_as_parsed().iter() {
match r { match r {
Receiver::Sapling(data) => { Receiver::Sapling(data) => {
return Ok(MyReceiver { return Ok(MyReceiver {
@ -39,18 +38,19 @@ impl FromAddress for MyReceiver {
} }
} }
pub fn get_ua(sapling_addr: &str, transparent_addr: &str) -> anyhow::Result<ZcashAddress> { pub fn get_ua(_sapling_addr: &str, _transparent_addr: &str) -> anyhow::Result<ZcashAddress> {
let sapling_addr = ZcashAddress::try_from_encoded(sapling_addr)?; todo!()
let transparent_addr = ZcashAddress::try_from_encoded(transparent_addr)?; // let sapling_addr = ZcashAddress::try_from_encoded(sapling_addr)?;
let receivers: Vec<_> = vec![sapling_addr, transparent_addr] // let transparent_addr = ZcashAddress::try_from_encoded(transparent_addr)?;
.iter() // let receivers: Vec<_> = vec![sapling_addr, transparent_addr]
.map(|r| r.clone().convert::<MyReceiver>().unwrap()) // .iter()
.collect(); // .map(|r| r.clone().convert::<MyReceiver>().unwrap())
let net = receivers.first().unwrap().net.clone(); // .collect();
let receivers: Vec<_> = receivers.iter().map(|r| r.receiver.clone()).collect(); // let net = receivers.first().unwrap().net.clone();
let ua: Address = Address::try_from(receivers)?; // let receivers: Vec<_> = receivers.iter().map(|r| r.receiver.clone()).collect();
let ua_address = ZcashAddress::from_unified(net, ua); // let ua: Address = Address::from_inner(receivers)?;
Ok(ua_address) // let ua_address = ZcashAddress::from_unified(net, ua);
// Ok(ua_address)
} }
pub fn get_sapling(ua_addr: &str) -> anyhow::Result<ZcashAddress> { pub fn get_sapling(ua_addr: &str) -> anyhow::Result<ZcashAddress> {

View File

@ -399,8 +399,8 @@ impl Wallet {
let mut diversifier_index = self.db.get_diversifier(account)?; let mut diversifier_index = self.db.get_diversifier(account)?;
diversifier_index.increment().unwrap(); diversifier_index.increment().unwrap();
let (new_diversifier_index, pa) = fvk let (new_diversifier_index, pa) = fvk
.address(diversifier_index) .find_address(diversifier_index)
.map_err(|_| anyhow::anyhow!("Cannot generate new address"))?; .ok_or_else(|| anyhow::anyhow!("Cannot generate new address"))?;
self.db.store_diversifier(account, &new_diversifier_index)?; self.db.store_diversifier(account, &new_diversifier_index)?;
let pa = encode_payment_address(self.network().hrp_sapling_payment_address(), &pa); let pa = encode_payment_address(self.network().hrp_sapling_payment_address(), &pa);
Ok(pa) Ok(pa)