Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backported sub ua #1629

Merged
merged 7 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
460 changes: 246 additions & 214 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions libtonode-tests/tests/chain_generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use zingolib::testutils::{

proptest::proptest! {
#![proptest_config(proptest::test_runner::Config::with_cases(4))]
#[ignore = "hangs"]
#[test]
fn single_sufficient_send_libtonode(send_value in 0..50_000u64, change_value in 0..10_000u64, sender_protocol in 1..2, receiver_pool in 0..2) {
Runtime::new().unwrap().block_on(async {
Expand Down
12 changes: 7 additions & 5 deletions libtonode-tests/tests/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ mod fast {
lightclient::from_inputs,
},
wallet::data::summaries::{SelfSendValueTransfer, SentValueTransfer, ValueTransferKind},
UAReceivers,
};

use super::*;
Expand Down Expand Up @@ -995,7 +996,7 @@ mod fast {
for code in ["o", "zo", "z"] {
recipient.do_new_address(code).await.unwrap();
}
let addresses = recipient.do_addresses().await;
let addresses = recipient.do_addresses(UAReceivers::All).await;
let address_5000_nonememo_tuples = addresses
.members()
.map(|ua| (ua["address"].as_str().unwrap(), 5_000, None))
Expand Down Expand Up @@ -1058,7 +1059,7 @@ mod fast {

//Verify that 1 increment of diversification with a tz receiver set produces uregtest1m8un60u... UA
let new_address = recipient1.do_new_address("tzo").await.unwrap();
let ua_index_1 = recipient1.do_addresses().await[1].clone();
let ua_index_1 = recipient1.do_addresses(UAReceivers::All).await[1].clone();
let ua_address_index_1 = ua_index_1["address"].clone().to_string();
assert_eq!(&new_address[0].to_string(), &ua_address_index_1);
let sapling_index_1 = ua_index_1["receivers"]["sapling"].clone().to_string();
Expand Down Expand Up @@ -1272,6 +1273,7 @@ mod slow {
assert_transaction_summary_exists,
lightclient::{from_inputs, get_fees_paid_by_client},
};
use zingolib::UAReceivers;

use super::*;

Expand Down Expand Up @@ -1676,7 +1678,7 @@ mod slow {
// let list = recipient.do_list_transactions().await;
// assert_eq!(list[0]["block_height"].as_u64().unwrap(), 4);
// assert_eq!(
// recipient.do_addresses().await[0]["receivers"]["transparent"].to_string(),
// recipient.do_addresses(UAReceivers::All).await[0]["receivers"]["transparent"].to_string(),
// recipient_taddr
// );
// assert_eq!(list[0]["amount"].as_u64().unwrap(), value);
Expand Down Expand Up @@ -2453,7 +2455,7 @@ mod slow {

// // 3. Check the balance is correct, and we received the incoming transaction from ?outside?
// let b = recipient.do_balance().await;
// let addresses = recipient.do_addresses().await;
// let addresses = recipient.do_addresses(UAReceivers::All).await;
// assert_eq!(b.sapling_balance.unwrap(), value);
// assert_eq!(b.unverified_sapling_balance.unwrap(), 0);
// assert_eq!(b.spendable_sapling_balance.unwrap(), value);
Expand Down Expand Up @@ -3093,7 +3095,7 @@ mod slow {
.await;
let seed_of_recipient_restored = {
recipient_restored.do_sync(true).await.unwrap();
let restored_addresses = recipient_restored.do_addresses().await;
let restored_addresses = recipient_restored.do_addresses(UAReceivers::All).await;
assert_eq!(
&restored_addresses[0]["address"],
&original_recipient_address
Expand Down
1 change: 1 addition & 0 deletions libtonode-tests/tests/sync.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use tempfile::TempDir;
use testvectors::seeds::HOSPITAL_MUSEUM_SEED;
use zingo_netutils::GrpcConnector;
use zingo_sync::sync::sync;

Check failure on line 4 in libtonode-tests/tests/sync.rs

View workflow job for this annotation

GitHub Actions / test / Build test artifacts

failed to resolve: use of undeclared crate or module `zingo_sync`
use zingolib::{
config::{construct_lightwalletd_uri, load_clientconfig, DEFAULT_LIGHTWALLETD_SERVER},
get_base_address_macro,
Expand Down Expand Up @@ -49,6 +49,7 @@
dbg!(&wallet.sync_state);
}

#[ignore = "hangs"]
#[tokio::test]
async fn sync_test() {
tracing_subscriber::fmt().init();
Expand Down
179 changes: 110 additions & 69 deletions zingolib/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl Command for ParseAddressCommand {
indoc! {r#"
Parse an address
Usage:
parse_address [address]
parse_address <address>

Example
parse_address tmSwk8bjXdCgBvpS8Kybk5nUyE21QFcDqre
Expand All @@ -242,71 +242,91 @@ impl Command for ParseAddressCommand {
}

fn exec(&self, args: &[&str], _lightclient: &LightClient) -> String {
match args.len() {
1 => json::stringify_pretty(
[
crate::config::ChainType::Mainnet,
crate::config::ChainType::Testnet,
crate::config::ChainType::Regtest(
crate::config::RegtestNetwork::all_upgrades_active(),
),
]
.iter()
.find_map(|chain| Address::decode(chain, args[0]).zip(Some(chain)))
.map_or(
object! {
"status" => "Invalid address",
"chain_name" => json::JsonValue::Null,
"address_kind" => json::JsonValue::Null,
},
|(recipient_address, chain_name)| {
let chain_name_string = match chain_name {
crate::config::ChainType::Mainnet => "main",
crate::config::ChainType::Testnet => "test",
crate::config::ChainType::Regtest(_) => "regtest",
};
match recipient_address {
Address::Sapling(_) => object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "sapling",
},
Address::Transparent(_) => object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "transparent",
},
Address::Unified(ua) => {
let mut receivers_available = vec![];
if ua.orchard().is_some() {
receivers_available.push("orchard")
}
if ua.sapling().is_some() {
receivers_available.push("sapling")
}
if ua.transparent().is_some() {
receivers_available.push("transparent")
}
object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "unified",
"receivers_available" => receivers_available,
}
}
Address::Tex(_) => {
object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "tex",
}
}
}
},
if args.len() > 1 {
zancas marked this conversation as resolved.
Show resolved Hide resolved
return self.help().to_string();
}
fn make_decoded_chain_pair(
address: &str,
) -> Option<(
zcash_client_backend::address::Address,
crate::config::ChainType,
)> {
[
crate::config::ChainType::Mainnet,
crate::config::ChainType::Testnet,
crate::config::ChainType::Regtest(
crate::config::RegtestNetwork::all_upgrades_active(),
),
4,
),
_ => self.help().to_string(),
]
.iter()
.find_map(|chain| Address::decode(chain, address).zip(Some(*chain)))
}
if let Some((recipient_address, chain_name)) = make_decoded_chain_pair(args[0]) {
let chain_name_string = match chain_name {
crate::config::ChainType::Mainnet => "main",
crate::config::ChainType::Testnet => "test",
crate::config::ChainType::Regtest(_) => "regtest",
};
match recipient_address {
Address::Sapling(_) => object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "sapling",
}
.to_string(),
Address::Transparent(_) => object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "transparent",
}
.to_string(),
Address::Tex(_) => object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "tex",
}
.to_string(),
Address::Unified(ua) => {
let mut receivers_available = vec![];
if ua.orchard().is_some() {
receivers_available.push("orchard")
}
if ua.sapling().is_some() {
receivers_available.push("sapling")
}
if ua.transparent().is_some() {
receivers_available.push("transparent")
}
if ua.orchard().is_some()
&& ua.sapling().is_some()
&& ua.transparent().is_some()
zancas marked this conversation as resolved.
Show resolved Hide resolved
{
object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "unified",
"receivers_available" => receivers_available,
"only_orchard_ua" => zcash_keys::address::UnifiedAddress::from_receivers(ua.orchard().cloned(), None, None).expect("To construct UA").encode(&chain_name),
}
.to_string()
} else {
object! {
"status" => "success",
"chain_name" => chain_name_string,
"address_kind" => "unified",
"receivers_available" => receivers_available,
}
.to_string()
}
}
}
} else {
object! {
"status" => "Invalid address",
"chain_name" => json::JsonValue::Null,
"address_kind" => json::JsonValue::Null,
}
.to_string()
}
}
}
Expand Down Expand Up @@ -702,9 +722,9 @@ struct AddressCommand {}
impl Command for AddressCommand {
fn help(&self) -> &'static str {
indoc! {r#"
List current addresses in the wallet
List current addresses in the wallet, shielded excludes t-addresses.
Usage:
address
addresses [shielded|orchard]

"#}
}
Expand All @@ -713,8 +733,29 @@ impl Command for AddressCommand {
"List all addresses in the wallet"
}

fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
RT.block_on(async move { lightclient.do_addresses().await.pretty(2) })
fn exec(&self, args: &[&str], lightclient: &LightClient) -> String {
use crate::lightclient::describe::UAReceivers;
match args.len() {
0 => RT.block_on(
async move { lightclient.do_addresses(UAReceivers::All).await.pretty(2) },
),
1 => match args[0] {
"shielded" => RT.block_on(async move {
lightclient
.do_addresses(UAReceivers::Shielded)
.await
.pretty(2)
}),
"orchard" => RT.block_on(async move {
lightclient
.do_addresses(UAReceivers::Orchard)
.await
.pretty(2)
}),
_ => self.help().to_string(),
},
_ => self.help().to_string(),
}
}
}

Expand Down
1 change: 1 addition & 0 deletions zingolib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! Zingo backend code base
//! Use this high level API to do things like submit transactions to the zcash blockchain

pub use lightclient::describe::UAReceivers;
#[macro_use]
extern crate rust_embed;

Expand Down
7 changes: 5 additions & 2 deletions zingolib/src/lightclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,10 @@ async fn get_recent_median_price_from_gemini() -> Result<f64, PriceFetchError> {

#[cfg(test)]
mod tests {
use crate::config::{ChainType, RegtestNetwork, ZingoConfig};
use crate::{
config::{ChainType, RegtestNetwork, ZingoConfig},
lightclient::describe::UAReceivers,
};
use testvectors::seeds::CHIMNEY_BETTER_SEED;
use tokio::runtime::Runtime;

Expand Down Expand Up @@ -730,7 +733,7 @@ mod tests {

// The first t address and z address should be derived
Runtime::new().unwrap().block_on(async move {
let addresses = lc.do_addresses().await;
let addresses = lc.do_addresses(UAReceivers::All).await;
assert_eq!(
"zregtestsapling1etnl5s47cqves0g5hk2dx5824rme4xv4aeauwzp4d6ys3qxykt5sw5rnaqh9syxry8vgxr7x3x4"
.to_string(),
Expand Down
49 changes: 37 additions & 12 deletions zingolib/src/lightclient/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ pub enum ValueTransferRecordingError {
fn some_sum(a: Option<u64>, b: Option<u64>) -> Option<u64> {
a.xor(b).or_else(|| a.zip(b).map(|(v, u)| v + u))
}
pub enum UAReceivers {
Orchard,
Shielded,
All,
}
impl LightClient {
/// Uses a query to select all notes across all transactions with specific properties and sum them
pub async fn query_sum_value(&self, include_notes: OutputQuery) -> u64 {
Expand All @@ -53,7 +58,7 @@ impl LightClient {

/// TODO: Add Doc Comment Here!
// todo use helpers
pub async fn do_addresses(&self) -> JsonValue {
pub async fn do_addresses(&self, subset: UAReceivers) -> JsonValue {
let mut objectified_addresses = Vec::new();
for address in self
.wallet
Expand All @@ -63,18 +68,35 @@ impl LightClient {
.addresses()
.iter()
{
let encoded_ua = address.encode(&self.config.chain);
let transparent = address
let local_address = match subset {
UAReceivers::Orchard => zcash_keys::address::UnifiedAddress::from_receivers(
address.orchard().copied(),
None,
None,
)
.expect("To create a new address."),
UAReceivers::Shielded => zcash_keys::address::UnifiedAddress::from_receivers(
address.orchard().copied(),
address.sapling().copied(),
None,
)
.expect("To create a new address."),
UAReceivers::All => address.clone(),
};
let encoded_ua = local_address.encode(&self.config.chain);
let transparent = local_address
.transparent()
.map(|taddr| address_from_pubkeyhash(&self.config, *taddr));
objectified_addresses.push(object! {
"address" => encoded_ua,
"receivers" => object!(
"transparent" => transparent,
"sapling" => address.sapling().map(|z_addr| encode_payment_address(self.config.chain.hrp_sapling_payment_address(), z_addr)),
"orchard_exists" => address.orchard().is_some(),
objectified_addresses.push(
object!{
"address" => encoded_ua,
"receivers" => object!(
"transparent" => transparent,
"sapling" => local_address.sapling().map(|z_addr| encode_payment_address(self.config.chain.hrp_sapling_payment_address(), z_addr)),
"orchard_exists" => local_address.orchard().is_some()
)
}
)
})
}
JsonValue::Array(objectified_addresses)
}
Expand Down Expand Up @@ -426,8 +448,11 @@ impl LightClient {
}

/// TODO: doc comment
pub async fn value_transfers_json_string(&self) -> String {
json::JsonValue::from(self.sorted_value_transfers(true).await).pretty(2)
pub async fn value_transfers_json_string(&self, recent_vts_to_retrieve: usize) -> String {
let sorted_vts = self.sorted_value_transfers(true).await;
let total = sorted_vts.len();
let subset = &sorted_vts.as_slice()[..recent_vts_to_retrieve];
object! {"value_transfers" => subset, "total" => total}.to_string()
}

/// Provides a list of transaction summaries related to this wallet in order of blockheight
Expand Down
Loading
Loading