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

Remove kruft #1182

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -3232,10 +3232,17 @@ mod slow {
// 5 Shield transparent and sapling to orchard
// # Expected Fees:
// - legacy: 10_000
// - 317: 5_000 for transparent + 10_000 for orchard + 10_000 for sapling == 25_000
from_inputs::shield(&pool_migration_client, &[PoolType::Transparent], None)
.await
.unwrap();
// - 317: disallowed (not *precisely*) BY 317...
from_inputs::shield(
&pool_migration_client,
&[
PoolType::Transparent,
PoolType::Shielded(ShieldedProtocol::Sapling),
],
None,
)
.await
.unwrap();
bump_and_check_pmc!(o: 50_000 s: 0 t: 0);

// 6 self send orchard to orchard
Expand Down
2 changes: 2 additions & 0 deletions zingolib/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `do_save_to_buffer`
- `do_save_to_buffer_sync`
- `fix_spent_at_height`
- `TransactionRecord::net_spent`
- `TransactionRecord::iget_transparent_value_spent()`
2 changes: 1 addition & 1 deletion zingolib/src/lightclient/deprecated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ impl LightClient {

// Get the total transparent value received in this transaction
// Again we see the assumption that utxos are incoming.
let net_transparent_value = total_transparent_received as i64 - wallet_transaction.get_transparent_value_spent() as i64;
let net_transparent_value = total_transparent_received as i64 - wallet_transaction.total_transparent_value_spent as i64;
let address = wallet_transaction.transparent_outputs.iter().map(|utxo| utxo.address.clone()).collect::<Vec<String>>().join(",");
if net_transparent_value > 0 {
if let Some(transaction) = consumer_notes_by_tx.iter_mut().find(|transaction| transaction["txid"] == txid.to_string()) {
Expand Down
231 changes: 133 additions & 98 deletions zingolib/src/lightclient/describe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! These functions can be called by consumer to learn about the LightClient.
use ::orchard::note_encryption::OrchardDomain;
use json::{object, JsonValue};
use orchard::note_encryption::OrchardDomain;
use sapling_crypto::note_encryption::SaplingDomain;
use std::collections::HashMap;
use tokio::runtime::Runtime;
Expand All @@ -20,15 +20,25 @@ use crate::{
error::ZingoLibError,
wallet::{
data::{
finsight, summaries::ValueTransfer, summaries::ValueTransferKind, OutgoingTxData,
TransactionRecord,
finsight,
summaries::{ValueTransfer, ValueTransferKind},
OutgoingTxData, TransactionRecord,
},
keys::address_from_pubkeyhash,
notes::{query::OutputQuery, OutputInterface},
transaction_records_by_id::TransactionRecordsById,
LightWallet,
},
};

#[allow(missing_docs)]
#[derive(Debug, thiserror::Error)]
pub enum ValueTransferRecordingError {
#[error("Fee was not calculable because of error: {0}")]
FeeCalculationError(String),
#[error("Nonempty outgoing_tx_data in non outgoing transaction: {0}")]
IncoherentOutgoing(String), // TODO: Make this the actual data
}
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 Down Expand Up @@ -261,7 +271,11 @@ impl LightClient {

/// Provides a list of value transfers related to this capability
pub async fn list_txsummaries(&self) -> Vec<ValueTransfer> {
self.list_txsummaries_and_capture_errors().await.0
}
async fn list_txsummaries_and_capture_errors(&self) -> (Vec<ValueTransfer>, Vec<String>) {
let mut summaries: Vec<ValueTransfer> = Vec::new();
let mut errors: Vec<String> = Vec::new();
let transaction_records_by_id = &self
.wallet
.transaction_context
Expand All @@ -271,7 +285,14 @@ impl LightClient {
.transaction_records_by_id;

for (txid, transaction_record) in transaction_records_by_id.iter() {
LightClient::tx_summary_matcher(&mut summaries, *txid, transaction_record);
if let Err(value_recording_error) = LightClient::record_value_transfers(
&mut summaries,
*txid,
transaction_record,
transaction_records_by_id,
) {
errors.push(value_recording_error.to_string())
};

if let Ok(tx_fee) =
transaction_records_by_id.calculate_transaction_fee(transaction_record)
Expand All @@ -294,7 +315,7 @@ impl LightClient {
};
}
summaries.sort_by_key(|summary| summary.block_height);
summaries
(summaries, errors)
}

/// TODO: Add Doc Comment Here!
Expand Down Expand Up @@ -375,104 +396,113 @@ impl LightClient {
pub fn get_server_uri(&self) -> http::Uri {
self.config.get_lightwalletd_uri()
}

fn tx_summary_matcher(
// Given a transaction write down ValueTransfer information in a Summary list
fn record_value_transfers(
summaries: &mut Vec<ValueTransfer>,
txid: TxId,
transaction_md: &TransactionRecord,
) {
transaction_record: &TransactionRecord,
transaction_records: &TransactionRecordsById,
) -> Result<(), ValueTransferRecordingError> {
let is_received = match transaction_records.transaction_is_received(transaction_record) {
Ok(received) => received,
Err(fee_error) => {
return Err(ValueTransferRecordingError::FeeCalculationError(
fee_error.to_string(),
))
}
};

let (block_height, datetime, price, pending) = (
transaction_md.status.get_height(),
transaction_md.datetime,
transaction_md.price,
!transaction_md.status.is_confirmed(),
transaction_record.status.get_height(),
transaction_record.datetime,
transaction_record.price,
!transaction_record.status.is_confirmed(),
);
match (
transaction_md.is_outgoing_transaction(),
transaction_md.is_incoming_transaction(),
) {
// This transaction is entirely composed of what we consider
// to be 'change'. We just make a Fee transfer and move on
(false, false) => (),
// All received funds were change, this is a normal send
(true, false) => {
for OutgoingTxData {
recipient_address,
value,
memo,
recipient_ua,
} in &transaction_md.outgoing_tx_data
{
if let Ok(recipient_address) = ZcashAddress::try_from_encoded(
recipient_ua.as_ref().unwrap_or(recipient_address),
) {
let memos = if let Memo::Text(textmemo) = memo {
vec![textmemo.clone()]
} else {
vec![]
};
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Sent {
recipient_address,
amount: *value,
},
memos,
price,
txid,
pending,
});
}
}
if is_received {
if !transaction_record.outgoing_tx_data.is_empty() {
return Err(ValueTransferRecordingError::IncoherentOutgoing(
"transaction_record.outgoing_tx_data".to_string(), // TODO: Make into real data.
));
}
// No funds spent, this is a normal receipt
(false, true) => {
for received_transparent in transaction_md.transparent_outputs.iter() {
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Transparent,
amount: received_transparent.value,
},
memos: vec![],
price,
txid,
pending,
});
}
for received_sapling in transaction_md.sapling_notes.iter() {
let memos = if let Some(Memo::Text(textmemo)) = &received_sapling.memo {
vec![textmemo.clone()]
} else {
vec![]
};
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Shielded(ShieldedProtocol::Sapling),
amount: received_sapling.value(),
},
memos,
price,
txid,
pending,
});
}
for received_orchard in transaction_md.orchard_notes.iter() {
let memos = if let Some(Memo::Text(textmemo)) = &received_orchard.memo {
// This transaction is *NOT* outgoing, I *THINK* the TransactionRecord
// only write down outputs that are relevant to this Capability
// so that means everything we know about is Received.
for received_transparent in transaction_record.transparent_outputs.iter() {
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Transparent,
amount: received_transparent.value,
},
memos: vec![],
price,
txid,
pending,
});
}
for received_sapling in transaction_record.sapling_notes.iter() {
let memos = if let Some(Memo::Text(textmemo)) = &received_sapling.memo {
vec![textmemo.clone()]
} else {
vec![]
};
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Shielded(ShieldedProtocol::Sapling),
amount: received_sapling.value(),
},
memos,
price,
txid,
pending,
});
}
for received_orchard in transaction_record.orchard_notes.iter() {
let memos = if let Some(Memo::Text(textmemo)) = &received_orchard.memo {
vec![textmemo.clone()]
} else {
vec![]
};
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Shielded(ShieldedProtocol::Orchard),
amount: received_orchard.value(),
},
memos,
price,
txid,
pending,
});
}
} else {
// These Value Transfers create resources that are controlled by
// a Capability other than the creator
for OutgoingTxData {
recipient_address,
value,
memo,
recipient_ua,
} in &transaction_record.outgoing_tx_data
{
if let Ok(recipient_address) = ZcashAddress::try_from_encoded(
recipient_ua.as_ref().unwrap_or(recipient_address),
) {
let memos = if let Memo::Text(textmemo) = memo {
vec![textmemo.clone()]
} else {
vec![]
};
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::Received {
pool_type: PoolType::Shielded(ShieldedProtocol::Orchard),
amount: received_orchard.value(),
kind: ValueTransferKind::Sent {
recipient_address,
amount: *value,
},
memos,
price,
Expand All @@ -481,19 +511,23 @@ impl LightClient {
});
}
}
// We spent funds, and received funds as non-change. This is most likely a send-to-self,
// TODO: Figure out what kind of special-case handling we want for these
(true, true) => {
// If the transaction is outgoing, and there are notes in:
// - sapling notes
// - orchard notes
// then they were sent to self
if !transaction_record.sapling_notes.is_empty()
|| !transaction_record.orchard_notes.is_empty()
{
summaries.push(ValueTransfer {
block_height,
datetime,
kind: ValueTransferKind::SendToSelf,
memos: transaction_md
memos: transaction_record
.sapling_notes
.iter()
.filter_map(|sapling_note| sapling_note.memo.clone())
.chain(
transaction_md
transaction_record
.orchard_notes
.iter()
.filter_map(|orchard_note| orchard_note.memo.clone()),
Expand All @@ -511,7 +545,8 @@ impl LightClient {
pending,
});
}
};
}
Ok(())
}

async fn list_sapling_notes(
Expand Down Expand Up @@ -573,7 +608,7 @@ impl LightClient {
if !all_notes && orch_note_metadata.is_spent() {
None
} else {
let address = LightWallet::note_address::<orchard::note_encryption::OrchardDomain>(&self.config.chain, orch_note_metadata, &self.wallet.wallet_capability());
let address = LightWallet::note_address::<OrchardDomain>(&self.config.chain, orch_note_metadata, &self.wallet.wallet_capability());
let spendable = transaction_metadata.status.is_confirmed_after_or_at(&anchor_height) && orch_note_metadata.spent.is_none() && orch_note_metadata.pending_spent.is_none();

let created_block:u32 = transaction_metadata.status.get_height().into();
Expand Down
22 changes: 21 additions & 1 deletion zingolib/src/wallet/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,27 @@ pub struct OutgoingTxData {
/// recipient_address?
pub recipient_ua: Option<String>,
}
impl std::fmt::Display for OutgoingTxData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Format the recipient address or unified address if provided.
let address_display = if let Some(ref ua) = self.recipient_ua {
format!("Unified Address: {}", ua)
} else {
format!("Recipient Address: {}", self.recipient_address)
};
let memo_text = if let Memo::Text(mt) = self.memo.clone() {
mt.to_string()
} else {
"not a text memo".to_string()
};

write!(
f,
"{}\nValue: {}\nMemo: {}",
address_display, self.value, memo_text
)
}
}

impl PartialEq for OutgoingTxData {
fn eq(&self, other: &Self) -> bool {
Expand All @@ -297,7 +318,6 @@ impl PartialEq for OutgoingTxData {
&& self.memo == other.memo
}
}

impl OutgoingTxData {
/// TODO: Add Doc Comment Here!
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
Expand Down
Loading
Loading