zcash_client_sqlite: Read rcm correctly from data DB after Canopy
ZIP 212 alters the note plaintext to store a seed from which rcm is derived, rather than storing rcm directly. In the mobile SDKs we only need rcm, so for post-ZIP 212 notes, we derive rcm from the seed and store rcm in the data DB. However, when selecting notes to spend, `create_to_address` was using the transaction's target height to determine if Canopy is active, and parsing the rcm value as the seed if so. This effectively applied a seed->rcm derivation to all selected notes' rcms once Canopy activated on the chain. As a result, the note commitments were incorrect, and thus the anchors derived from the witness paths were also incorrect. This caused two kinds of observed failures: - If more than one note was selected, the builder would fail with "anchor mismatch", as the note commitments would be effectively randomised, causing the derived anchors to also randomise. - If a single note was selected, the transaction would be built using the randomised anchor, and then rejected when sent to the network. The fix is to "pretend" in `create_to_address` that all notes are pre-ZIP 212 notes. This works fine because we never need to serialize back to the note plaintext while spending a note.
This commit is contained in:
parent
37b5d67d33
commit
524cc2e979
|
@ -7,7 +7,7 @@ use std::convert::TryInto;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use zcash_client_backend::encoding::encode_extended_full_viewing_key;
|
use zcash_client_backend::encoding::encode_extended_full_viewing_key;
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
consensus::{self, NetworkUpgrade, Parameters},
|
consensus,
|
||||||
keys::OutgoingViewingKey,
|
keys::OutgoingViewingKey,
|
||||||
merkle_tree::{IncrementalWitness, MerklePath},
|
merkle_tree::{IncrementalWitness, MerklePath},
|
||||||
note_encryption::Memo,
|
note_encryption::Memo,
|
||||||
|
@ -227,19 +227,16 @@ pub fn create_to_address<P: AsRef<Path>>(
|
||||||
let rseed = {
|
let rseed = {
|
||||||
let d: Vec<_> = row.get(2)?;
|
let d: Vec<_> = row.get(2)?;
|
||||||
|
|
||||||
if Network::is_nu_active(NetworkUpgrade::Canopy, height) {
|
// We store rcm directly in the data DB, regardless of whether the note
|
||||||
let mut r = [0u8; 32];
|
// used a v1 or v2 note plaintext, so for the purposes of spending let's
|
||||||
r.copy_from_slice(&d[..]);
|
// pretend this is a pre-ZIP 212 note.
|
||||||
Rseed::AfterZip212(r)
|
let r = jubjub::Fr::from_repr(
|
||||||
} else {
|
d[..]
|
||||||
let r = jubjub::Fr::from_repr(
|
.try_into()
|
||||||
d[..]
|
.map_err(|_| Error(ErrorKind::InvalidNote))?,
|
||||||
.try_into()
|
)
|
||||||
.map_err(|_| Error(ErrorKind::InvalidNote))?,
|
.ok_or(Error(ErrorKind::InvalidNote))?;
|
||||||
)
|
Rseed::BeforeZip212(r)
|
||||||
.ok_or(Error(ErrorKind::InvalidNote))?;
|
|
||||||
Rseed::BeforeZip212(r)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let from = extfvk.fvk.vk.to_payment_address(diversifier).unwrap();
|
let from = extfvk.fvk.vk.to_payment_address(diversifier).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue