v1.0
This commit is contained in:
parent
3432ea15bd
commit
f1d948c0f6
153
src/builder.rs
153
src/builder.rs
|
@ -216,18 +216,19 @@ impl Builder<Witness, CTreeBuilder> for WitnessBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
let right = if depth != 0 && !context.first_block {
|
||||
context.right
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// println!("D {}", depth);
|
||||
// println!("O {:?}", offset.map(|r| hex::encode(r.repr)));
|
||||
// println!("R {:?}", right.map(|r| hex::encode(r.repr)));
|
||||
// for c in commitments.iter() {
|
||||
// println!("{}", hex::encode(c.repr));
|
||||
// }
|
||||
let right = if depth != 0 && !context.first_block {
|
||||
context.right
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let p1 = self.p + 1;
|
||||
// println!("P {} P1 {} S {} AS {}", self.p, p1, context.start, context.adjusted_start(&right));
|
||||
let has_p1 = p1 >= context.adjusted_start(&right) && p1 < context.start + commitments.len();
|
||||
if has_p1 {
|
||||
let p1 = CTreeBuilder::get(commitments, p1 - context.adjusted_start(&right), &right);
|
||||
|
@ -342,6 +343,7 @@ impl BlockProcessor {
|
|||
}
|
||||
|
||||
pub fn add_nodes(&mut self, nodes: &mut [Node], new_witnesses: &[Witness]) {
|
||||
if nodes.is_empty() { return }
|
||||
self.prev_witnesses.extend_from_slice(new_witnesses);
|
||||
let (t, ws) = advance_tree(
|
||||
&self.prev_tree,
|
||||
|
@ -349,13 +351,19 @@ impl BlockProcessor {
|
|||
nodes,
|
||||
self.first_block,
|
||||
);
|
||||
self.first_block = false;
|
||||
self.prev_tree = t;
|
||||
self.prev_witnesses = ws;
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> (CTree, Vec<Witness>) {
|
||||
let (t, ws) = advance_tree(&self.prev_tree, &self.prev_witnesses, &mut [], false);
|
||||
(t, ws)
|
||||
if self.first_block {
|
||||
(self.prev_tree, self.prev_witnesses)
|
||||
}
|
||||
else {
|
||||
let (t, ws) = advance_tree(&self.prev_tree, &self.prev_witnesses, &mut [], false);
|
||||
(t, ws)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,6 +377,121 @@ mod tests {
|
|||
use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness};
|
||||
use zcash_primitives::sapling::Node;
|
||||
|
||||
fn make_nodes(p: usize, len: usize) -> Vec<Node> {
|
||||
let nodes: Vec<_> = (p..p+len).map(|v| {
|
||||
let mut bb = [0u8; 32];
|
||||
bb[0..8].copy_from_slice(&v.to_be_bytes());
|
||||
Node::new(bb)
|
||||
}).collect();
|
||||
nodes
|
||||
}
|
||||
|
||||
fn make_witnesses(p: usize, len: usize) -> Vec<Witness> {
|
||||
let witnesses: Vec<_> = (p..p+len).map(|v| {
|
||||
Witness::new(v, 0, None)
|
||||
}).collect();
|
||||
witnesses
|
||||
}
|
||||
|
||||
fn update_witnesses1(tree: &mut CommitmentTree<Node>, ws: &mut Vec<IncrementalWitness<Node>>, nodes: &[Node]) {
|
||||
for n in nodes.iter() {
|
||||
tree.append(n.clone()).unwrap();
|
||||
for w in ws.iter_mut() {
|
||||
w.append(n.clone()).unwrap();
|
||||
}
|
||||
let w = IncrementalWitness::<Node>::from_tree(&tree);
|
||||
ws.push(w);
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_witness(w1: &IncrementalWitness<Node>, w2: &Witness) {
|
||||
let mut bb1: Vec<u8> = vec![];
|
||||
w1.write(&mut bb1).unwrap();
|
||||
let mut bb2: Vec<u8> = vec![];
|
||||
w2.write(&mut bb2).unwrap();
|
||||
|
||||
if bb1 != bb2 {
|
||||
print_witness(&w1);
|
||||
print_witness2(&w2);
|
||||
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
let v = [0u8; 32];
|
||||
let mut bp = BlockProcessor::new(&CTree::new(), &[]);
|
||||
let mut nodes = [Node::new(v)];
|
||||
bp.add_nodes(&mut [], &[]);
|
||||
bp.add_nodes(&mut nodes, &[Witness::new(0, 0, None)]);
|
||||
bp.finalize();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bp_1run() {
|
||||
for n1 in 0..=40 {
|
||||
for n2 in 0..=40 {
|
||||
println!("{} {}", n1, n2);
|
||||
let mut bp = BlockProcessor::new(&CTree::new(), &[]);
|
||||
let mut tree1: CommitmentTree<Node> = CommitmentTree::empty();
|
||||
let mut ws1: Vec<IncrementalWitness<Node>> = vec![];
|
||||
|
||||
let mut nodes = make_nodes(0, n1);
|
||||
update_witnesses1(&mut tree1, &mut ws1, &nodes);
|
||||
bp.add_nodes(&mut nodes, &make_witnesses(0, n1));
|
||||
|
||||
let mut nodes = make_nodes(n1, n2);
|
||||
update_witnesses1(&mut tree1, &mut ws1, &nodes);
|
||||
bp.add_nodes(&mut nodes, &make_witnesses(n1, n2));
|
||||
|
||||
let (_, ws2) = bp.finalize();
|
||||
|
||||
for (i, (w1, w2)) in ws1.iter().zip(ws2.iter()).enumerate() {
|
||||
println!("Compare {}", i);
|
||||
compare_witness(w1, w2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bp_2run() {
|
||||
for n1 in 0..=40 {
|
||||
for n2 in 0..=40 {
|
||||
println!("{} {}", n1, n2);
|
||||
let mut tree1: CommitmentTree<Node> = CommitmentTree::empty();
|
||||
let mut ws1: Vec<IncrementalWitness<Node>> = vec![];
|
||||
let mut tree2 = CTree::new();
|
||||
let mut ws2: Vec<Witness> = vec![];
|
||||
|
||||
{
|
||||
let mut bp = BlockProcessor::new(&tree2, &ws2);
|
||||
let mut nodes = make_nodes(0, n1);
|
||||
update_witnesses1(&mut tree1, &mut ws1, &nodes);
|
||||
bp.add_nodes(&mut nodes, &make_witnesses(0, n1));
|
||||
let (t2, w2) = bp.finalize();
|
||||
tree2 = t2;
|
||||
ws2 = w2;
|
||||
}
|
||||
|
||||
{
|
||||
let mut bp = BlockProcessor::new(&tree2, &ws2);
|
||||
let mut nodes = make_nodes(n1, n2);
|
||||
update_witnesses1(&mut tree1, &mut ws1, &nodes);
|
||||
bp.add_nodes(&mut nodes, &make_witnesses(n1, n2));
|
||||
let (_t2, w2) = bp.finalize();
|
||||
ws2 = w2;
|
||||
}
|
||||
|
||||
for (i, (w1, w2)) in ws1.iter().zip(ws2.iter()).enumerate() {
|
||||
println!("Compare {}", i);
|
||||
compare_witness(w1, w2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_advance_tree_equal_blocks() {
|
||||
for num_nodes in 1..=10 {
|
||||
|
@ -380,8 +503,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_advance_tree_unequal_blocks() {
|
||||
for num_nodes1 in 1..=30 {
|
||||
for num_nodes2 in 1..=30 {
|
||||
for num_nodes1 in 0..=30 {
|
||||
for num_nodes2 in 0..=30 {
|
||||
println!("TESTING {} {}", num_nodes1, num_nodes2);
|
||||
let (t, ws) = test_advance_tree_helper(num_nodes1, 1, 100.0, None);
|
||||
test_advance_tree_helper(num_nodes2, 1, 100.0, Some((t, ws)));
|
||||
|
@ -390,8 +513,16 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_advance_tree() {
|
||||
test_advance_tree_helper(100, 50, 1.0, None);
|
||||
fn test_small_blocks() {
|
||||
for num_nodes1 in 1..=30 {
|
||||
println!("TESTING {}", num_nodes1);
|
||||
test_advance_tree_helper(num_nodes1, 1, 100.0, None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tree() {
|
||||
test_advance_tree_helper(4, 1, 100.0, None);
|
||||
|
||||
// test_advance_tree_helper(2, 10, 100.0);
|
||||
// test_advance_tree_helper(1, 40, 100.0);
|
||||
|
|
11
src/chain.rs
11
src/chain.rs
|
@ -19,10 +19,11 @@ use zcash_primitives::transaction::components::sapling::CompactOutputDescription
|
|||
use zcash_primitives::zip32::ExtendedFullViewingKey;
|
||||
|
||||
const MAX_CHUNK: u32 = 50000;
|
||||
pub const LWD_URL: &str = "https://mainnet.lightwalletd.com:9067";
|
||||
// pub const LWD_URL: &str = "https://testnet.lightwalletd.com:9067";
|
||||
// pub const LWD_URL: &str = "http://lwd.hanh.me:9067";
|
||||
// pub const LWD_URL: &str = "https://lwdv3.zecwallet.co";
|
||||
pub const LWD_URL: &str = "http://127.0.0.1:9067";
|
||||
// pub const LWD_URL: &str = "http://127.0.0.1:9067";
|
||||
|
||||
pub async fn get_latest_height(
|
||||
client: &mut CompactTxStreamerClient<Channel>,
|
||||
|
@ -211,7 +212,13 @@ pub async fn send_transaction(
|
|||
.send_transaction(Request::new(raw_tx))
|
||||
.await?
|
||||
.into_inner();
|
||||
Ok(rep.error_message)
|
||||
let code = rep.error_code;
|
||||
if code == 0 {
|
||||
Ok(rep.error_message)
|
||||
}
|
||||
else {
|
||||
Err(anyhow::anyhow!(rep.error_message))
|
||||
}
|
||||
}
|
||||
|
||||
/* Using the IncrementalWitness */
|
||||
|
|
|
@ -98,19 +98,20 @@ impl Witness {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(position: usize, id_note: u32, mut reader: R) -> std::io::Result<Self> {
|
||||
pub fn read<R: Read>(id_note: u32, mut reader: R) -> std::io::Result<Self> {
|
||||
let tree = CTree::read(&mut reader)?;
|
||||
let filled = Vector::read(&mut reader, |r| Node::read(r))?;
|
||||
let cursor = Optional::read(&mut reader, |r| CTree::read(r))?;
|
||||
|
||||
let witness = Witness {
|
||||
position,
|
||||
let mut witness = Witness {
|
||||
position: 0,
|
||||
id_note,
|
||||
tree,
|
||||
filled,
|
||||
cursor: cursor.unwrap_or_else(CTree::new),
|
||||
note: None,
|
||||
};
|
||||
witness.position = witness.tree.get_position() - 1;
|
||||
|
||||
Ok(witness)
|
||||
}
|
||||
|
|
50
src/db.rs
50
src/db.rs
|
@ -11,7 +11,7 @@ use zcash_primitives::zip32::ExtendedFullViewingKey;
|
|||
pub const DEFAULT_DB_PATH: &str = "zec.db";
|
||||
|
||||
pub struct DbAdapter {
|
||||
connection: Connection,
|
||||
pub connection: Connection,
|
||||
}
|
||||
|
||||
pub struct ReceivedNote {
|
||||
|
@ -25,6 +25,7 @@ pub struct ReceivedNote {
|
|||
}
|
||||
|
||||
pub struct SpendableNote {
|
||||
pub id: u32,
|
||||
pub note: Note,
|
||||
pub diversifier: Diversifier,
|
||||
pub witness: IncrementalWitness<Node>,
|
||||
|
@ -40,6 +41,7 @@ impl DbAdapter {
|
|||
self.connection.execute(
|
||||
"CREATE TABLE IF NOT EXISTS accounts (
|
||||
id_account INTEGER PRIMARY KEY,
|
||||
seed TEXT NOT NULL,
|
||||
sk TEXT NOT NULL UNIQUE,
|
||||
ivk TEXT NOT NULL,
|
||||
address TEXT NOT NULL)",
|
||||
|
@ -95,11 +97,11 @@ impl DbAdapter {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn store_account(&self, sk: &str, ivk: &str, address: &str) -> anyhow::Result<()> {
|
||||
pub fn store_account(&self, seed: &str, sk: &str, ivk: &str, address: &str) -> anyhow::Result<()> {
|
||||
self.connection.execute(
|
||||
"INSERT INTO accounts(sk, ivk, address) VALUES (?1, ?2, ?3)
|
||||
"INSERT INTO accounts(seed, sk, ivk, address) VALUES (?1, ?2, ?3, ?4)
|
||||
ON CONFLICT DO NOTHING",
|
||||
params![sk, ivk, address],
|
||||
params![seed, sk, ivk, address],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -235,7 +237,7 @@ impl DbAdapter {
|
|||
|
||||
pub fn get_balance(&self) -> anyhow::Result<u64> {
|
||||
let balance: Option<i64> = self.connection.query_row(
|
||||
"SELECT SUM(value) FROM received_notes WHERE spent IS NULL",
|
||||
"SELECT SUM(value) FROM received_notes WHERE spent IS NULL OR spent = 0",
|
||||
NO_PARAMS,
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
@ -291,12 +293,11 @@ impl DbAdapter {
|
|||
Some((height, tree)) => {
|
||||
let tree = CTree::read(&*tree)?;
|
||||
let mut statement = self.connection.prepare(
|
||||
"SELECT id_note, position, witness FROM sapling_witnesses w, received_notes n WHERE w.height = ?1 AND w.note = n.id_note AND n.spent IS NULL")?;
|
||||
"SELECT id_note, witness FROM sapling_witnesses w, received_notes n WHERE w.height = ?1 AND w.note = n.id_note AND (n.spent IS NULL OR n.spent = 0)")?;
|
||||
let ws = statement.query_map(params![height], |row| {
|
||||
let id_note: u32 = row.get(0)?;
|
||||
let position: u32 = row.get(1)?;
|
||||
let witness: Vec<u8> = row.get(2)?;
|
||||
Ok(Witness::read(position as usize, id_note, &*witness).unwrap())
|
||||
let witness: Vec<u8> = row.get(1)?;
|
||||
Ok(Witness::read(id_note, &*witness).unwrap())
|
||||
})?;
|
||||
let mut witnesses: Vec<Witness> = vec![];
|
||||
for w in ws {
|
||||
|
@ -311,7 +312,7 @@ impl DbAdapter {
|
|||
pub fn get_nullifiers(&self) -> anyhow::Result<HashMap<Nf, u32>> {
|
||||
let mut statement = self
|
||||
.connection
|
||||
.prepare("SELECT id_note, nf FROM received_notes WHERE spent IS NULL")?;
|
||||
.prepare("SELECT id_note, nf FROM received_notes WHERE spent IS NULL OR spent = 0")?;
|
||||
let nfs_res = statement.query_map(NO_PARAMS, |row| {
|
||||
let id_note: u32 = row.get(0)?;
|
||||
let nf_vec: Vec<u8> = row.get(1)?;
|
||||
|
@ -331,7 +332,7 @@ impl DbAdapter {
|
|||
pub fn get_nullifier_amounts(&self) -> anyhow::Result<HashMap<Vec<u8>, u64>> {
|
||||
let mut statement = self
|
||||
.connection
|
||||
.prepare("SELECT value, nf FROM received_notes WHERE spent IS NULL")?;
|
||||
.prepare("SELECT value, nf FROM received_notes WHERE spent IS NULL OR spent = 0")?;
|
||||
let nfs_res = statement.query_map(NO_PARAMS, |row| {
|
||||
let amount: i64 = row.get(0)?;
|
||||
let nf: Vec<u8> = row.get(1)?;
|
||||
|
@ -352,15 +353,17 @@ impl DbAdapter {
|
|||
fvk: &ExtendedFullViewingKey,
|
||||
) -> anyhow::Result<Vec<SpendableNote>> {
|
||||
let mut statement = self.connection.prepare(
|
||||
"SELECT diversifier, value, rcm, witness FROM received_notes r, sapling_witnesses w WHERE spent IS NULL
|
||||
"SELECT id_note, diversifier, value, rcm, witness FROM received_notes r, sapling_witnesses w WHERE spent IS NULL
|
||||
AND w.height = (
|
||||
SELECT MAX(height) FROM sapling_witnesses WHERE height <= ?1
|
||||
) AND r.id_note = w.note")?;
|
||||
let notes = statement.query_map(params![anchor_height], |row| {
|
||||
let diversifier: Vec<u8> = row.get(0)?;
|
||||
let value: i64 = row.get(1)?;
|
||||
let rcm: Vec<u8> = row.get(2)?;
|
||||
let witness: Vec<u8> = row.get(3)?;
|
||||
let id_note: u32 = row.get(0)?;
|
||||
|
||||
let diversifier: Vec<u8> = row.get(1)?;
|
||||
let value: i64 = row.get(2)?;
|
||||
let rcm: Vec<u8> = row.get(3)?;
|
||||
let witness: Vec<u8> = row.get(4)?;
|
||||
|
||||
let mut diversifer_bytes = [0u8; 11];
|
||||
diversifer_bytes.copy_from_slice(&diversifier);
|
||||
|
@ -374,6 +377,7 @@ impl DbAdapter {
|
|||
let pa = fvk.fvk.vk.to_payment_address(diversifier).unwrap();
|
||||
let note = pa.create_note(value as u64, rseed).unwrap();
|
||||
Ok(SpendableNote {
|
||||
id: id_note,
|
||||
note,
|
||||
diversifier,
|
||||
witness,
|
||||
|
@ -397,6 +401,20 @@ impl DbAdapter {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_seed(&self, account: u32) -> anyhow::Result<String> {
|
||||
log::debug!("+get_seed");
|
||||
let ivk = self.connection.query_row(
|
||||
"SELECT seed FROM accounts WHERE id_account = ?1",
|
||||
params![account],
|
||||
|row| {
|
||||
let ivk: String = row.get(0)?;
|
||||
Ok(ivk)
|
||||
},
|
||||
)?;
|
||||
log::debug!("-get_seed");
|
||||
Ok(ivk)
|
||||
}
|
||||
|
||||
pub fn get_sk(&self, account: u32) -> anyhow::Result<String> {
|
||||
log::debug!("+get_sk");
|
||||
let ivk = self.connection.query_row(
|
||||
|
|
|
@ -3,7 +3,7 @@ use zcash_primitives::consensus::Network;
|
|||
#[path = "generated/cash.z.wallet.sdk.rpc.rs"]
|
||||
pub mod lw_rpc;
|
||||
|
||||
pub const NETWORK: Network = Network::TestNetwork;
|
||||
pub const NETWORK: Network = Network::MainNetwork;
|
||||
|
||||
mod builder;
|
||||
mod chain;
|
||||
|
@ -28,3 +28,4 @@ pub use crate::lw_rpc::*;
|
|||
pub use crate::mempool::MemPool;
|
||||
pub use crate::scan::{latest_height, scan_all, sync_async};
|
||||
pub use crate::wallet::{Wallet, WalletBalance, DEFAULT_ACCOUNT};
|
||||
pub use crate::print::*;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use bip39::{Language, Mnemonic};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use sync::{DbAdapter, Wallet, DEFAULT_ACCOUNT, ChainError};
|
||||
use sync::{DbAdapter, Wallet, DEFAULT_ACCOUNT, ChainError, Witness, print_witness2};
|
||||
use rusqlite::NO_PARAMS;
|
||||
|
||||
const DB_NAME: &str = "zec.db";
|
||||
|
||||
|
@ -29,11 +30,11 @@ async fn test() -> anyhow::Result<()> {
|
|||
println!("REORG");
|
||||
}
|
||||
}
|
||||
let tx_id = wallet
|
||||
.send_payment(DEFAULT_ACCOUNT, &address, 50000)
|
||||
.await
|
||||
.unwrap();
|
||||
println!("TXID = {}", tx_id);
|
||||
// let tx_id = wallet
|
||||
// .send_payment(DEFAULT_ACCOUNT, &address, 50000)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// println!("TXID = {}", tx_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -50,18 +51,53 @@ fn test_make_wallet() {
|
|||
#[allow(dead_code)]
|
||||
fn test_rewind() {
|
||||
let mut db = DbAdapter::new(DB_NAME).unwrap();
|
||||
db.trim_to_height(1460000).unwrap();
|
||||
db.trim_to_height(1466520).unwrap();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn test_get_balance() {
|
||||
let db = DbAdapter::new(DB_NAME).unwrap();
|
||||
let balance = db.get_balance().unwrap();
|
||||
println!("Balance = {}", (balance as f64) / 100_000_000.0);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn test_invalid_witness() {
|
||||
dotenv::dotenv().unwrap();
|
||||
env_logger::init();
|
||||
|
||||
println!("BAD");
|
||||
let witness = dotenv::var("WITNESS").unwrap();
|
||||
let w = Witness::read(0, &*hex::decode(&witness).unwrap()).unwrap();
|
||||
print_witness2(&w);
|
||||
|
||||
println!("GOOD");
|
||||
let witness = dotenv::var("WITNESS2").unwrap();
|
||||
let w = Witness::read(0, &*hex::decode(&witness).unwrap()).unwrap();
|
||||
print_witness2(&w);
|
||||
}
|
||||
|
||||
fn w() {
|
||||
let db = DbAdapter::new("zec.db").unwrap();
|
||||
// let w_b: Vec<u8> = db.connection.query_row("SELECT witness FROM sapling_witnesses WHERE note = 66 AND height = 1466097", NO_PARAMS, |row| row.get(0)).unwrap();
|
||||
// let w = Witness::read(0, &*w_b).unwrap();
|
||||
// print_witness2(&w);
|
||||
//
|
||||
let w_b: Vec<u8> = db.connection.query_row("SELECT witness FROM sapling_witnesses WHERE note = 66 AND height = 1466200", NO_PARAMS, |row| row.get(0)).unwrap();
|
||||
let w = Witness::read(0, &*w_b).unwrap();
|
||||
print_witness2(&w);
|
||||
|
||||
println!("GOOD");
|
||||
let witness = dotenv::var("WITNESS2").unwrap();
|
||||
let w = Witness::read(0, &*hex::decode(&witness).unwrap()).unwrap();
|
||||
print_witness2(&w);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
init();
|
||||
// test_invalid_witness()
|
||||
// test_rewind();
|
||||
test().unwrap();
|
||||
test_get_balance();
|
||||
// test_get_balance();
|
||||
// w();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use zcash_client_backend::encoding::decode_extended_full_viewing_key;
|
|||
use zcash_primitives::consensus::{NetworkUpgrade, Parameters};
|
||||
use zcash_primitives::sapling::Node;
|
||||
use zcash_primitives::zip32::ExtendedFullViewingKey;
|
||||
use std::panic;
|
||||
|
||||
pub async fn scan_all(fvks: &[ExtendedFullViewingKey]) -> anyhow::Result<()> {
|
||||
let decrypter = DecryptNode::new(fvks.to_vec());
|
||||
|
@ -214,6 +215,7 @@ pub async fn sync_async(
|
|||
if !nodes.is_empty() {
|
||||
bp.add_nodes(&mut nodes, &witnesses);
|
||||
}
|
||||
// println!("NOTES = {}", nodes.len());
|
||||
|
||||
if let Some(block) = blocks.0.last() {
|
||||
let mut hash = [0u8; 32];
|
||||
|
@ -276,6 +278,9 @@ pub async fn sync_async(
|
|||
}
|
||||
Err(err) => {
|
||||
log::info!("Sync error = {}", err);
|
||||
if err.is_panic() {
|
||||
panic::resume_unwind(err.into_panic());
|
||||
}
|
||||
anyhow::bail!("Join Error");
|
||||
},
|
||||
}
|
||||
|
|
|
@ -76,6 +76,10 @@ impl Wallet {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_seed(&self, account: u32) -> anyhow::Result<String> {
|
||||
self.db.get_seed(account)
|
||||
}
|
||||
|
||||
pub fn has_account(&self, account: u32) -> anyhow::Result<bool> {
|
||||
self.db.has_account(account)
|
||||
}
|
||||
|
@ -84,7 +88,7 @@ impl Wallet {
|
|||
let sk = get_secret_key(&seed).unwrap();
|
||||
let vk = get_viewing_key(&sk).unwrap();
|
||||
let pa = get_address(&vk).unwrap();
|
||||
self.db.store_account(&sk, &vk, &pa)?;
|
||||
self.db.store_account(seed, &sk, &vk, &pa)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -195,7 +199,8 @@ impl Wallet {
|
|||
|
||||
let mut amount = target_amount;
|
||||
amount += DEFAULT_FEE;
|
||||
for n in notes {
|
||||
let mut selected_note: Vec<u32> = vec![];
|
||||
for n in notes.iter() {
|
||||
if amount.is_positive() {
|
||||
let a = amount.min(
|
||||
Amount::from_u64(n.note.value)
|
||||
|
@ -203,12 +208,15 @@ impl Wallet {
|
|||
);
|
||||
amount -= a;
|
||||
let merkle_path = n.witness.path().context("Invalid Merkle Path")?;
|
||||
let mut witness_bytes: Vec<u8> = vec![];
|
||||
n.witness.write(&mut witness_bytes)?;
|
||||
builder.add_sapling_spend(
|
||||
skey.clone(),
|
||||
n.diversifier,
|
||||
n.note.clone(),
|
||||
merkle_path,
|
||||
)?;
|
||||
selected_note.push(n.id);
|
||||
}
|
||||
}
|
||||
if amount.is_positive() {
|
||||
|
@ -237,6 +245,10 @@ impl Wallet {
|
|||
let mut client = connect_lightwalletd().await?;
|
||||
let tx_id = send_transaction(&mut client, &raw_tx, last_height).await?;
|
||||
log::info!("Tx ID = {}", tx_id);
|
||||
|
||||
for id_note in selected_note.iter() {
|
||||
self.db.mark_spent(*id_note, 0)?;
|
||||
}
|
||||
Ok(tx_id)
|
||||
}
|
||||
|
||||
|
|
BIN
zec.db-journal
BIN
zec.db-journal
Binary file not shown.
Loading…
Reference in New Issue