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 support for transparent-source-only (TEX) addresses #1257

Merged
merged 56 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2fae4bb
ZIP 320 implementation.
daira Jun 22, 2024
0f3de63
Apply documentation suggestions from code review.
daira Jun 22, 2024
549fe0b
In `reserve_next_n_ephemeral_addresses`, exclude addresses observed in
daira Jun 22, 2024
eb88461
Address review comment: `EphemeralIvk` should not implement `Incoming…
daira Jun 22, 2024
c6520cf
Change the protobuf schema to explicitly specify whether a `ChangeValue`
daira Jun 22, 2024
2f521d7
If a change memo is supplied, it should not be used in the second step
daira Jun 23, 2024
0f49dae
`mark_ephemeral_address_as_mined` now prefers setting `mined_in_tx` to
daira Jun 23, 2024
637ae92
Add a migration test for the `ephemeral_addresses` migration.
daira Jun 23, 2024
994f6ff
Change type of `n` in `reserve_next_n_ephemeral_addresses`.
daira Jun 24, 2024
25f07da
Add a constraint on the range of `ephemeral_addresses(address_index)`.
daira Jun 24, 2024
e164b59
Move most ephemeral address index handling into helper functions in
daira Jun 24, 2024
914acb5
Move most remaining code for wallet support of ephemeral addresses into
daira Jun 24, 2024
745054b
`find_account_for_transparent_output` now searches unreserved ephemeral
daira Jun 24, 2024
6b465b7
Document the mapping functions on `zcash_client_backend::wallet::Reci…
daira Jun 24, 2024
4f43a01
Refactor transparent address metadata lookups. This is correct as-is but
daira Jun 25, 2024
5a90fff
Factor out the conversion of the `diversifier_index_be` field in the
daira Jun 25, 2024
7fb3557
Implement `WalletRead::get_transparent_address_metadata` for
daira Jun 25, 2024
7d8a96f
Don't cache metadata between steps; it's not an important optimization.
daira Jun 25, 2024
bd6c9f3
Apply documentation suggestions from code review.
daira Jun 26, 2024
0735390
Rename `amount` to `transfer_amount` in `send_multi_step_proposed_tra…
daira Jun 26, 2024
c926e7c
Filter ephemeral transparent `ChangeValue`s by `is_ephemeral()` as we…
daira Jun 26, 2024
ffb2ddf
`zcash_client_backend::fees::ChangeValue` is now an enum, allowing only
daira Jun 26, 2024
b778139
Refactor ephemeral output-related parameters to balance calculation.
daira Jun 26, 2024
7a05b44
Make mutable inputs to closures in `create_proposed_transaction` expl…
daira Jun 26, 2024
6471d4c
Don't assume that prior step outputs are ephemeral iff they are
daira Jun 27, 2024
ec4a6d0
Documentation improvements.
daira Jun 27, 2024
81a2846
Simpler way to calculate `has_shielded_inputs`.
daira Jun 27, 2024
f0e5aab
Improve discrimination of proposal errors.
daira Jun 27, 2024
feabe6d
Remove complicated code to calculate the number of dust spends.
daira Jun 26, 2024
baccb43
Restore the logic to determine whether we are spending inputs that are
daira Jun 28, 2024
9c082dc
`zcash_primitives::transaction::fees::zip317::FeeRule::non_standard` has
daira Jun 28, 2024
3829663
Change note selection query to select notes > 5000 zats, not >= 5000 …
daira Jun 28, 2024
25006ab
Documentation improvement from code review.
daira Jun 28, 2024
3922d71
Change the type of `n` in `reserve_next_n_ephemeral_addresses` back t…
daira Jun 28, 2024
d32b7db
Remove `ChangeValue::new`. Also document `ChangeValue::is_ephemeral` as
daira Jun 28, 2024
286439a
Define a constant `EphemeralParameters::NONE` instead of deriving `De…
daira Jun 29, 2024
bc38f2a
Document the `possible_change` parameter to `check_for_uneconomic_inp…
daira Jun 29, 2024
7838c04
Make `ephemeral_parameters` and `EphemeralParameters::NONE` available
daira Jun 29, 2024
14bdcde
We cannot spend prior outputs at all when "transparent-inputs" is not
daira Jun 29, 2024
8636daa
Tiny simplification.
daira Jun 29, 2024
01ff201
Minor changes responding to review comments.
daira Jul 3, 2024
b63ff5b
Rename `get_reserved_ephemeral_addresses` to `get_known_ephemeral_add…
daira Jul 3, 2024
e97da43
Refactoring to address review comments.
daira Jul 3, 2024
a01588b
Ensure that `mark_ephemeral_address_as_mined` correctly handles indices
daira Jul 4, 2024
86428c4
Refactor `find_account_for_transparent_output` (now called
daira Jul 4, 2024
b48f627
Minor simplification in a test.
daira Jul 4, 2024
6bc22f4
Documentation fixes and improvements.
daira Jul 4, 2024
27ca6e4
Remove unneeded `impl SealedChangeLevelKey for EphemeralIvk`.
daira Jul 4, 2024
bda6451
Change `unwrap`s to `expect`s when constructing `NonHardenedChildIndex`.
daira Jul 4, 2024
22b8cff
The `TxId` argument to `EphemeralAddressReuse` does not need to be op…
daira Jul 4, 2024
9856a70
Simpler handling of a potential overflow.
daira Jul 4, 2024
56aa348
Extend the `send_multi_step_proposed_transfer` test to check the beha…
daira Jul 4, 2024
aa43123
Use `EphemeralBalance` instead of `EphemeralParameters`
nuttycom Jul 16, 2024
dbb5eeb
Fix a potential crash related to varying behavior between change stra…
nuttycom Jul 16, 2024
24b6d50
Apply suggestions from code review
nuttycom Jul 16, 2024
f8bedd8
Make ephemeral_addresses.address unique
nuttycom Jul 17, 2024
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: 4 additions & 6 deletions zcash_client_sqlite/src/wallet/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ CREATE INDEX "addresses_accounts" ON "addresses" (
///
/// All but the last `GAP_LIMIT` addresses are defined to be "reserved" addresses. Since the next
/// index to reserve is determined by dead reckoning from the last stored address, we use dummy
/// entries after the maximum valid index in order to allow the last `GAP_LIMIT` addresses at the
/// end of the index range to be used.
/// entries having `NULL` for the value of the `address` column after the maximum valid index in
/// order to allow the last `GAP_LIMIT` addresses at the end of the index range to be used.
///
/// Note that the fact that `used_in_tx` references a specific transaction is just a debugging aid.
/// The same is mostly true of `seen_in_tx`, but we also take into account whether the referenced
Expand All @@ -116,13 +116,15 @@ pub(super) const TABLE_EPHEMERAL_ADDRESSES: &str = r#"
CREATE TABLE ephemeral_addresses (
account_id INTEGER NOT NULL,
address_index INTEGER NOT NULL,
-- nullability of this column is controlled by the index_range_and_address_nullity check
address TEXT,
used_in_tx INTEGER,
seen_in_tx INTEGER,
FOREIGN KEY (account_id) REFERENCES accounts(id),
FOREIGN KEY (used_in_tx) REFERENCES transactions(id_tx),
FOREIGN KEY (seen_in_tx) REFERENCES transactions(id_tx),
PRIMARY KEY (account_id, address_index),
CONSTRAINT ephemeral_addr_uniq UNIQUE (address),
CONSTRAINT used_implies_seen CHECK (
used_in_tx IS NULL OR seen_in_tx IS NOT NULL
),
Expand All @@ -135,10 +137,6 @@ CREATE TABLE ephemeral_addresses (
// libsqlite3-sys requires at least version 3.14.0.
// "WITHOUT ROWID" tells SQLite to use a clustered index on the (composite) primary key.
const_assert_eq!(GAP_LIMIT, 20);
pub(super) const INDEX_EPHEMERAL_ADDRESSES_ADDRESS: &str = r#"
CREATE INDEX ephemeral_addresses_address ON ephemeral_addresses (
address ASC
)"#;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, the ephemeral_addr_uniq constraint has essentially the same effect as a unique index.


/// Stores information about every block that the wallet has scanned.
///
Expand Down
1 change: 0 additions & 1 deletion zcash_client_sqlite/src/wallet/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,6 @@ mod tests {
db::INDEX_ACCOUNTS_UIVK,
db::INDEX_HD_ACCOUNT,
db::INDEX_ADDRESSES_ACCOUNTS,
db::INDEX_EPHEMERAL_ADDRESSES_ADDRESS,
db::INDEX_NF_MAP_LOCATOR_IDX,
db::INDEX_ORCHARD_RECEIVED_NOTES_ACCOUNT,
db::INDEX_ORCHARD_RECEIVED_NOTES_TX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,36 @@
DEPENDENCIES.into_iter().collect()
}

fn description(&self) -> &'static str {
"Record ephemeral addresses for each account."

Check warning on line 36 in zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs#L35-L36

Added lines #L35 - L36 were not covered by tests
}
}

impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
type Error = WalletMigrationError;

fn up(&self, transaction: &rusqlite::Transaction) -> Result<(), WalletMigrationError> {

Check warning on line 43 in zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs#L43

Added line #L43 was not covered by tests
transaction.execute_batch(
"CREATE TABLE ephemeral_addresses (
account_id INTEGER NOT NULL,
address_index INTEGER NOT NULL,
-- nullability of this column is controlled by the index_range_and_address_nullity check
address TEXT,
used_in_tx INTEGER,
seen_in_tx INTEGER,
FOREIGN KEY (account_id) REFERENCES accounts(id),
FOREIGN KEY (used_in_tx) REFERENCES transactions(id_tx),
FOREIGN KEY (seen_in_tx) REFERENCES transactions(id_tx),
PRIMARY KEY (account_id, address_index),
CONSTRAINT ephemeral_addr_uniq UNIQUE (address),
CONSTRAINT used_implies_seen CHECK (
used_in_tx IS NULL OR seen_in_tx IS NOT NULL
),
CONSTRAINT index_range_and_address_nullity CHECK (
(address_index BETWEEN 0 AND 0x7FFFFFFF AND address IS NOT NULL) OR
(address_index BETWEEN 0x80000000 AND 0x7FFFFFFF + 20 AND address IS NULL AND used_in_tx IS NULL AND seen_in_tx IS NULL)
)
) WITHOUT ROWID;
CREATE INDEX ephemeral_addresses_address ON ephemeral_addresses (
address ASC
);",
) WITHOUT ROWID;"
)?;

// Make sure that at least `GAP_LIMIT` ephemeral transparent addresses are
Expand All @@ -75,8 +74,8 @@
Ok(())
}

fn down(&self, _transaction: &rusqlite::Transaction) -> Result<(), WalletMigrationError> {
Err(WalletMigrationError::CannotRevert(MIGRATION_ID))

Check warning on line 78 in zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/init/migrations/ephemeral_addresses.rs#L77-L78

Added lines #L77 - L78 were not covered by tests
}
}

Expand Down
18 changes: 11 additions & 7 deletions zcash_client_sqlite/src/wallet/transparent/ephemeral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
);

if allocation.len() < n {
return Err(AddressGenerationError::DiversifierSpaceExhausted.into());

Check warning on line 231 in zcash_client_sqlite/src/wallet/transparent/ephemeral.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/transparent/ephemeral.rs#L231

Added line #L231 was not covered by tests
}
if allocation.end > first_unsafe {
return Err(SqliteClientError::ReachedGapLimit(
Expand Down Expand Up @@ -282,14 +282,18 @@
)?;

for raw_index in range_to_store {
let address_str_opt = match NonHardenedChildIndex::from_index(raw_index) {
Some(address_index) => Some(
// The range to store may contain indicies that are out of the valid range of non hardened
// child indices; we still store explicit rows in the ephemeral_addresses table for these
// so that it's possible to find the first unused address using dead reckoning with the gap
// limit.
let address_str_opt = NonHardenedChildIndex::from_index(raw_index)
.map(|address_index| {
ephemeral_ivk
.derive_ephemeral_address(address_index)?
.encode(params),
),
None => None,
};
.derive_ephemeral_address(address_index)
.map(|addr| addr.encode(params))
})
.transpose()?;

stmt_insert_ephemeral_address.execute(named_params![
":account_id": account_id.0,
":address_index": raw_index,
Expand Down Expand Up @@ -334,13 +338,13 @@

if let Some(txid_bytes) = res {
let txid = TxId::from_bytes(
txid_bytes
.try_into()
.map_err(|_| SqliteClientError::CorruptedData("invalid txid".to_owned()))?,

Check warning on line 343 in zcash_client_sqlite/src/wallet/transparent/ephemeral.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/transparent/ephemeral.rs#L341-L343

Added lines #L341 - L343 were not covered by tests
);
Err(SqliteClientError::EphemeralAddressReuse(
address_str.to_owned(),
txid,

Check warning on line 347 in zcash_client_sqlite/src/wallet/transparent/ephemeral.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet/transparent/ephemeral.rs#L345-L347

Added lines #L345 - L347 were not covered by tests
))
} else {
Ok(())
Expand Down
Loading