Unified viewing keys

This commit is contained in:
Hanh 2022-11-17 17:13:51 +08:00
parent 25a2e28e74
commit 74a6310784
22 changed files with 195 additions and 124 deletions

View File

@ -44,6 +44,11 @@ typedef struct CResult_u64 {
char *error;
} CResult_u64;
typedef struct CResult {
char value; // dummy
char *error;
} CResult;
void dummy_export(void);
void dart_post_cobject(DartPostCObjectFnType ptr);
@ -68,6 +73,10 @@ struct CResult_u32 new_account(uint8_t coin, char *name, char *data, int32_t ind
void new_sub_account(char *name, int32_t index, uint32_t count);
CResult convert_to_watchonly(uint8_t coin, uint32_t id_account);
struct CResult_____c_char get_backup(uint8_t coin, uint32_t id_account);
struct CResult_____c_char get_address(uint8_t coin, uint32_t id_account, uint8_t ua_type);
void import_transparent_key(uint8_t coin, uint32_t id_account, char *path);
@ -115,7 +124,7 @@ struct CResult_____c_char prepare_multi_payment(uint8_t coin,
struct CResult_____c_char transaction_report(uint8_t coin, char *plan);
struct CResult_____c_char sign(uint8_t coin, uint32_t account, char *tx, int64_t port);
struct CResult_____c_char sign(uint8_t coin, uint32_t account, char *tx, int64_t _port);
struct CResult_____c_char sign_and_broadcast(uint8_t coin, uint32_t account, char *tx_plan);

View File

@ -5,18 +5,23 @@
use crate::coinconfig::CoinConfig;
use crate::db::AccountData;
use crate::key2::decode_key;
use crate::orchard::OrchardKeyBytes;
use crate::taddr::{derive_taddr, derive_tkeys};
use crate::transaction::retrieve_tx_info;
use crate::unified::UnifiedAddressType;
use crate::zip32::derive_zip32;
use crate::{connect_lightwalletd, AccountInfo, KeyPack};
use crate::{AccountInfo, KeyPack};
use anyhow::anyhow;
use bip39::{Language, Mnemonic};
use orchard::keys::{FullViewingKey, Scope};
use rand::rngs::OsRng;
use rand::RngCore;
use serde::Serialize;
use std::fs::File;
use std::io::BufReader;
use zcash_address::unified::{Address as UA, Receiver};
use zcash_address::{ToAddress, ZcashAddress};
use zcash_client_backend::encoding::{decode_extended_full_viewing_key, encode_payment_address};
use zcash_client_backend::keys::UnifiedFullViewingKey;
use zcash_primitives::consensus::Parameters;
/// Create a new account
@ -77,7 +82,7 @@ pub fn new_sub_account(name: &str, index: Option<u32>, count: u32) -> anyhow::Re
fn new_account_with_key(coin: u8, name: &str, key: &str, index: u32) -> anyhow::Result<u32> {
let c = CoinConfig::get(coin);
let (seed, sk, ivk, pa) = decode_key(coin, key, index)?;
let (seed, sk, ivk, pa, ofvk) = decode_key(coin, key, index)?;
let db = c.db()?;
let account = db.get_account_id(&ivk)?;
let account = match account {
@ -89,7 +94,14 @@ fn new_account_with_key(coin: u8, name: &str, key: &str, index: u32) -> anyhow::
db.create_taddr(account)?;
}
if c.chain.has_unified() {
db.create_orchard(account)?;
match ofvk {
Some(fvk) => {
db.store_orchard_fvk(account, &fvk.to_bytes())?;
}
None => {
db.create_orchard(account)?;
}
}
}
db.store_ua_settings(account, false, true, c.chain.has_unified())?;
account
@ -98,6 +110,50 @@ fn new_account_with_key(coin: u8, name: &str, key: &str, index: u32) -> anyhow::
Ok(account)
}
pub fn convert_to_watchonly(coin: u8, id_account: u32) -> anyhow::Result<()> {
let c = CoinConfig::get(coin);
let db = c.db()?;
db.convert_to_watchonly(id_account)?;
Ok(())
}
pub fn get_backup_package(coin: u8, id_account: u32) -> anyhow::Result<Backup> {
let c = CoinConfig::get(coin);
let network = c.chain.network();
let db = c.db()?;
let AccountData {
name,
seed,
sk,
fvk,
aindex,
..
} = db.get_account_info(id_account)?;
let orchard_keys = db.get_orchard(id_account)?;
let fvk = match orchard_keys {
None => fvk,
Some(OrchardKeyBytes { fvk: ofvk, .. }) => {
// orchard sk is not serializable and must derived from seed
let sapling_efvk = decode_extended_full_viewing_key(
network.hrp_sapling_extended_full_viewing_key(),
&fvk,
)
.unwrap();
let sapling_dfvk = sapling_efvk.to_diversifiable_full_viewing_key();
let orchard_fvk = orchard::keys::FullViewingKey::from_bytes(&ofvk);
let ufvk = UnifiedFullViewingKey::new(Some(sapling_dfvk), orchard_fvk).unwrap();
ufvk.encode(network)
}
};
Ok(Backup {
name,
seed,
index: aindex,
sk,
ivk: fvk,
})
}
/// Update the transparent secret key for the given account from a derivation path
///
/// # Arguments
@ -146,8 +202,26 @@ pub fn new_diversified_address() -> anyhow::Result<String> {
.find_address(diversifier_index)
.ok_or_else(|| anyhow::anyhow!("Cannot generate new address"))?;
db.store_diversifier(c.id_account, &new_diversifier_index)?;
let pa = encode_payment_address(c.chain.network().hrp_sapling_payment_address(), &pa);
Ok(pa)
let orchard_keys = db.get_orchard(c.id_account)?;
let address = match orchard_keys {
Some(orchard_keys) => {
let orchard_fvk = FullViewingKey::from_bytes(&orchard_keys.fvk).unwrap();
let index = diversifier_index.0; // any sapling index is fine for orchard
let orchard_address = orchard_fvk.address_at(index, Scope::External);
let unified_address = UA(vec![
Receiver::Sapling(pa.to_bytes()),
Receiver::Orchard(orchard_address.to_raw_address_bytes()),
]);
let address = ZcashAddress::from_unified(
c.chain.network().address_network().unwrap(),
unified_address,
);
address.encode()
}
None => encode_payment_address(c.chain.network().hrp_sapling_payment_address(), &pa),
};
Ok(address)
}
/// Retrieve the transparent balance for the current account from the LWD server
@ -256,7 +330,7 @@ pub fn import_from_zwl(coin: u8, name: &str, data: &str) -> anyhow::Result<()> {
let db = c.db()?;
for (i, key) in sks.iter().enumerate() {
let name = format!("{}-{}", name, i + 1);
let (seed, sk, ivk, pa) = decode_key(coin, key, 0)?;
let (seed, sk, ivk, pa, _ufvk) = decode_key(coin, key, 0)?;
db.store_account(&name, seed.as_deref(), 0, sk.as_deref(), &ivk, &pa)?;
}
Ok(())
@ -351,3 +425,12 @@ pub fn decode_unified_address(coin: u8, address: &str) -> anyhow::Result<String>
let res = crate::decode_unified_address(c.chain.network(), address)?;
Ok(res.to_string())
}
#[derive(Serialize)]
pub struct Backup {
name: String,
seed: Option<String>,
index: u32,
sk: Option<String>,
ivk: String,
}

View File

@ -175,6 +175,23 @@ pub unsafe extern "C" fn new_sub_account(name: *mut c_char, index: i32, count: u
log_error(res)
}
#[no_mangle]
pub unsafe extern "C" fn convert_to_watchonly(coin: u8, id_account: u32) -> CResult<()> {
let res = crate::api::account::convert_to_watchonly(coin, id_account);
to_cresult(res)
}
#[no_mangle]
pub unsafe extern "C" fn get_backup(coin: u8, id_account: u32) -> CResult<*mut c_char> {
let res = || {
let backup = crate::api::account::get_backup_package(coin, id_account)?;
let backup_str = serde_json::to_string(&backup)?;
Ok::<_, anyhow::Error>(backup_str)
};
to_cresult_str(res())
}
#[no_mangle]
pub unsafe extern "C" fn get_address(
coin: u8,
@ -291,6 +308,7 @@ pub async unsafe extern "C" fn get_latest_height() -> CResult<u32> {
to_cresult(height)
}
#[allow(dead_code)]
fn report_progress(progress: Progress, port: i64) {
if port != 0 {
let progress = match progress.end() {
@ -452,7 +470,7 @@ pub async unsafe extern "C" fn sign(
coin: u8,
account: u32,
tx: *mut c_char,
port: i64,
_port: i64,
) -> CResult<*mut c_char> {
from_c_str!(tx);
let res = async {

View File

@ -1,8 +1,8 @@
use crate::api::account::get_unified_address;
use crate::api::recipient::{RecipientMemo, RecipientShort};
use crate::api::recipient::RecipientMemo;
use crate::api::sync::get_latest_height;
pub use crate::broadcast_tx;
use crate::note_selection::{FeeFlat, FeeZIP327, Order, TransactionReport};
use crate::note_selection::{FeeFlat, Order};
use crate::{
build_tx, fetch_utxos, get_secret_keys, note_selection, AccountData, CoinConfig, DbAdapter,
TransactionBuilderConfig, TransactionBuilderError, TransactionPlan, TxBuilderContext,
@ -12,9 +12,10 @@ use rand::rngs::OsRng;
use std::cmp::min;
use std::slice;
use std::str::FromStr;
use zcash_primitives::memo::{Memo, MemoBytes, TextMemo};
use zcash_primitives::memo::{Memo, MemoBytes};
use zcash_primitives::transaction::builder::Progress;
#[allow(dead_code)]
type PaymentProgressCallback = Box<dyn Fn(Progress) + Send + Sync>;
pub async fn build_tx_plan(
@ -29,7 +30,6 @@ pub async fn build_tx_plan(
let (fvk, checkpoint_height) = {
let db = c.db()?;
let AccountData { fvk, .. } = db.get_account_info(account)?;
let anchor_height = last_height.saturating_sub(confirmations);
let checkpoint_height = get_checkpoint_height(&db, last_height, confirmations)?;
(fvk, checkpoint_height)
};

View File

@ -1,6 +1,6 @@
use crate::db::ZMessage;
use crate::{AccountData, CoinConfig};
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::str::FromStr;
use zcash_primitives::memo::Memo;

View File

@ -3,15 +3,13 @@
use crate::coinconfig::CoinConfig;
use crate::scan::{AMProgressCallback, Progress};
use crate::sync::CTree;
use crate::{AccountData, BlockId, ChainError, CompactTxStreamerClient, DbAdapter};
use crate::{AccountData, BlockId, CompactTxStreamerClient, DbAdapter};
use std::sync::Arc;
use tokio::sync::Mutex;
use tonic::transport::Channel;
use tonic::Request;
use zcash_primitives::sapling::Note;
const DEFAULT_CHUNK_SIZE: u32 = 100_000;
/// Asynchronously perform warp sync
/// # Arguments
/// * `coin`: 0 for zcash, 1 for ycash

View File

@ -62,6 +62,7 @@ pub fn init_coin(coin: u8, db_path: &str) -> anyhow::Result<()> {
}
/// Upgrade database schema for given coin and db path
/// Used from ywallet
pub fn migrate_coin(coin: u8, db_path: &str) -> anyhow::Result<()> {
let chain = get_coin_chain(get_coin_type(coin));
DbAdapter::migrate_db(chain.network(), db_path, chain.has_unified())?;

View File

@ -204,6 +204,18 @@ impl DbAdapter {
Ok(())
}
pub fn convert_to_watchonly(&self, id_account: u32) -> anyhow::Result<()> {
self.connection.execute(
"UPDATE accounts SET seed = NULL, sk = NULL WHERE id_account = ?1",
params![id_account],
)?;
self.connection.execute(
"UPDATE orchard_addrs SET sk = NULL WHERE account = ?1",
params![id_account],
)?;
Ok(())
}
pub fn get_sapling_fvks(&self) -> anyhow::Result<Vec<SaplingViewKey>> {
let mut statement = self
.connection
@ -318,17 +330,17 @@ impl DbAdapter {
sapling_tree.write(&mut sapling_bb)?;
connection.execute(
"INSERT INTO blocks(height, hash, timestamp)
VALUES (?1, ?2, ?3)",
VALUES (?1, ?2, ?3) ON CONFLICT DO NOTHING",
params![height, hash, timestamp],
)?;
connection.execute(
"INSERT INTO sapling_tree(height, tree) VALUES (?1, ?2)",
"INSERT INTO sapling_tree(height, tree) VALUES (?1, ?2) ON CONFLICT DO NOTHING",
params![height, &sapling_bb],
)?;
let mut orchard_bb: Vec<u8> = vec![];
orchard_tree.write(&mut orchard_bb)?;
connection.execute(
"INSERT INTO orchard_tree(height, tree) VALUES (?1, ?2)",
"INSERT INTO orchard_tree(height, tree) VALUES (?1, ?2) ON CONFLICT DO NOTHING",
params![height, &orchard_bb],
)?;
log::debug!("-block");
@ -859,6 +871,14 @@ impl DbAdapter {
Ok(())
}
pub fn store_orchard_fvk(&self, account: u32, fvk: &[u8; 96]) -> anyhow::Result<()> {
self.connection.execute(
"INSERT INTO orchard_addrs(account, sk, fvk) VALUES (?1, NULL, ?2) ON CONFLICT DO NOTHING",
params![account, fvk],
)?;
Ok(())
}
pub fn find_account_by_fvk(&self, fvk: &str) -> anyhow::Result<Option<u32>> {
let account = self
.connection
@ -881,10 +901,10 @@ impl DbAdapter {
"SELECT sk, fvk FROM orchard_addrs WHERE account = ?1",
params![account],
|row| {
let sk: Vec<u8> = row.get(0)?;
let sk: Option<Vec<u8>> = row.get(0)?;
let fvk: Vec<u8> = row.get(1)?;
Ok(OrchardKeyBytes {
sk: sk.try_into().unwrap(),
sk: sk.map(|sk| sk.try_into().unwrap()),
fvk: fvk.try_into().unwrap(),
})
},

View File

@ -49,12 +49,14 @@ macro_rules! accumulate_scalar {
};
}
#[allow(dead_code)]
pub fn pedersen_hash(depth: u8, left: &Hash, right: &Hash) -> Hash {
let p = pedersen_hash_inner(depth, left, right);
p.to_affine().get_u().to_repr()
}
#[allow(dead_code)]
pub fn pedersen_hash_inner(depth: u8, left: &Hash, right: &Hash) -> ExtendedPoint {
let mut result = ExtendedPoint::identity();
let mut bitoffset = 0;
@ -116,6 +118,7 @@ pub fn pedersen_hash_inner(depth: u8, left: &Hash, right: &Hash) -> ExtendedPoin
result
}
#[allow(dead_code)]
fn generator_multiplication(
acc: &Fr,
gens: &[ExtendedNielsPoint],

View File

@ -1,9 +1,11 @@
use crate::coinconfig::CoinConfig;
use anyhow::anyhow;
use bip39::{Language, Mnemonic, Seed};
use zcash_client_backend::encoding::{
decode_extended_full_viewing_key, decode_extended_spending_key,
encode_extended_full_viewing_key, encode_extended_spending_key, encode_payment_address,
};
use zcash_client_backend::keys::UnifiedFullViewingKey;
use zcash_primitives::consensus::{Network, Parameters};
use zcash_primitives::zip32::{ChildIndex, ExtendedFullViewingKey, ExtendedSpendingKey};
@ -11,26 +13,44 @@ pub fn decode_key(
coin: u8,
key: &str,
index: u32,
) -> anyhow::Result<(Option<String>, Option<String>, String, String)> {
) -> anyhow::Result<(
Option<String>,
Option<String>,
String,
String,
Option<orchard::keys::FullViewingKey>,
)> {
let c = CoinConfig::get(coin);
let network = c.chain.network();
let res = if let Ok(mnemonic) = Mnemonic::from_phrase(key, Language::English) {
let (sk, ivk, pa) = derive_secret_key(network, &mnemonic, index)?;
Ok((Some(key.to_string()), Some(sk), ivk, pa))
Ok((Some(key.to_string()), Some(sk), ivk, pa, None))
} else if let Ok(sk) =
decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), key)
{
let (ivk, pa) = derive_viewing_key(network, &sk)?;
Ok((None, Some(key.to_string()), ivk, pa))
Ok((None, Some(key.to_string()), ivk, pa, None))
} else if let Ok(fvk) =
decode_extended_full_viewing_key(network.hrp_sapling_extended_full_viewing_key(), key)
{
let pa = derive_address(network, &fvk)?;
Ok((None, None, key.to_string(), pa))
Ok((None, None, key.to_string(), pa, None))
} else if let Ok(ufvk) = UnifiedFullViewingKey::decode(network, key) {
let sapling_dfvk = ufvk
.sapling()
.ok_or(anyhow!("UFVK must contain a sapling key"))?;
let sapling_efvk =
ExtendedFullViewingKey::from_diversifiable_full_viewing_key(&sapling_dfvk);
let key = encode_extended_full_viewing_key(
network.hrp_sapling_extended_full_viewing_key(),
&sapling_efvk,
);
let pa = derive_address(network, &sapling_efvk)?;
let orchard_key = ufvk.orchard().cloned();
Ok((None, None, key, pa, orchard_key))
} else {
Err(anyhow::anyhow!("Not a valid key"))
};
// TODO: Accept UA viewing key
res
}
@ -49,6 +69,9 @@ pub fn is_valid_key(coin: u8, key: &str) -> i8 {
{
return 2;
}
if UnifiedFullViewingKey::decode(network, key).is_ok() {
return 3;
}
// TODO: Accept UA viewing key
-1
}

View File

@ -57,7 +57,7 @@
pub mod lw_rpc;
// Mainnet
const LWD_URL: &str = "https://mainnet.lightwalletd.com:9067";
// const LWD_URL: &str = "https://mainnet.lightwalletd.com:9067";
// pub const LWD_URL: &str = "https://lwdv3.zecwallet.co";
// pub const LWD_URL: &str = "http://lwd.hanh.me:9067";
// pub const LWD_URL: &str = "http://127.0.0.1:9067";

View File

@ -10,15 +10,13 @@ use rocket::response::Responder;
use rocket::serde::{json::Json, Deserialize, Serialize};
use rocket::{response, Request, Response, State};
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufReader, Read};
use std::sync::Mutex;
use thiserror::Error;
use warp_api_ffi::api::payment_uri::PaymentURI;
use warp_api_ffi::api::recipient::{Recipient, RecipientMemo, RecipientShort};
use warp_api_ffi::{
build_tx, get_best_server, get_secret_keys, AccountData, AccountInfo, AccountRec, CoinConfig,
KeyPack, RaptorQDrops, TransactionBuilderConfig, TransactionPlan, Tx, TxBuilderContext, TxRec,
build_tx, get_secret_keys, AccountData, AccountInfo, AccountRec, CoinConfig, KeyPack,
RaptorQDrops, TransactionPlan, TxRec,
};
lazy_static! {

View File

@ -10,7 +10,6 @@ use std::str::FromStr;
pub use utxo::fetch_utxos;
use crate::api::recipient::Recipient;
use optimize::{allocate_funds, fill, group_orders, outputs_for_change, select_inputs, sum_utxos};
use thiserror::Error;
use ua::decode;
use zcash_primitives::memo::Memo;
@ -37,6 +36,7 @@ mod utxo;
pub const MAX_ATTEMPTS: usize = 10;
#[allow(dead_code)]
pub fn recipients_to_orders(recipients: &[Recipient]) -> Result<Vec<Order>> {
let orders: Result<Vec<_>> = recipients
.iter()

View File

@ -1,13 +1,10 @@
use super::decode;
use super::types::*;
use crate::coinconfig::get_prover;
use crate::note_selection::fee::FeeFlat;
use crate::note_selection::{build_tx_plan, fetch_utxos};
use crate::orchard::{get_proving_key, OrchardHasher, ORCHARD_ROOTS};
use crate::sapling::{SaplingHasher, SAPLING_ROOTS};
use crate::sync::tree::TreeCheckpoint;
use crate::sync::Witness;
use crate::{broadcast_tx, init_coin, set_active, set_coin_lwd_url, AccountData, CoinConfig, Hash};
use crate::{AccountData, CoinConfig};
use anyhow::anyhow;
use jubjub::Fr;
use orchard::builder::Builder as OrchardBuilder;
@ -16,7 +13,6 @@ use orchard::keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey};
use orchard::note::Nullifier;
use orchard::value::NoteValue;
use orchard::{Address, Anchor, Bundle};
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};
use ripemd::{Digest, Ripemd160};
use secp256k1::{All, PublicKey, Secp256k1, SecretKey};
@ -25,7 +21,6 @@ use std::str::FromStr;
use zcash_client_backend::encoding::decode_extended_spending_key;
use zcash_primitives::consensus::{BlockHeight, BranchId, Network, Parameters};
use zcash_primitives::legacy::TransparentAddress;
use zcash_primitives::memo::MemoBytes;
use zcash_primitives::merkle_tree::IncrementalWitness;
use zcash_primitives::sapling::prover::TxProver;
use zcash_primitives::sapling::{Diversifier, Node, PaymentAddress, Rseed};
@ -292,7 +287,7 @@ pub fn get_secret_keys(coin: u8, account: u32) -> anyhow::Result<SecretKeys> {
let orchard_sk = db
.get_orchard(account)?
.map(|ob| SpendingKey::from_bytes(ob.sk).unwrap());
.and_then(|ob| ob.sk.map(|sk| SpendingKey::from_bytes(sk).unwrap()));
let sk = SecretKeys {
transparent: transparent_sk,
@ -301,68 +296,3 @@ pub fn get_secret_keys(coin: u8, account: u32) -> anyhow::Result<SecretKeys> {
};
Ok(sk)
}
#[tokio::test]
async fn dummy_test() {
let _ = env_logger::try_init();
init_coin(0, "./zec.db").unwrap();
set_coin_lwd_url(0, "http://127.0.0.1:9067");
let c = CoinConfig::get(0);
log::info!("Start test");
let height = {
let db = c.db.as_ref().unwrap();
let db = db.lock().unwrap();
db.get_last_sync_height().unwrap().unwrap()
};
log::info!("Height {}", height);
const REGTEST_CHANGE: &str = "uregtest1mxy5wq2n0xw57nuxa4lqpl358zw4vzyfgadsn5jungttmqcv6nx6cpx465dtpzjzw0vprjle4j4nqqzxtkuzm93regvgg4xce0un5ec6tedquc469zjhtdpkxz04kunqqyasv4rwvcweh3ue0ku0payn29stl2pwcrghyzscrrju9ar57rn36wgz74nmynwcyw27rjd8yk477l97ez8";
let mut config = TransactionBuilderConfig::new(REGTEST_CHANGE);
log::info!("Getting signing keys");
let keys = get_secret_keys(0, 1).unwrap();
log::info!("Building signing context");
let context = TxBuilderContext::from_height(0, height).unwrap();
log::info!("Getting available notes");
let utxos = fetch_utxos(0, 1, height).await.unwrap();
// let notes: Vec<_> = utxos.into_iter().filter(|utxo| utxo.source.pool() == Pool::Orchard).collect();
log::info!("Preparing outputs");
let mut orders = vec![];
orders.push(Order::new(
1,
"tmWXoSBwPoCjJCNZjw4P7heoVMcT2Ronrqq",
10000,
MemoBytes::empty(),
));
orders.push(Order::new(2, "zregtestsapling1qzy9wafd2axnenul6t6wav76dys6s8uatsq778mpmdvmx4k9myqxsd9m73aqdgc7gwnv53wga4j", 20000, MemoBytes::empty()));
orders.push(Order::new(3, "uregtest1mzt5lx5s5u8kczlfr82av97kjckmfjfuq8y9849h6cl9chhdekxsm6r9dklracflqwplrnfzm5rucp5txfdm04z5myrde8y3y5rayev8", 30000, MemoBytes::empty()));
orders.push(Order::new(4, "uregtest1yvucqfqnmq5ldc6fkvuudlsjhxg56hxph9ymmcnmpzpywd752ym8sr5l5d24wqn4enz3gakk6alf5hlpw2cjs3jjrcdae3nksrefyum5x400f9gs3ak9yllcr8czhrlnjufuuy7n5mh", 40000, MemoBytes::empty()));
orders.push(Order::new(5, "uregtest1wqgc0cm50a7a647qrdglgj62fl40q8njsrcfkt2mzlsmj979rdmsdwuysypc6ewxjxz0zc48kmm35jwx4q6c4fgqwkmmqyhwlep4n2hc0229vf6cahcnesr38y7gyzfx6pa8zg9jvv9", 50000, MemoBytes::empty()));
orders.push(Order::new(6, "uregtest1usu9eyxgqu48sa8lqug6ccjc7vcam3mt3a5t7jvyxj7pq5dgdtkjgkqzsyh9pfeav9970xddp2c9h5x44drwnz4f0zwc894k3vt380g6kfsg9j9fmnpljye9r56d94njsv40uaam392xvmky2v38dh3yhayz44z6xv402slujuhwy3mg", 60000, MemoBytes::empty()));
orders.push(Order::new(7, "uregtest1mxy5wq2n0xw57nuxa4lqpl358zw4vzyfgadsn5jungttmqcv6nx6cpx465dtpzjzw0vprjle4j4nqqzxtkuzm93regvgg4xce0un5ec6tedquc469zjhtdpkxz04kunqqyasv4rwvcweh3ue0ku0payn29stl2pwcrghyzscrrju9ar57rn36wgz74nmynwcyw27rjd8yk477l97ez8", 70000, MemoBytes::empty()));
log::info!("Building tx plan");
let tx_plan =
build_tx_plan::<FeeFlat>("", 0, &Hash::default(), &utxos, &mut orders, &config).unwrap();
log::info!("Plan: {}", serde_json::to_string(&tx_plan).unwrap());
log::info!("Building tx");
let tx = build_tx(c.chain.network(), &keys, &tx_plan, OsRng).unwrap();
println!("{}", hex::encode(&tx));
}
#[tokio::test]
async fn submit_tx() {
let _ = env_logger::try_init();
init_coin(0, "./zec.db").unwrap();
set_coin_lwd_url(0, "http://127.0.0.1:9067");
set_active(0);
let tx = "";
let r = broadcast_tx(&hex::decode(tx).unwrap()).await.unwrap();
log::info!("{}", r);
}

View File

@ -5,8 +5,7 @@ use crate::note_selection::TransactionBuilderError::TxTooComplex;
use crate::note_selection::{TransactionBuilderError, MAX_ATTEMPTS};
use crate::Hash;
use anyhow::anyhow;
use std::str::FromStr;
use zcash_primitives::memo::{Memo, MemoBytes};
use zcash_primitives::memo::MemoBytes;
pub fn sum_utxos(utxos: &[UTXO]) -> Result<PoolAllocation> {
let mut pool = PoolAllocation::default();

View File

@ -1,5 +1,4 @@
use crate::note_selection::types::{TransactionOutput, TransactionReport};
use crate::note_selection::{Destination, Source};
use crate::TransactionPlan;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;

View File

@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize};
use serde_hex::{SerHex, Strict};
use serde_with::serde_as;
use zcash_client_backend::encoding::{encode_payment_address, AddressCodec};
use zcash_params::coin::CoinType::Zcash;
use zcash_primitives::consensus::{Network, Parameters};
use zcash_primitives::legacy::TransparentAddress;
use zcash_primitives::memo::MemoBytes;

View File

@ -3,7 +3,7 @@ use orchard::keys::{FullViewingKey, Scope, SpendingKey};
use orchard::Address;
pub struct OrchardKeyBytes {
pub sk: [u8; 32],
pub sk: Option<[u8; 32]>,
pub fvk: [u8; 96],
}
@ -21,7 +21,7 @@ pub fn derive_orchard_keys(coin_type: u32, seed: &str, account_index: u32) -> Or
let sk = SpendingKey::from_zip32_seed(seed.as_bytes(), coin_type, account_index).unwrap();
let fvk = FullViewingKey::from(&sk);
OrchardKeyBytes {
sk: sk.to_bytes().clone(),
sk: Some(sk.to_bytes().clone()),
fvk: fvk.to_bytes(),
}
}

View File

@ -3,11 +3,8 @@ use crate::db::ReceivedNote;
use crate::sync::{
CompactOutputBytes, DecryptedNote, Node, OutputPosition, TrialDecrypter, ViewKey,
};
use crate::{CompactTx, DbAdapterBuilder};
use orchard::keys::Scope;
use crate::CompactTx;
use orchard::note_encryption::OrchardDomain;
use zcash_note_encryption;
use zcash_params::coin::CoinType;
use zcash_primitives::consensus::{BlockHeight, Parameters};
#[derive(Clone, Debug)]

View File

@ -91,11 +91,13 @@ pub struct RecipientSummary {
pub amount: u64,
}
#[allow(dead_code)]
pub struct TxBuilder {
pub tx: Tx,
coin_type: CoinType,
}
#[allow(dead_code)]
impl TxBuilder {
pub fn new(coin_type: CoinType, height: u32) -> Self {
TxBuilder {

View File

@ -3,7 +3,7 @@ use crate::db::AccountViewKey;
use serde::Serialize;
use crate::chain::{download_chain, DecryptNode};
use crate::transaction::{get_transaction_details, retrieve_tx_info, GetTransactionDetailRequest};
use crate::transaction::get_transaction_details;
use crate::{
connect_lightwalletd, ChainError, CoinConfig, CompactBlock, CompactSaplingOutput, CompactTx,
DbAdapterBuilder,
@ -224,12 +224,6 @@ async fn sync_async_inner<'a>(
Ok(())
}
pub async fn latest_height(ld_url: &str) -> anyhow::Result<u32> {
let mut client = connect_lightwalletd(ld_url).await?;
let height = get_latest_height(&mut client).await?;
Ok(height)
}
#[allow(dead_code)]
// test function
pub fn trial_decrypt_one(

View File

@ -4,13 +4,11 @@ use crate::unified::orchard_as_unified;
use crate::{AccountData, CoinConfig, CompactTxStreamerClient, DbAdapter, Hash, TxFilter};
use orchard::keys::{FullViewingKey, IncomingViewingKey, OutgoingViewingKey, Scope};
use orchard::note_encryption::OrchardDomain;
use orchard::value::ValueCommitment;
use serde::Serialize;
use std::collections::HashMap;
use std::convert::TryFrom;
use tonic::transport::Channel;
use tonic::Request;
use zcash_address::{ToAddress, ZcashAddress};
use zcash_client_backend::encoding::{
decode_extended_full_viewing_key, encode_payment_address, encode_transparent_address,
};