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

Add means to retrieve more birthday height values #176

Merged
merged 1 commit into from
Dec 10, 2023
Merged
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
10 changes: 10 additions & 0 deletions src/Nerdbank.Zcash/LightWalletClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public LightWalletClient(Uri serverUrl, ZcashNetwork network, string walletPath,
/// The birthday height is the length of the blockchain when the account was created.
/// It serves to reduce initial sync times when this account is imported into another wallet.
/// </remarks>
/// <seealso cref="GetBirthdayHeights"/>
public ulong BirthdayHeight => this.Interop(LightWalletMethods.LightwalletGetBirthdayHeight);

/// <summary>
Expand All @@ -143,6 +144,15 @@ public static ValueTask<ulong> GetLatestBlockHeightAsync(Uri lightWalletServerUr
cancellationToken));
}

/// <summary>
/// Gets the various forms of birthday heights relevant to this account.
/// </summary>
/// <returns>The birthday heights.</returns>
/// <remarks>
/// The resulting struct contains fields which may be influenced by the completeness of the sync to the blockchain.
/// </remarks>
public BirthdayHeights GetBirthdayHeights() => this.Interop(LightWalletMethods.LightwalletGetBirthdayHeights);

/// <inheritdoc cref="GetLatestBlockHeightAsync(Uri, CancellationToken)"/>
public ValueTask<ulong> GetLatestBlockHeightAsync(CancellationToken cancellationToken) => GetLatestBlockHeightAsync(this.serverUrl, cancellationToken);

Expand Down
1 change: 1 addition & 0 deletions src/Nerdbank.Zcash/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Nerdbank.Zcash.LightWalletClient.BirthdayHeight.get -> ulong
Nerdbank.Zcash.LightWalletClient.Dispose() -> void
Nerdbank.Zcash.LightWalletClient.DownloadTransactionsAsync(System.IProgress<Nerdbank.Zcash.LightWalletClient.SyncProgress!>? progress, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Nerdbank.Zcash.LightWalletClient.SyncResult!>!
Nerdbank.Zcash.LightWalletClient.DownloadTransactionsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Nerdbank.Zcash.LightWalletClient.SyncResult!>!
Nerdbank.Zcash.LightWalletClient.GetBirthdayHeights() -> uniffi.LightWallet.BirthdayHeights!
Nerdbank.Zcash.LightWalletClient.GetDownloadedTransactions(uint startingBlock = 0) -> System.Collections.Generic.List<Nerdbank.Zcash.Transaction!>!
Nerdbank.Zcash.LightWalletClient.GetLatestBlockHeightAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask<ulong>
Nerdbank.Zcash.LightWalletClient.GetPoolBalances() -> Nerdbank.Zcash.LightWalletClient.PoolBalances
Expand Down
56 changes: 56 additions & 0 deletions src/Nerdbank.Zcash/RustBindings/LightWallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@
public static extern ulong uniffi_nerdbank_zcash_rust_fn_func_lightwallet_get_birthday_height(ulong @handle,ref RustCallStatus _uniffi_out_err
);

[DllImport("nerdbank_zcash_rust")]
public static extern RustBuffer uniffi_nerdbank_zcash_rust_fn_func_lightwallet_get_birthday_heights(ulong @handle,ref RustCallStatus _uniffi_out_err
);

[DllImport("nerdbank_zcash_rust")]
public static extern ulong uniffi_nerdbank_zcash_rust_fn_func_lightwallet_get_block_height(RustBuffer @serverUri,ref RustCallStatus _uniffi_out_err
);
Expand Down Expand Up @@ -716,6 +720,10 @@
public static extern ushort uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_birthday_height(
);

[DllImport("nerdbank_zcash_rust")]
public static extern ushort uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_birthday_heights(
);

[DllImport("nerdbank_zcash_rust")]
public static extern ushort uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_block_height(
);
Expand Down Expand Up @@ -794,6 +802,12 @@
throw new UniffiContractChecksumException($"uniffi.LightWallet: uniffi bindings expected function `uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_birthday_height` checksum `29297`, library returned `{checksum}`");
}
}
{
var checksum = _UniFFILib.uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_birthday_heights();

Check warning on line 806 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L806

Added line #L806 was not covered by tests
if (checksum != 36095) {
throw new UniffiContractChecksumException($"uniffi.LightWallet: uniffi bindings expected function `uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_birthday_heights` checksum `36095`, library returned `{checksum}`");

Check warning on line 808 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L808

Added line #L808 was not covered by tests
}
}
{
var checksum = _UniFFILib.uniffi_nerdbank_zcash_rust_checksum_func_lightwallet_get_block_height();
if (checksum != 43659) {
Expand Down Expand Up @@ -1036,6 +1050,40 @@



public record BirthdayHeights (
ulong @originalBirthdayHeight,
ulong @birthdayHeight,
ulong? @rebirthHeight
) {

Check warning on line 1057 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L1053-L1057

Added lines #L1053 - L1057 were not covered by tests
}

class FfiConverterTypeBirthdayHeights: FfiConverterRustBuffer<BirthdayHeights> {
public static FfiConverterTypeBirthdayHeights INSTANCE = new FfiConverterTypeBirthdayHeights();

Check warning on line 1061 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L1061

Added line #L1061 was not covered by tests

public override BirthdayHeights Read(BigEndianStream stream) {
return new BirthdayHeights(
FfiConverterUInt64.INSTANCE.Read(stream),
FfiConverterUInt64.INSTANCE.Read(stream),
FfiConverterOptionalUInt64.INSTANCE.Read(stream)
);

Check warning on line 1068 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L1064-L1068

Added lines #L1064 - L1068 were not covered by tests
}

public override int AllocationSize(BirthdayHeights value) {
return
FfiConverterUInt64.INSTANCE.AllocationSize(value.@originalBirthdayHeight) +
FfiConverterUInt64.INSTANCE.AllocationSize(value.@birthdayHeight) +
FfiConverterOptionalUInt64.INSTANCE.AllocationSize(value.@rebirthHeight);

Check warning on line 1075 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L1072-L1075

Added lines #L1072 - L1075 were not covered by tests
}

public override void Write(BirthdayHeights value, BigEndianStream stream) {
FfiConverterUInt64.INSTANCE.Write(value.@originalBirthdayHeight, stream);
FfiConverterUInt64.INSTANCE.Write(value.@birthdayHeight, stream);
FfiConverterOptionalUInt64.INSTANCE.Write(value.@rebirthHeight, stream);
}

Check warning on line 1082 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L1079-L1082

Added lines #L1079 - L1082 were not covered by tests
}



public record Config (
String @serverUri,
ChainType @chainType,
Expand Down Expand Up @@ -1956,6 +2004,14 @@
));
}

/// <exception cref="LightWalletException"></exception>
public static BirthdayHeights LightwalletGetBirthdayHeights(ulong @handle) {
return FfiConverterTypeBirthdayHeights.INSTANCE.Lift(
_UniffiHelpers.RustCallWithError(FfiConverterTypeLightWalletException.INSTANCE, (ref RustCallStatus _status) =>
_UniFFILib.uniffi_nerdbank_zcash_rust_fn_func_lightwallet_get_birthday_heights(FfiConverterUInt64.INSTANCE.Lower(@handle), ref _status)
));

Check warning on line 2012 in src/Nerdbank.Zcash/RustBindings/LightWallet.cs

View check run for this annotation

Codecov / codecov/patch

src/Nerdbank.Zcash/RustBindings/LightWallet.cs#L2009-L2012

Added lines #L2009 - L2012 were not covered by tests
}

/// <exception cref="LightWalletException"></exception>
public static ulong LightwalletGetBlockHeight(String @serverUri) {
return FfiConverterUInt64.INSTANCE.Lift(
Expand Down
23 changes: 16 additions & 7 deletions src/nerdbank-zcash-rust/src/ffi.udl
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,19 @@ dictionary PoolBalances {
};

dictionary UserBalances {
u64 spendable;
u64 immature_change;
u64 minimum_fees;
u64 immature_income;
u64 dust;
u64 incoming;
u64 incoming_dust;
u64 spendable;
u64 immature_change;
u64 minimum_fees;
u64 immature_income;
u64 dust;
u64 incoming;
u64 incoming_dust;
};

dictionary BirthdayHeights{
u64 original_birthday_height;
u64 birthday_height;
u64? rebirth_height;
};

namespace LightWallet {
Expand Down Expand Up @@ -159,4 +165,7 @@ namespace LightWallet {

[Throws=LightWalletError]
UserBalances lightwallet_get_user_balances(u64 handle);

[Throws=LightWalletError]
BirthdayHeights lightwallet_get_birthday_heights(u64 handle);
};
13 changes: 7 additions & 6 deletions src/nerdbank-zcash-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ mod sapling;

use lightwallet::{
last_synced_height, lightwallet_deinitialize, lightwallet_get_balances,
lightwallet_get_birthday_height, lightwallet_get_block_height, lightwallet_get_transactions,
lightwallet_get_user_balances, lightwallet_initialize, lightwallet_initialize_from_disk,
lightwallet_send_check_status, lightwallet_send_to_address, lightwallet_sync,
lightwallet_sync_interrupt, lightwallet_sync_status, ChainType, Config, LightWalletError,
OrchardNote, SaplingNote, SendUpdate, SyncStatus, Transaction, TransactionSendDetail,
UserBalances, WalletInfo,
lightwallet_get_birthday_height, lightwallet_get_birthday_heights,
lightwallet_get_block_height, lightwallet_get_transactions, lightwallet_get_user_balances,
lightwallet_initialize, lightwallet_initialize_from_disk, lightwallet_send_check_status,
lightwallet_send_to_address, lightwallet_sync, lightwallet_sync_interrupt,
lightwallet_sync_status, BirthdayHeights, ChainType, Config, LightWalletError, OrchardNote,
SaplingNote, SendUpdate, SyncStatus, Transaction, TransactionSendDetail, UserBalances,
WalletInfo,
};
use zingolib::lightclient::{PoolBalances, SyncResult};
46 changes: 46 additions & 0 deletions src/nerdbank-zcash-rust/src/lightwallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,49 @@ pub fn lightwallet_get_user_balances(handle: u64) -> Result<UserBalances, LightW
Ok(balances)
})
}

pub struct BirthdayHeights {
/// The original birthday height given at account creation if non-zero,
/// otherwise the block number of the first transaction if any,
/// otherwise the sapling activation height.
pub original_birthday_height: u64,
/// The block number of the first transaction if any,
/// otherwise the sapling activation height.
pub birthday_height: u64,
/// The block number of the oldest unspent note or UTXO, if any.
pub rebirth_height: Option<u64>,
}

pub fn lightwallet_get_birthday_heights(handle: u64) -> Result<BirthdayHeights, LightWalletError> {
let lightclient = get_lightclient(handle)?;
Ok(RT.block_on(async move {
let mut block_number_with_oldest_unspent_note_or_utxo = None;
lightclient
.wallet
.transactions()
.read()
.await
.current
.iter()
.for_each(|(_, tx)| {
if tx.orchard_notes.iter().any(|n| n.spent().is_none())
|| tx.sapling_notes.iter().any(|n| n.spent().is_none())
|| tx.received_utxos.iter().any(|n| n.spent.is_none())
{
if block_number_with_oldest_unspent_note_or_utxo.is_none() {
block_number_with_oldest_unspent_note_or_utxo = Some(tx.block_height);
} else if tx.block_height
< block_number_with_oldest_unspent_note_or_utxo.unwrap()
{
block_number_with_oldest_unspent_note_or_utxo = Some(tx.block_height);
}
}
});

BirthdayHeights {
original_birthday_height: lightclient.wallet.get_birthday().await,
birthday_height: lightclient.wallet.get_first_transaction_block().await,
rebirth_height: block_number_with_oldest_unspent_note_or_utxo.map(u64::from),
}
}))
}