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

Bug in is_shielding state going from TRUE to FALSE after the first confirmation #1571

Closed
true-jared opened this issue Oct 14, 2024 · 3 comments · Fixed by #1585
Closed

Bug in is_shielding state going from TRUE to FALSE after the first confirmation #1571

true-jared opened this issue Oct 14, 2024 · 3 comments · Fixed by #1585
Assignees
Labels
bug C-tracked-bug Category: This is a bug for which we are tracking deployment to apps.

Comments

@true-jared
Copy link

  • the states of the DB and is_shielding changes from true to false

How to reproduce:

  • I tapped a button to shield my funds, it:
  • created a transaction in a pending state with is_shielding TRUE
  • after 1st confirmation, it flipped to sending instead of shielding, I checked the DB and there is no TRUE anymore (see the DB)
  • after 10 confirmations, it flipped to sent
  • when I restore the same wallet, I see shielded again

Few more observations:

  • when I try to restore the wallet on a different simulator while it’s still waiting on 10 confirmations and should be shielding funds but it’s sending, I see correct state restored.. so restore is able to bring the TRUE flag back but where it matters it’s broken

  • db export shared via Slack here: https://zcash.slack.com/archives/C02C1GZ0R6F/p1724835111523729

@true-jared true-jared added the bug label Oct 14, 2024
@true-jared true-jared changed the title Bug in is_shielding state going from [shielding] to [sending] after the first confirmation Bug in is_shielding state going from TRUE to FALSE after the first confirmation Oct 14, 2024
@nuttycom
Copy link
Contributor

nuttycom commented Oct 22, 2024

The root of the problem here appears to be that the received note in the shielding transaction is no longer interpreted as a change output after the transaction is mined.

This is the code that is causing the transaction to be marked as not shielding:

-- We do not know about any external outputs of the transaction.
AND MAX(COALESCE(sent_note_counts.sent_notes, 0)) = 0

In investigating the source of the sent_note_counts data, and comparing the two provided database files, I found that the value of the is_change column in the orchard_received_notes table is changing from 1 to 0 at the point that the transaction is discovered via chain scanning.

@nuttycom
Copy link
Contributor

nuttycom commented Oct 22, 2024

Noticed along the way: the following lines don't make sense, as the is_change field is not optional, so the nullability check will never return false:

This could usefully be implemented as MAX(:is_change, is_change) instead and would work around this bug, but the actual root cause is somewhere upstream of this, in the is_change determination coming from scanning.

@nuttycom
Copy link
Contributor

nuttycom commented Oct 22, 2024

The root cause of the is_change field being set to false in shielding transactions is that

let (sapling_spends, sapling_unlinked_nullifiers) = find_spent(
&tx.spends,
&nullifiers.sapling,
|spend| {
spend.nf().expect(
"Could not deserialize nullifier for spend from protobuf representation.",
)
},
WalletSpend::from_parts,
);
sapling_nullifier_map.push((txid, tx_index, sapling_unlinked_nullifiers));
#[cfg(feature = "orchard")]
let orchard_spends = {
let (orchard_spends, orchard_unlinked_nullifiers) = find_spent(
&tx.actions,
&nullifiers.orchard,
|spend| {
spend.nf().expect(
"Could not deserialize nullifier for spend from protobuf representation.",
)
},
WalletSpend::from_parts,
);
orchard_nullifier_map.push((txid, tx_index, orchard_unlinked_nullifiers));
orchard_spends
};
does not (and cannot) determine that the spend is from the same account, because the spent UTXO is transparent.

To fix this, we could query the backend to augment the spent_from_account set for the transaction. This would work for the particular case of shielding transactions in the wallet steady state, because the backend will already have the transaction data. However, this may not be satisfactory in e.g. wallet recovery cases, because the shielded parts of the compact block could conceivably be scanned before the transparent UTXO DAG is traversed. Therefore, we may need to make changes in other places to ensure that stored notes are updated to correct their is_change values if we decide to take this route. It would also require a database capability to be added in a place that it doesn't currently exist, so this seems like a less desirable approach.

Remediation:

  • We should make the MAX change previously described; that is noninvasive and obviously correct.
  • The existing code doesn't appear to be taking the key scope into account for the is_change determination. This was an intentional choice though, because for example a cross-account wallet-internal transfer shouldn't be considered change.
  • It's necessary to add a migration to fix incorrect is_change values in existing wallets for outputs of wallet-internal shielding transactions where the source account is the same as the recipient account.
  • We should potentially change https://github.com/zcash/librustzcash/blob/main/zcash_client_sqlite/src/wallet/db.rs#L822 to use a comparison between source and recipient account instead of is_change? That might be complex to add to the query though.

nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 23, 2024
…ash#1571

The update to a shielding transaction causes the information that the
output is considered change to be lost. This happens because the
scanning process does not have access to any information about the
inputs to the transaction, and so it does not recognize the output as
change.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 23, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 23, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 23, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 23, 2024
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
…ash#1571

The update to a shielding transaction causes the information that the
output is considered change to be lost. This happens because the
scanning process does not have access to any information about the
inputs to the transaction, and so it does not recognize the output as
change.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
…scind that determination.

This is a minimal and correct but incomplete fix for
zcash#1571. Additional work to distinguish change outputs
is necessary to update existing wallets that have made an incorrect
change determination in the past.
nuttycom added a commit to nuttycom/librustzcash that referenced this issue Oct 24, 2024
@str4d str4d added the C-tracked-bug Category: This is a bug for which we are tracking deployment to apps. label Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug C-tracked-bug Category: This is a bug for which we are tracking deployment to apps.
Projects
None yet
3 participants