Merge pull request #511 from zcash/merge-non-consensus-changes-again
Merge non consensus changes again
This commit is contained in:
commit
ff243b4f00
|
@ -314,7 +314,7 @@ fn tree_validator(p: &Params, state: &Blake2bState, indices: &[u32]) -> Result<N
|
||||||
validate_subtrees(p, &a, &b).map_err(Error)?;
|
validate_subtrees(p, &a, &b).map_err(Error)?;
|
||||||
Ok(Node::from_children(a, b, p.collision_byte_length()))
|
Ok(Node::from_children(a, b, p.collision_byte_length()))
|
||||||
} else {
|
} else {
|
||||||
Ok(Node::new(&p, &state, indices[0]))
|
Ok(Node::new(p, state, indices[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,13 +486,13 @@ mod tests {
|
||||||
fn invalid_test_vectors() {
|
fn invalid_test_vectors() {
|
||||||
for tv in INVALID_TEST_VECTORS {
|
for tv in INVALID_TEST_VECTORS {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
is_valid_solution_iterative(tv.params, tv.input, &tv.nonce, &tv.solution)
|
is_valid_solution_iterative(tv.params, tv.input, &tv.nonce, tv.solution)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.0,
|
.0,
|
||||||
tv.error
|
tv.error
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
is_valid_solution_recursive(tv.params, tv.input, &tv.nonce, &tv.solution)
|
is_valid_solution_recursive(tv.params, tv.input, &tv.nonce, tv.solution)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.0,
|
.0,
|
||||||
tv.error
|
tv.error
|
||||||
|
|
|
@ -94,7 +94,7 @@ impl<'a> State<'a> {
|
||||||
let hash = Blake2bParams::new()
|
let hash = Blake2bParams::new()
|
||||||
.hash_length(self.left.len())
|
.hash_length(self.left.len())
|
||||||
.personal(&H_PERS!(i))
|
.personal(&H_PERS!(i))
|
||||||
.hash(&self.right);
|
.hash(self.right);
|
||||||
xor(self.left, hash.as_bytes())
|
xor(self.left, hash.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ impl<'a> State<'a> {
|
||||||
let hash = Blake2bParams::new()
|
let hash = Blake2bParams::new()
|
||||||
.hash_length(OUTBYTES)
|
.hash_length(OUTBYTES)
|
||||||
.personal(&G_PERS!(i, j as u16))
|
.personal(&G_PERS!(i, j as u16))
|
||||||
.hash(&self.left);
|
.hash(self.left);
|
||||||
xor(&mut self.right[j * OUTBYTES..], hash.as_bytes());
|
xor(&mut self.right[j * OUTBYTES..], hash.as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,25 +155,15 @@ pub fn f4jumble_inv_mut(message: &mut [u8]) -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn f4jumble(message: &[u8]) -> Option<Vec<u8>> {
|
pub fn f4jumble(message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
let mut result = message.to_vec();
|
let mut result = message.to_vec();
|
||||||
let res = f4jumble_mut(&mut result);
|
f4jumble_mut(&mut result).map(|()| result)
|
||||||
if res.is_ok() {
|
|
||||||
Some(result)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn f4jumble_inv(message: &[u8]) -> Option<Vec<u8>> {
|
pub fn f4jumble_inv(message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
let mut result = message.to_vec();
|
let mut result = message.to_vec();
|
||||||
let res = f4jumble_inv_mut(&mut result);
|
f4jumble_inv_mut(&mut result).map(|()| result)
|
||||||
if res.is_ok() {
|
|
||||||
Some(result)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -198,11 +188,11 @@ mod common_tests {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
let mut cache = vec![0u8; test_vectors::MAX_VECTOR_LENGTH];
|
let mut cache = vec![0u8; test_vectors::MAX_VECTOR_LENGTH];
|
||||||
for v in test_vectors::TEST_VECTORS {
|
for v in test_vectors::TEST_VECTORS {
|
||||||
let mut data = &mut cache[..v.normal.len()];
|
let data = &mut cache[..v.normal.len()];
|
||||||
data.clone_from_slice(&v.normal);
|
data.clone_from_slice(v.normal);
|
||||||
f4jumble_mut(&mut data).unwrap();
|
f4jumble_mut(data).unwrap();
|
||||||
assert_eq!(data, v.jumbled);
|
assert_eq!(data, v.jumbled);
|
||||||
f4jumble_inv_mut(&mut data).unwrap();
|
f4jumble_inv_mut(data).unwrap();
|
||||||
assert_eq!(data, v.normal);
|
assert_eq!(data, v.normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,9 +236,9 @@ mod std_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn f4jumble_check_vectors() {
|
fn f4jumble_check_vectors() {
|
||||||
for v in test_vectors::TEST_VECTORS {
|
for v in test_vectors::TEST_VECTORS {
|
||||||
let jumbled = f4jumble(&v.normal).unwrap();
|
let jumbled = f4jumble(v.normal).unwrap();
|
||||||
assert_eq!(jumbled, v.jumbled);
|
assert_eq!(jumbled, v.jumbled);
|
||||||
let unjumbled = f4jumble_inv(&v.jumbled).unwrap();
|
let unjumbled = f4jumble_inv(v.jumbled).unwrap();
|
||||||
assert_eq!(unjumbled, v.normal);
|
assert_eq!(unjumbled, v.normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,11 +222,12 @@ pub(crate) mod private {
|
||||||
writer.write_all(&padding).unwrap();
|
writer.write_all(&padding).unwrap();
|
||||||
|
|
||||||
let padded = writer.into_inner();
|
let padded = writer.into_inner();
|
||||||
f4jumble::f4jumble(&padded).unwrap_or_else(|| panic!("f4jumble failed on {:?}", padded))
|
f4jumble::f4jumble(&padded)
|
||||||
|
.unwrap_or_else(|e| panic!("f4jumble failed on {:?}: {}", padded, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the items of the unified container.
|
/// Parse the items of the unified container.
|
||||||
fn parse_items(hrp: &str, buf: &[u8]) -> Result<Vec<Self::Item>, ParseError> {
|
fn parse_items<T: Into<Vec<u8>>>(hrp: &str, buf: T) -> Result<Vec<Self::Item>, ParseError> {
|
||||||
fn read_receiver<R: SealedItem>(
|
fn read_receiver<R: SealedItem>(
|
||||||
mut cursor: &mut std::io::Cursor<&[u8]>,
|
mut cursor: &mut std::io::Cursor<&[u8]>,
|
||||||
) -> Result<R, ParseError> {
|
) -> Result<R, ParseError> {
|
||||||
|
@ -265,8 +266,10 @@ pub(crate) mod private {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
let encoded = f4jumble::f4jumble_inv(buf).ok_or_else(|| {
|
// Here we allocate if necessary to get a mutable Vec<u8> to unjumble.
|
||||||
ParseError::InvalidEncoding("F4Jumble decoding failed".to_owned())
|
let mut encoded = buf.into();
|
||||||
|
f4jumble::f4jumble_inv_mut(&mut encoded[..]).map_err(|e| {
|
||||||
|
ParseError::InvalidEncoding(format!("F4Jumble decoding failed: {}", e))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Validate and strip trailing padding bytes.
|
// Validate and strip trailing padding bytes.
|
||||||
|
@ -326,7 +329,7 @@ pub(crate) mod private {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_internal(hrp: &str, buf: &[u8]) -> Result<Self, ParseError> {
|
fn parse_internal<T: Into<Vec<u8>>>(hrp: &str, buf: T) -> Result<Self, ParseError> {
|
||||||
Self::parse_items(hrp, buf).and_then(Self::try_from_items_internal)
|
Self::parse_items(hrp, buf).and_then(Self::try_from_items_internal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,7 +367,7 @@ pub trait Encoding: private::SealedContainer {
|
||||||
let data = Vec::<u8>::from_base32(&data)
|
let data = Vec::<u8>::from_base32(&data)
|
||||||
.map_err(|e| ParseError::InvalidEncoding(e.to_string()))?;
|
.map_err(|e| ParseError::InvalidEncoding(e.to_string()))?;
|
||||||
|
|
||||||
Self::parse_internal(hrp, &data[..]).map(|value| (net, value))
|
Self::parse_internal(hrp, data).map(|value| (net, value))
|
||||||
} else {
|
} else {
|
||||||
Err(ParseError::NotUnified)
|
Err(ParseError::NotUnified)
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,7 +475,7 @@ impl<D: Domain> NoteEncryption<D> {
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> [u8; OUT_CIPHERTEXT_SIZE] {
|
) -> [u8; OUT_CIPHERTEXT_SIZE] {
|
||||||
let (ock, input) = if let Some(ovk) = &self.ovk {
|
let (ock, input) = if let Some(ovk) = &self.ovk {
|
||||||
let ock = D::derive_ock(ovk, &cv, &cmstar.into(), &D::epk_bytes(&self.epk));
|
let ock = D::derive_ock(ovk, cv, &cmstar.into(), &D::epk_bytes(&self.epk));
|
||||||
let input = D::outgoing_plaintext_bytes(&self.note, &self.esk);
|
let input = D::outgoing_plaintext_bytes(&self.note, &self.esk);
|
||||||
|
|
||||||
(ock, input)
|
(ock, input)
|
||||||
|
@ -563,7 +563,7 @@ fn parse_note_plaintext_without_memo_ivk<D: Domain>(
|
||||||
cmstar_bytes: &D::ExtractedCommitmentBytes,
|
cmstar_bytes: &D::ExtractedCommitmentBytes,
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> Option<(D::Note, D::Recipient)> {
|
) -> Option<(D::Note, D::Recipient)> {
|
||||||
let (note, to) = domain.parse_note_plaintext_without_memo_ivk(ivk, &plaintext)?;
|
let (note, to) = domain.parse_note_plaintext_without_memo_ivk(ivk, plaintext)?;
|
||||||
|
|
||||||
if let NoteValidity::Valid = check_note_validity::<D>(¬e, ephemeral_key, cmstar_bytes) {
|
if let NoteValidity::Valid = check_note_validity::<D>(¬e, ephemeral_key, cmstar_bytes) {
|
||||||
Some((note, to))
|
Some((note, to))
|
||||||
|
@ -577,10 +577,10 @@ fn check_note_validity<D: Domain>(
|
||||||
ephemeral_key: &EphemeralKeyBytes,
|
ephemeral_key: &EphemeralKeyBytes,
|
||||||
cmstar_bytes: &D::ExtractedCommitmentBytes,
|
cmstar_bytes: &D::ExtractedCommitmentBytes,
|
||||||
) -> NoteValidity {
|
) -> NoteValidity {
|
||||||
if &D::ExtractedCommitmentBytes::from(&D::cmstar(¬e)) == cmstar_bytes {
|
if &D::ExtractedCommitmentBytes::from(&D::cmstar(note)) == cmstar_bytes {
|
||||||
if let Some(derived_esk) = D::derive_esk(note) {
|
if let Some(derived_esk) = D::derive_esk(note) {
|
||||||
if D::epk_bytes(&D::ka_derive_public(¬e, &derived_esk))
|
if D::epk_bytes(&D::ka_derive_public(note, &derived_esk))
|
||||||
.ct_eq(&ephemeral_key)
|
.ct_eq(ephemeral_key)
|
||||||
.into()
|
.into()
|
||||||
{
|
{
|
||||||
NoteValidity::Valid
|
NoteValidity::Valid
|
||||||
|
@ -614,7 +614,7 @@ pub fn try_compact_note_decryption<D: Domain, Output: ShieldedOutput<D, COMPACT_
|
||||||
let ephemeral_key = output.ephemeral_key();
|
let ephemeral_key = output.ephemeral_key();
|
||||||
|
|
||||||
let epk = D::epk(&ephemeral_key)?;
|
let epk = D::epk(&ephemeral_key)?;
|
||||||
let shared_secret = D::ka_agree_dec(&ivk, &epk);
|
let shared_secret = D::ka_agree_dec(ivk, &epk);
|
||||||
let key = D::kdf(shared_secret, &ephemeral_key);
|
let key = D::kdf(shared_secret, &ephemeral_key);
|
||||||
|
|
||||||
try_compact_note_decryption_inner(domain, ivk, &ephemeral_key, output, key)
|
try_compact_note_decryption_inner(domain, ivk, &ephemeral_key, output, key)
|
||||||
|
@ -659,7 +659,7 @@ pub fn try_output_recovery_with_ovk<D: Domain, Output: ShieldedOutput<D, ENC_CIP
|
||||||
cv: &D::ValueCommitment,
|
cv: &D::ValueCommitment,
|
||||||
out_ciphertext: &[u8; OUT_CIPHERTEXT_SIZE],
|
out_ciphertext: &[u8; OUT_CIPHERTEXT_SIZE],
|
||||||
) -> Option<(D::Note, D::Recipient, D::Memo)> {
|
) -> Option<(D::Note, D::Recipient, D::Memo)> {
|
||||||
let ock = D::derive_ock(ovk, &cv, &output.cmstar_bytes(), &output.ephemeral_key());
|
let ock = D::derive_ock(ovk, cv, &output.cmstar_bytes(), &output.ephemeral_key());
|
||||||
try_output_recovery_with_ock(domain, &ock, output, out_ciphertext)
|
try_output_recovery_with_ock(domain, &ock, output, out_ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ impl<N: fmt::Display> fmt::Display for Error<N> {
|
||||||
write!(f, "Invalid chain (upper bound: {}): {:?}", u32::from(*upper_bound), cause)
|
write!(f, "Invalid chain (upper bound: {}): {:?}", u32::from(*upper_bound), cause)
|
||||||
}
|
}
|
||||||
Error::InvalidExtSk(account) => {
|
Error::InvalidExtSk(account) => {
|
||||||
write!(f, "Incorrect ExtendedSpendingKey for account {}", account.0)
|
write!(f, "Incorrect ExtendedSpendingKey for account {}", u32::from(*account))
|
||||||
}
|
}
|
||||||
Error::InvalidNewWitnessAnchor(output, txid, last_height, anchor) => write!(
|
Error::InvalidNewWitnessAnchor(output, txid, last_height, anchor) => write!(
|
||||||
f,
|
f,
|
||||||
|
|
|
@ -142,7 +142,7 @@ where
|
||||||
/// }
|
/// }
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let account = AccountId(0);
|
/// let account = AccountId::from(0);
|
||||||
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, account);
|
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, account);
|
||||||
/// let to = extsk.default_address().1.into();
|
/// let to = extsk.default_address().1.into();
|
||||||
///
|
///
|
||||||
|
@ -347,7 +347,7 @@ where
|
||||||
Err(Error::MemoForbidden)
|
Err(Error::MemoForbidden)
|
||||||
} else {
|
} else {
|
||||||
builder
|
builder
|
||||||
.add_transparent_output(&to, payment.amount)
|
.add_transparent_output(to, payment.amount)
|
||||||
.map_err(Error::Builder)
|
.map_err(Error::Builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ where
|
||||||
{
|
{
|
||||||
// Check that the ExtendedSpendingKey we have been given corresponds to the
|
// Check that the ExtendedSpendingKey we have been given corresponds to the
|
||||||
// ExtendedFullViewingKey for the account we are spending from.
|
// ExtendedFullViewingKey for the account we are spending from.
|
||||||
if !wallet_db.is_valid_account_extfvk(account, &extfvk)? {
|
if !wallet_db.is_valid_account_extfvk(account, extfvk)? {
|
||||||
return Err(E::from(Error::InvalidExtSk(account)));
|
return Err(E::from(Error::InvalidExtSk(account)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ where
|
||||||
{
|
{
|
||||||
match bech32::decode(s)? {
|
match bech32::decode(s)? {
|
||||||
(decoded_hrp, data, Variant::Bech32) if decoded_hrp == hrp => {
|
(decoded_hrp, data, Variant::Bech32) if decoded_hrp == hrp => {
|
||||||
Vec::<u8>::from_base32(&data).map(|data| read(data))
|
Vec::<u8>::from_base32(&data).map(read)
|
||||||
}
|
}
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ impl<P: consensus::Parameters> AddressCodec<P> for TransparentAddress {
|
||||||
/// keys::sapling,
|
/// keys::sapling,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId(0));
|
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId::from(0));
|
||||||
/// let encoded = encode_extended_spending_key(HRP_SAPLING_EXTENDED_SPENDING_KEY, &extsk);
|
/// let encoded = encode_extended_spending_key(HRP_SAPLING_EXTENDED_SPENDING_KEY, &extsk);
|
||||||
/// ```
|
/// ```
|
||||||
/// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey
|
/// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey
|
||||||
|
@ -140,7 +140,7 @@ pub fn decode_extended_spending_key(
|
||||||
/// };
|
/// };
|
||||||
/// use zcash_primitives::zip32::ExtendedFullViewingKey;
|
/// use zcash_primitives::zip32::ExtendedFullViewingKey;
|
||||||
///
|
///
|
||||||
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId(0));
|
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId::from(0));
|
||||||
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
|
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
/// let encoded = encode_extended_full_viewing_key(HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, &extfvk);
|
/// let encoded = encode_extended_full_viewing_key(HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, &extfvk);
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub mod sapling {
|
||||||
/// keys::sapling,
|
/// keys::sapling,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId(0));
|
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId::from(0));
|
||||||
/// ```
|
/// ```
|
||||||
/// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey
|
/// [`ExtendedSpendingKey`]: zcash_primitives::zip32::ExtendedSpendingKey
|
||||||
pub fn spending_key(seed: &[u8], coin_type: u32, account: AccountId) -> ExtendedSpendingKey {
|
pub fn spending_key(seed: &[u8], coin_type: u32, account: AccountId) -> ExtendedSpendingKey {
|
||||||
|
@ -35,11 +35,11 @@ pub mod sapling {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtendedSpendingKey::from_path(
|
ExtendedSpendingKey::from_path(
|
||||||
&ExtendedSpendingKey::master(&seed),
|
&ExtendedSpendingKey::master(seed),
|
||||||
&[
|
&[
|
||||||
ChildIndex::Hardened(32),
|
ChildIndex::Hardened(32),
|
||||||
ChildIndex::Hardened(coin_type),
|
ChildIndex::Hardened(coin_type),
|
||||||
ChildIndex::Hardened(account.0),
|
ChildIndex::Hardened(account.into()),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -186,20 +186,21 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn spending_key_panics_on_short_seed() {
|
fn spending_key_panics_on_short_seed() {
|
||||||
let _ = sapling::spending_key(&[0; 31][..], 0, AccountId(0));
|
let _ = sapling::spending_key(&[0; 31][..], 0, AccountId::from(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
#[test]
|
#[test]
|
||||||
fn pk_to_taddr() {
|
fn pk_to_taddr() {
|
||||||
let taddr = legacy::keys::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
|
let taddr =
|
||||||
.unwrap()
|
legacy::keys::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId::from(0))
|
||||||
.to_account_pubkey()
|
.unwrap()
|
||||||
.derive_external_ivk()
|
.to_account_pubkey()
|
||||||
.unwrap()
|
.derive_external_ivk()
|
||||||
.derive_address(0)
|
.unwrap()
|
||||||
.unwrap()
|
.derive_address(0)
|
||||||
.encode(&MAIN_NETWORK);
|
.unwrap()
|
||||||
|
.encode(&MAIN_NETWORK);
|
||||||
assert_eq!(taddr, "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4".to_string());
|
assert_eq!(taddr, "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ fn scan_output<P: consensus::Parameters, K: ScanningKey>(
|
||||||
// - Change created by spending fractions of notes.
|
// - Change created by spending fractions of notes.
|
||||||
// - Notes created by consolidation transactions.
|
// - Notes created by consolidation transactions.
|
||||||
// - Notes sent from one account to itself.
|
// - Notes sent from one account to itself.
|
||||||
let is_change = spent_from_accounts.contains(&account);
|
let is_change = spent_from_accounts.contains(account);
|
||||||
|
|
||||||
let witness = IncrementalWitness::from_tree(tree);
|
let witness = IncrementalWitness::from_tree(tree);
|
||||||
let nf = vk.nf(¬e, &witness);
|
let nf = vk.nf(¬e, &witness);
|
||||||
|
@ -229,7 +229,7 @@ pub fn scan_block<P: consensus::Parameters, K: ScanningKey>(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(account, nf)| CtOption::new(account, nf.ct_eq(&spend_nf)))
|
.map(|&(account, nf)| CtOption::new(account, nf.ct_eq(&spend_nf)))
|
||||||
.fold(
|
.fold(
|
||||||
CtOption::new(AccountId::default(), 0.into()),
|
CtOption::new(AccountId::from(0), 0.into()),
|
||||||
|first, next| CtOption::conditional_select(&next, &first, first.is_some()),
|
|first, next| CtOption::conditional_select(&next, &first, first.is_some()),
|
||||||
)
|
)
|
||||||
.map(|account| WalletShieldedSpend {
|
.map(|account| WalletShieldedSpend {
|
||||||
|
@ -441,7 +441,7 @@ mod tests {
|
||||||
let txs = scan_block(
|
let txs = scan_block(
|
||||||
&Network::TestNetwork,
|
&Network::TestNetwork,
|
||||||
cb,
|
cb,
|
||||||
&[(&AccountId(0), &extfvk)],
|
&[(&AccountId::from(0), &extfvk)],
|
||||||
&[],
|
&[],
|
||||||
&mut tree,
|
&mut tree,
|
||||||
&mut [],
|
&mut [],
|
||||||
|
@ -455,7 +455,7 @@ mod tests {
|
||||||
assert_eq!(tx.shielded_spends.len(), 0);
|
assert_eq!(tx.shielded_spends.len(), 0);
|
||||||
assert_eq!(tx.shielded_outputs.len(), 1);
|
assert_eq!(tx.shielded_outputs.len(), 1);
|
||||||
assert_eq!(tx.shielded_outputs[0].index, 0);
|
assert_eq!(tx.shielded_outputs[0].index, 0);
|
||||||
assert_eq!(tx.shielded_outputs[0].account, AccountId(0));
|
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
|
||||||
assert_eq!(tx.shielded_outputs[0].note.value, 5);
|
assert_eq!(tx.shielded_outputs[0].note.value, 5);
|
||||||
|
|
||||||
// Check that the witness root matches
|
// Check that the witness root matches
|
||||||
|
@ -480,7 +480,7 @@ mod tests {
|
||||||
let txs = scan_block(
|
let txs = scan_block(
|
||||||
&Network::TestNetwork,
|
&Network::TestNetwork,
|
||||||
cb,
|
cb,
|
||||||
&[(&AccountId(0), &extfvk)],
|
&[(&AccountId::from(0), &extfvk)],
|
||||||
&[],
|
&[],
|
||||||
&mut tree,
|
&mut tree,
|
||||||
&mut [],
|
&mut [],
|
||||||
|
@ -494,7 +494,7 @@ mod tests {
|
||||||
assert_eq!(tx.shielded_spends.len(), 0);
|
assert_eq!(tx.shielded_spends.len(), 0);
|
||||||
assert_eq!(tx.shielded_outputs.len(), 1);
|
assert_eq!(tx.shielded_outputs.len(), 1);
|
||||||
assert_eq!(tx.shielded_outputs[0].index, 0);
|
assert_eq!(tx.shielded_outputs[0].index, 0);
|
||||||
assert_eq!(tx.shielded_outputs[0].account, AccountId(0));
|
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
|
||||||
assert_eq!(tx.shielded_outputs[0].note.value, 5);
|
assert_eq!(tx.shielded_outputs[0].note.value, 5);
|
||||||
|
|
||||||
// Check that the witness root matches
|
// Check that the witness root matches
|
||||||
|
@ -506,7 +506,7 @@ mod tests {
|
||||||
let extsk = ExtendedSpendingKey::master(&[]);
|
let extsk = ExtendedSpendingKey::master(&[]);
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
let nf = Nullifier([7; 32]);
|
let nf = Nullifier([7; 32]);
|
||||||
let account = AccountId(12);
|
let account = AccountId::from(12);
|
||||||
|
|
||||||
let cb = fake_compact_block(1u32.into(), nf, extfvk, Amount::from_u64(5).unwrap(), false);
|
let cb = fake_compact_block(1u32.into(), nf, extfvk, Amount::from_u64(5).unwrap(), false);
|
||||||
assert_eq!(cb.vtx.len(), 2);
|
assert_eq!(cb.vtx.len(), 2);
|
||||||
|
|
|
@ -173,32 +173,32 @@ impl TransactionRequest {
|
||||||
payment
|
payment
|
||||||
.memo
|
.memo
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| render::memo_param(&m, payment_index)),
|
.map(|m| render::memo_param(m, payment_index)),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
payment
|
payment
|
||||||
.label
|
.label
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| render::str_param("label", &m, payment_index)),
|
.map(|m| render::str_param("label", m, payment_index)),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
payment
|
payment
|
||||||
.message
|
.message
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| render::str_param("message", &m, payment_index)),
|
.map(|m| render::str_param("message", m, payment_index)),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
payment
|
payment
|
||||||
.other_params
|
.other_params
|
||||||
.iter()
|
.iter()
|
||||||
.map(move |(name, value)| render::str_param(&name, &value, payment_index)),
|
.map(move |(name, value)| render::str_param(name, value, payment_index)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.payments[..] {
|
match &self.payments[..] {
|
||||||
[] => None,
|
[] => None,
|
||||||
[payment] => {
|
[payment] => {
|
||||||
let query_params = payment_params(&payment, None)
|
let query_params = payment_params(payment, None)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ impl TransactionRequest {
|
||||||
let primary_address = payment.recipient_address.clone();
|
let primary_address = payment.recipient_address.clone();
|
||||||
std::iter::empty()
|
std::iter::empty()
|
||||||
.chain(Some(render::addr_param(params, &primary_address, Some(i))))
|
.chain(Some(render::addr_param(params, &primary_address, Some(i))))
|
||||||
.chain(payment_params(&payment, Some(i)))
|
.chain(payment_params(payment, Some(i)))
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ impl TransactionRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(current) => {
|
Some(current) => {
|
||||||
if parse::has_duplicate_param(¤t, &p.param) {
|
if parse::has_duplicate_param(current, &p.param) {
|
||||||
return Err(Zip321Error::DuplicateParameter(p.param, p.payment_index));
|
return Err(Zip321Error::DuplicateParameter(p.param, p.payment_index));
|
||||||
} else {
|
} else {
|
||||||
current.push(p.param);
|
current.push(p.param);
|
||||||
|
@ -775,12 +775,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zip321_parse_simple() {
|
fn test_zip321_parse_simple() {
|
||||||
let uri = "zcash:ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k?amount=3768769.02796286&message=";
|
let uri = "zcash:ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k?amount=3768769.02796286&message=";
|
||||||
let parse_result = TransactionRequest::from_uri(&TEST_NETWORK, &uri).unwrap();
|
let parse_result = TransactionRequest::from_uri(&TEST_NETWORK, uri).unwrap();
|
||||||
|
|
||||||
let expected = TransactionRequest {
|
let expected = TransactionRequest {
|
||||||
payments: vec![
|
payments: vec![
|
||||||
Payment {
|
Payment {
|
||||||
recipient_address: RecipientAddress::Shielded(decode_payment_address(&TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap().unwrap()),
|
recipient_address: RecipientAddress::Shielded(decode_payment_address(TEST_NETWORK.hrp_sapling_payment_address(), "ztestsapling1n65uaftvs2g7075q2x2a04shfk066u3lldzxsrprfrqtzxnhc9ps73v4lhx4l9yfxj46sl0q90k").unwrap().unwrap()),
|
||||||
amount: Amount::from_u64(376876902796286).unwrap(),
|
amount: Amount::from_u64(376876902796286).unwrap(),
|
||||||
memo: None,
|
memo: None,
|
||||||
label: None,
|
label: None,
|
||||||
|
@ -833,14 +833,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zip321_spec_valid_examples() {
|
fn test_zip321_spec_valid_examples() {
|
||||||
let valid_1 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=1&memo=VGhpcyBpcyBhIHNpbXBsZSBtZW1vLg&message=Thank%20you%20for%20your%20purchase";
|
let valid_1 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=1&memo=VGhpcyBpcyBhIHNpbXBsZSBtZW1vLg&message=Thank%20you%20for%20your%20purchase";
|
||||||
let v1r = TransactionRequest::from_uri(&TEST_NETWORK, &valid_1).unwrap();
|
let v1r = TransactionRequest::from_uri(&TEST_NETWORK, valid_1).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v1r.payments.get(0).map(|p| p.amount),
|
v1r.payments.get(0).map(|p| p.amount),
|
||||||
Some(Amount::from_u64(100000000).unwrap())
|
Some(Amount::from_u64(100000000).unwrap())
|
||||||
);
|
);
|
||||||
|
|
||||||
let valid_2 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=123.456&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=0.789&memo.1=VGhpcyBpcyBhIHVuaWNvZGUgbWVtbyDinKjwn6aE8J-PhvCfjok";
|
let valid_2 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=123.456&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=0.789&memo.1=VGhpcyBpcyBhIHVuaWNvZGUgbWVtbyDinKjwn6aE8J-PhvCfjok";
|
||||||
let mut v2r = TransactionRequest::from_uri(&TEST_NETWORK, &valid_2).unwrap();
|
let mut v2r = TransactionRequest::from_uri(&TEST_NETWORK, valid_2).unwrap();
|
||||||
v2r.normalize(&TEST_NETWORK);
|
v2r.normalize(&TEST_NETWORK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v2r.payments.get(0).map(|p| p.amount),
|
v2r.payments.get(0).map(|p| p.amount),
|
||||||
|
@ -854,7 +854,7 @@ mod tests {
|
||||||
// valid; amount just less than MAX_MONEY
|
// valid; amount just less than MAX_MONEY
|
||||||
// 20999999.99999999
|
// 20999999.99999999
|
||||||
let valid_3 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=20999999.99999999";
|
let valid_3 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=20999999.99999999";
|
||||||
let v3r = TransactionRequest::from_uri(&TEST_NETWORK, &valid_3).unwrap();
|
let v3r = TransactionRequest::from_uri(&TEST_NETWORK, valid_3).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v3r.payments.get(0).map(|p| p.amount),
|
v3r.payments.get(0).map(|p| p.amount),
|
||||||
Some(Amount::from_u64(2099999999999999u64).unwrap())
|
Some(Amount::from_u64(2099999999999999u64).unwrap())
|
||||||
|
@ -863,7 +863,7 @@ mod tests {
|
||||||
// valid; MAX_MONEY
|
// valid; MAX_MONEY
|
||||||
// 21000000
|
// 21000000
|
||||||
let valid_4 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=21000000";
|
let valid_4 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=21000000";
|
||||||
let v4r = TransactionRequest::from_uri(&TEST_NETWORK, &valid_4).unwrap();
|
let v4r = TransactionRequest::from_uri(&TEST_NETWORK, valid_4).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v4r.payments.get(0).map(|p| p.amount),
|
v4r.payments.get(0).map(|p| p.amount),
|
||||||
Some(Amount::from_u64(2100000000000000u64).unwrap())
|
Some(Amount::from_u64(2100000000000000u64).unwrap())
|
||||||
|
@ -874,63 +874,63 @@ mod tests {
|
||||||
fn test_zip321_spec_invalid_examples() {
|
fn test_zip321_spec_invalid_examples() {
|
||||||
// invalid; missing `address=`
|
// invalid; missing `address=`
|
||||||
let invalid_1 = "zcash:?amount=3491405.05201255&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=5740296.87793245";
|
let invalid_1 = "zcash:?amount=3491405.05201255&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=5740296.87793245";
|
||||||
let i1r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_1);
|
let i1r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_1);
|
||||||
assert!(i1r.is_err());
|
assert!(i1r.is_err());
|
||||||
|
|
||||||
// invalid; missing `address.1=`
|
// invalid; missing `address.1=`
|
||||||
let invalid_2 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=1&amount.1=2&address.2=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez";
|
let invalid_2 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=1&amount.1=2&address.2=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez";
|
||||||
let i2r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_2);
|
let i2r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_2);
|
||||||
assert!(i2r.is_err());
|
assert!(i2r.is_err());
|
||||||
|
|
||||||
// invalid; `address.0=` and `amount.0=` are not permitted (leading 0s).
|
// invalid; `address.0=` and `amount.0=` are not permitted (leading 0s).
|
||||||
let invalid_3 = "zcash:?address.0=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.0=2";
|
let invalid_3 = "zcash:?address.0=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.0=2";
|
||||||
let i3r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_3);
|
let i3r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_3);
|
||||||
assert!(i3r.is_err());
|
assert!(i3r.is_err());
|
||||||
|
|
||||||
// invalid; duplicate `amount=` field
|
// invalid; duplicate `amount=` field
|
||||||
let invalid_4 =
|
let invalid_4 =
|
||||||
"zcash:?amount=1.234&amount=2.345&address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
"zcash:?amount=1.234&amount=2.345&address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
||||||
let i4r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_4);
|
let i4r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_4);
|
||||||
assert!(i4r.is_err());
|
assert!(i4r.is_err());
|
||||||
|
|
||||||
// invalid; duplicate `amount.1=` field
|
// invalid; duplicate `amount.1=` field
|
||||||
let invalid_5 =
|
let invalid_5 =
|
||||||
"zcash:?amount.1=1.234&amount.1=2.345&address.1=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
"zcash:?amount.1=1.234&amount.1=2.345&address.1=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
||||||
let i5r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_5);
|
let i5r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_5);
|
||||||
assert!(i5r.is_err());
|
assert!(i5r.is_err());
|
||||||
|
|
||||||
//invalid; memo associated with t-addr
|
//invalid; memo associated with t-addr
|
||||||
let invalid_6 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=123.456&memo=eyAia2V5IjogIlRoaXMgaXMgYSBKU09OLXN0cnVjdHVyZWQgbWVtby4iIH0&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=0.789&memo.1=VGhpcyBpcyBhIHVuaWNvZGUgbWVtbyDinKjwn6aE8J-PhvCfjok";
|
let invalid_6 = "zcash:?address=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU&amount=123.456&memo=eyAia2V5IjogIlRoaXMgaXMgYSBKU09OLXN0cnVjdHVyZWQgbWVtby4iIH0&address.1=ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez&amount.1=0.789&memo.1=VGhpcyBpcyBhIHVuaWNvZGUgbWVtbyDinKjwn6aE8J-PhvCfjok";
|
||||||
let i6r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_6);
|
let i6r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_6);
|
||||||
assert!(i6r.is_err());
|
assert!(i6r.is_err());
|
||||||
|
|
||||||
// invalid; amount component exceeds an i64
|
// invalid; amount component exceeds an i64
|
||||||
// 9223372036854775808 = i64::MAX + 1
|
// 9223372036854775808 = i64::MAX + 1
|
||||||
let invalid_7 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=9223372036854775808";
|
let invalid_7 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=9223372036854775808";
|
||||||
let i7r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_7);
|
let i7r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_7);
|
||||||
assert!(i7r.is_err());
|
assert!(i7r.is_err());
|
||||||
|
|
||||||
// invalid; amount component wraps into a valid small positive i64
|
// invalid; amount component wraps into a valid small positive i64
|
||||||
// 18446744073709551624
|
// 18446744073709551624
|
||||||
let invalid_7a = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=18446744073709551624";
|
let invalid_7a = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=18446744073709551624";
|
||||||
let i7ar = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_7a);
|
let i7ar = TransactionRequest::from_uri(&TEST_NETWORK, invalid_7a);
|
||||||
assert!(i7ar.is_err());
|
assert!(i7ar.is_err());
|
||||||
|
|
||||||
// invalid; amount component is MAX_MONEY
|
// invalid; amount component is MAX_MONEY
|
||||||
// 21000000.00000001
|
// 21000000.00000001
|
||||||
let invalid_8 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=21000000.00000001";
|
let invalid_8 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=21000000.00000001";
|
||||||
let i8r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_8);
|
let i8r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_8);
|
||||||
assert!(i8r.is_err());
|
assert!(i8r.is_err());
|
||||||
|
|
||||||
// invalid; negative amount
|
// invalid; negative amount
|
||||||
let invalid_9 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=-1";
|
let invalid_9 = "zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=-1";
|
||||||
let i9r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_9);
|
let i9r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_9);
|
||||||
assert!(i9r.is_err());
|
assert!(i9r.is_err());
|
||||||
|
|
||||||
// invalid; parameter index too large
|
// invalid; parameter index too large
|
||||||
let invalid_10 =
|
let invalid_10 =
|
||||||
"zcash:?amount.10000=1.23&address.10000=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
"zcash:?amount.10000=1.23&address.10000=tmEZhbWHTpdKMw5it8YDspUXSMGQyFwovpU";
|
||||||
let i10r = TransactionRequest::from_uri(&TEST_NETWORK, &invalid_10);
|
let i10r = TransactionRequest::from_uri(&TEST_NETWORK, invalid_10);
|
||||||
assert!(i10r.is_err());
|
assert!(i10r.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,7 +323,10 @@ mod tests {
|
||||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||||
|
|
||||||
// Account balance should be zero
|
// Account balance should be zero
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
|
|
||||||
// Create fake CompactBlocks sending value to the address
|
// Create fake CompactBlocks sending value to the address
|
||||||
let value = Amount::from_u64(5).unwrap();
|
let value = Amount::from_u64(5).unwrap();
|
||||||
|
@ -346,7 +349,7 @@ mod tests {
|
||||||
|
|
||||||
// Account balance should reflect both received notes
|
// Account balance should reflect both received notes
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value + value2).unwrap()
|
(value + value2).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -355,7 +358,7 @@ mod tests {
|
||||||
|
|
||||||
// Account balance should be unaltered
|
// Account balance should be unaltered
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value + value2).unwrap()
|
(value + value2).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -363,14 +366,14 @@ mod tests {
|
||||||
rewind_to_height(&db_data, sapling_activation_height()).unwrap();
|
rewind_to_height(&db_data, sapling_activation_height()).unwrap();
|
||||||
|
|
||||||
// Account balance should only contain the first received note
|
// Account balance should only contain the first received note
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
// Scan the cache again
|
// Scan the cache again
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
|
|
||||||
// Account balance should again reflect both received notes
|
// Account balance should again reflect both received notes
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value + value2).unwrap()
|
(value + value2).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -399,7 +402,7 @@ mod tests {
|
||||||
insert_into_cache(&db_cache, &cb1);
|
insert_into_cache(&db_cache, &cb1);
|
||||||
let mut db_write = db_data.get_update_ops().unwrap();
|
let mut db_write = db_data.get_update_ops().unwrap();
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
// We cannot scan a block of height SAPLING_ACTIVATION_HEIGHT + 2 next
|
// We cannot scan a block of height SAPLING_ACTIVATION_HEIGHT + 2 next
|
||||||
let (cb2, _) = fake_compact_block(
|
let (cb2, _) = fake_compact_block(
|
||||||
|
@ -429,7 +432,7 @@ mod tests {
|
||||||
insert_into_cache(&db_cache, &cb2);
|
insert_into_cache(&db_cache, &cb2);
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
Amount::from_u64(150_000).unwrap()
|
Amount::from_u64(150_000).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -448,7 +451,10 @@ mod tests {
|
||||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||||
|
|
||||||
// Account balance should be zero
|
// Account balance should be zero
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
|
|
||||||
// Create a fake CompactBlock sending value to the address
|
// Create a fake CompactBlock sending value to the address
|
||||||
let value = Amount::from_u64(5).unwrap();
|
let value = Amount::from_u64(5).unwrap();
|
||||||
|
@ -465,7 +471,7 @@ mod tests {
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
|
|
||||||
// Account balance should reflect the received note
|
// Account balance should reflect the received note
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
// Create a second fake CompactBlock sending more value to the address
|
// Create a second fake CompactBlock sending more value to the address
|
||||||
let value2 = Amount::from_u64(7).unwrap();
|
let value2 = Amount::from_u64(7).unwrap();
|
||||||
|
@ -478,7 +484,7 @@ mod tests {
|
||||||
|
|
||||||
// Account balance should reflect both received notes
|
// Account balance should reflect both received notes
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value + value2).unwrap()
|
(value + value2).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -497,7 +503,10 @@ mod tests {
|
||||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||||
|
|
||||||
// Account balance should be zero
|
// Account balance should be zero
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
|
|
||||||
// Create a fake CompactBlock sending value to the address
|
// Create a fake CompactBlock sending value to the address
|
||||||
let value = Amount::from_u64(5).unwrap();
|
let value = Amount::from_u64(5).unwrap();
|
||||||
|
@ -514,7 +523,7 @@ mod tests {
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
|
|
||||||
// Account balance should reflect the received note
|
// Account balance should reflect the received note
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
// Create a second fake CompactBlock spending value from the address
|
// Create a second fake CompactBlock spending value from the address
|
||||||
let extsk2 = ExtendedSpendingKey::master(&[0]);
|
let extsk2 = ExtendedSpendingKey::master(&[0]);
|
||||||
|
@ -537,7 +546,7 @@ mod tests {
|
||||||
|
|
||||||
// Account balance should equal the change
|
// Account balance should equal the change
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value - value2).unwrap()
|
(value - value2).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,29 +212,29 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
|
|
||||||
fn block_height_extrema(&self) -> Result<Option<(BlockHeight, BlockHeight)>, Self::Error> {
|
fn block_height_extrema(&self) -> Result<Option<(BlockHeight, BlockHeight)>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::block_height_extrema(&self).map_err(SqliteClientError::from)
|
wallet::block_height_extrema(self).map_err(SqliteClientError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> {
|
fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_block_hash(&self, block_height).map_err(SqliteClientError::from)
|
wallet::get_block_hash(self, block_height).map_err(SqliteClientError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tx_height(&self, txid: TxId) -> Result<Option<BlockHeight>, Self::Error> {
|
fn get_tx_height(&self, txid: TxId) -> Result<Option<BlockHeight>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_tx_height(&self, txid).map_err(SqliteClientError::from)
|
wallet::get_tx_height(self, txid).map_err(SqliteClientError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_extended_full_viewing_keys(
|
fn get_extended_full_viewing_keys(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<HashMap<AccountId, ExtendedFullViewingKey>, Self::Error> {
|
) -> Result<HashMap<AccountId, ExtendedFullViewingKey>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_extended_full_viewing_keys(&self)
|
wallet::get_extended_full_viewing_keys(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_address(&self, account: AccountId) -> Result<Option<PaymentAddress>, Self::Error> {
|
fn get_address(&self, account: AccountId) -> Result<Option<PaymentAddress>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_address(&self, account)
|
wallet::get_address(self, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_account_extfvk(
|
fn is_valid_account_extfvk(
|
||||||
|
@ -243,7 +243,7 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
extfvk: &ExtendedFullViewingKey,
|
extfvk: &ExtendedFullViewingKey,
|
||||||
) -> Result<bool, Self::Error> {
|
) -> Result<bool, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::is_valid_account_extfvk(&self, account, extfvk)
|
wallet::is_valid_account_extfvk(self, account, extfvk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_balance_at(
|
fn get_balance_at(
|
||||||
|
@ -252,12 +252,12 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
anchor_height: BlockHeight,
|
anchor_height: BlockHeight,
|
||||||
) -> Result<Amount, Self::Error> {
|
) -> Result<Amount, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_balance_at(&self, account, anchor_height)
|
wallet::get_balance_at(self, account, anchor_height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_transaction(&self, id_tx: i64) -> Result<Transaction, Self::Error> {
|
fn get_transaction(&self, id_tx: i64) -> Result<Transaction, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_transaction(&self, id_tx)
|
wallet::get_transaction(self, id_tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memo(&self, id_note: Self::NoteRef) -> Result<Memo, Self::Error> {
|
fn get_memo(&self, id_note: Self::NoteRef) -> Result<Memo, Self::Error> {
|
||||||
|
@ -273,7 +273,7 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
block_height: BlockHeight,
|
block_height: BlockHeight,
|
||||||
) -> Result<Option<CommitmentTree<Node>>, Self::Error> {
|
) -> Result<Option<CommitmentTree<Node>>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_commitment_tree(&self, block_height)
|
wallet::get_commitment_tree(self, block_height)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
|
@ -282,17 +282,17 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
block_height: BlockHeight,
|
block_height: BlockHeight,
|
||||||
) -> Result<Vec<(Self::NoteRef, IncrementalWitness<Node>)>, Self::Error> {
|
) -> Result<Vec<(Self::NoteRef, IncrementalWitness<Node>)>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_witnesses(&self, block_height)
|
wallet::get_witnesses(self, block_height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error> {
|
fn get_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_nullifiers(&self)
|
wallet::get_nullifiers(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error> {
|
fn get_all_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::get_all_nullifiers(&self)
|
wallet::get_all_nullifiers(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_spendable_sapling_notes(
|
fn get_spendable_sapling_notes(
|
||||||
|
@ -301,7 +301,7 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
anchor_height: BlockHeight,
|
anchor_height: BlockHeight,
|
||||||
) -> Result<Vec<SpendableNote>, Self::Error> {
|
) -> Result<Vec<SpendableNote>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::transact::get_spendable_sapling_notes(&self, account, anchor_height)
|
wallet::transact::get_spendable_sapling_notes(self, account, anchor_height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_spendable_sapling_notes(
|
fn select_spendable_sapling_notes(
|
||||||
|
@ -311,12 +311,7 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
|
||||||
anchor_height: BlockHeight,
|
anchor_height: BlockHeight,
|
||||||
) -> Result<Vec<SpendableNote>, Self::Error> {
|
) -> Result<Vec<SpendableNote>, Self::Error> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
wallet::transact::select_spendable_sapling_notes(
|
wallet::transact::select_spendable_sapling_notes(self, account, target_value, anchor_height)
|
||||||
&self,
|
|
||||||
account,
|
|
||||||
target_value,
|
|
||||||
anchor_height,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +322,7 @@ impl<P: consensus::Parameters> WalletReadTransparent for WalletDb<P> {
|
||||||
address: &TransparentAddress,
|
address: &TransparentAddress,
|
||||||
max_height: BlockHeight,
|
max_height: BlockHeight,
|
||||||
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
|
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
|
||||||
wallet::get_unspent_transparent_outputs(&self, address, max_height)
|
wallet::get_unspent_transparent_outputs(self, address, max_height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,12 +514,12 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
|
||||||
block.block_height,
|
block.block_height,
|
||||||
block.block_hash,
|
block.block_hash,
|
||||||
block.block_time,
|
block.block_time,
|
||||||
&block.commitment_tree,
|
block.commitment_tree,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut new_witnesses = vec![];
|
let mut new_witnesses = vec![];
|
||||||
for tx in block.transactions {
|
for tx in block.transactions {
|
||||||
let tx_row = wallet::put_tx_meta(up, &tx, block.block_height)?;
|
let tx_row = wallet::put_tx_meta(up, tx, block.block_height)?;
|
||||||
|
|
||||||
// Mark notes as spent and remove them from the scanning cache
|
// Mark notes as spent and remove them from the scanning cache
|
||||||
for spend in &tx.shielded_spends {
|
for spend in &tx.shielded_spends {
|
||||||
|
@ -624,7 +619,7 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
|
||||||
fn store_sent_tx(&mut self, sent_tx: &SentTransaction) -> Result<Self::TxRef, Self::Error> {
|
fn store_sent_tx(&mut self, sent_tx: &SentTransaction) -> Result<Self::TxRef, Self::Error> {
|
||||||
// Update the database atomically, to ensure the result is internally consistent.
|
// Update the database atomically, to ensure the result is internally consistent.
|
||||||
self.transactionally(|up| {
|
self.transactionally(|up| {
|
||||||
let tx_ref = wallet::put_tx_data(up, &sent_tx.tx, Some(sent_tx.created))?;
|
let tx_ref = wallet::put_tx_data(up, sent_tx.tx, Some(sent_tx.created))?;
|
||||||
|
|
||||||
// Mark notes as spent.
|
// Mark notes as spent.
|
||||||
//
|
//
|
||||||
|
@ -642,7 +637,7 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
for utxo_outpoint in &sent_tx.utxos_spent {
|
for utxo_outpoint in &sent_tx.utxos_spent {
|
||||||
wallet::mark_transparent_utxo_spent(up, tx_ref, &utxo_outpoint)?;
|
wallet::mark_transparent_utxo_spent(up, tx_ref, utxo_outpoint)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for output in &sent_tx.outputs {
|
for output in &sent_tx.outputs {
|
||||||
|
@ -652,7 +647,7 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
|
||||||
tx_ref,
|
tx_ref,
|
||||||
output.output_index,
|
output.output_index,
|
||||||
sent_tx.account,
|
sent_tx.account,
|
||||||
&addr,
|
addr,
|
||||||
output.value,
|
output.value,
|
||||||
output.memo.as_ref(),
|
output.memo.as_ref(),
|
||||||
)?,
|
)?,
|
||||||
|
@ -661,7 +656,7 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
|
||||||
tx_ref,
|
tx_ref,
|
||||||
output.output_index,
|
output.output_index,
|
||||||
sent_tx.account,
|
sent_tx.account,
|
||||||
&addr,
|
addr,
|
||||||
output.value,
|
output.value,
|
||||||
)?,
|
)?,
|
||||||
}
|
}
|
||||||
|
@ -785,7 +780,7 @@ mod tests {
|
||||||
db_data: &WalletDb<Network>,
|
db_data: &WalletDb<Network>,
|
||||||
) -> (ExtendedFullViewingKey, Option<TransparentAddress>) {
|
) -> (ExtendedFullViewingKey, Option<TransparentAddress>) {
|
||||||
let seed = [0u8; 32];
|
let seed = [0u8; 32];
|
||||||
let account = AccountId(0);
|
let account = AccountId::from(0);
|
||||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ impl ShieldedOutput for DecryptedOutput {
|
||||||
///
|
///
|
||||||
/// let data_file = NamedTempFile::new().unwrap();
|
/// let data_file = NamedTempFile::new().unwrap();
|
||||||
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
||||||
/// let addr = get_address(&db, AccountId(0));
|
/// let addr = get_address(&db, AccountId::from(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_address instead."
|
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_address instead."
|
||||||
|
@ -158,7 +158,7 @@ pub fn get_address<P: consensus::Parameters>(
|
||||||
let addr: String = wdb.conn.query_row(
|
let addr: String = wdb.conn.query_row(
|
||||||
"SELECT address FROM accounts
|
"SELECT address FROM accounts
|
||||||
WHERE account = ?",
|
WHERE account = ?",
|
||||||
&[account.0],
|
&[u32::from(account)],
|
||||||
|row| row.get(0),
|
|row| row.get(0),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ pub fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||||
|
|
||||||
let rows = stmt_fetch_accounts
|
let rows = stmt_fetch_accounts
|
||||||
.query_map(NO_PARAMS, |row| {
|
.query_map(NO_PARAMS, |row| {
|
||||||
let acct = row.get(0).map(AccountId)?;
|
let acct: u32 = row.get(0)?;
|
||||||
let extfvk = row.get(1).map(|extfvk: String| {
|
let extfvk = row.get(1).map(|extfvk: String| {
|
||||||
decode_extended_full_viewing_key(
|
decode_extended_full_viewing_key(
|
||||||
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
||||||
|
@ -192,7 +192,7 @@ pub fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||||
.and_then(|k| k.ok_or(SqliteClientError::IncorrectHrpExtFvk))
|
.and_then(|k| k.ok_or(SqliteClientError::IncorrectHrpExtFvk))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok((acct, extfvk))
|
Ok((AccountId::from(acct), extfvk))
|
||||||
})
|
})
|
||||||
.map_err(SqliteClientError::from)?;
|
.map_err(SqliteClientError::from)?;
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ pub fn is_valid_account_extfvk<P: consensus::Parameters>(
|
||||||
wdb.conn
|
wdb.conn
|
||||||
.prepare("SELECT * FROM accounts WHERE account = ? AND extfvk = ?")?
|
.prepare("SELECT * FROM accounts WHERE account = ? AND extfvk = ?")?
|
||||||
.exists(&[
|
.exists(&[
|
||||||
account.0.to_sql()?,
|
u32::from(account).to_sql()?,
|
||||||
encode_extended_full_viewing_key(
|
encode_extended_full_viewing_key(
|
||||||
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
wdb.params.hrp_sapling_extended_full_viewing_key(),
|
||||||
extfvk,
|
extfvk,
|
||||||
|
@ -253,7 +253,7 @@ pub fn is_valid_account_extfvk<P: consensus::Parameters>(
|
||||||
///
|
///
|
||||||
/// let data_file = NamedTempFile::new().unwrap();
|
/// let data_file = NamedTempFile::new().unwrap();
|
||||||
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
||||||
/// let addr = get_balance(&db, AccountId(0));
|
/// let addr = get_balance(&db, AccountId::from(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_balance_at instead."
|
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_balance_at instead."
|
||||||
|
@ -263,7 +263,7 @@ pub fn get_balance<P>(wdb: &WalletDb<P>, account: AccountId) -> Result<Amount, S
|
||||||
"SELECT SUM(value) FROM received_notes
|
"SELECT SUM(value) FROM received_notes
|
||||||
INNER JOIN transactions ON transactions.id_tx = received_notes.tx
|
INNER JOIN transactions ON transactions.id_tx = received_notes.tx
|
||||||
WHERE account = ? AND spent IS NULL AND transactions.block IS NOT NULL",
|
WHERE account = ? AND spent IS NULL AND transactions.block IS NOT NULL",
|
||||||
&[account.0],
|
&[u32::from(account)],
|
||||||
|row| row.get(0).or(Ok(0)),
|
|row| row.get(0).or(Ok(0)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ pub fn get_balance<P>(wdb: &WalletDb<P>, account: AccountId) -> Result<Amount, S
|
||||||
///
|
///
|
||||||
/// let data_file = NamedTempFile::new().unwrap();
|
/// let data_file = NamedTempFile::new().unwrap();
|
||||||
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
/// let db = WalletDb::for_path(data_file, Network::TestNetwork).unwrap();
|
||||||
/// let addr = get_balance_at(&db, AccountId(0), BlockHeight::from_u32(0));
|
/// let addr = get_balance_at(&db, AccountId::from(0), BlockHeight::from_u32(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_balance_at instead."
|
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_balance_at instead."
|
||||||
|
@ -308,7 +308,7 @@ pub fn get_balance_at<P>(
|
||||||
"SELECT SUM(value) FROM received_notes
|
"SELECT SUM(value) FROM received_notes
|
||||||
INNER JOIN transactions ON transactions.id_tx = received_notes.tx
|
INNER JOIN transactions ON transactions.id_tx = received_notes.tx
|
||||||
WHERE account = ? AND spent IS NULL AND transactions.block <= ?",
|
WHERE account = ? AND spent IS NULL AND transactions.block <= ?",
|
||||||
&[account.0, u32::from(anchor_height)],
|
&[u32::from(account), u32::from(anchor_height)],
|
||||||
|row| row.get(0).or(Ok(0)),
|
|row| row.get(0).or(Ok(0)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -564,12 +564,12 @@ pub(crate) fn rewind_to_height<P: consensus::Parameters>(
|
||||||
.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| {
|
.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| {
|
||||||
row.get(0)
|
row.get(0)
|
||||||
.map(|h: u32| h.into())
|
.map(|h: u32| h.into())
|
||||||
.or(Ok(sapling_activation_height - 1))
|
.or_else(|_| Ok(sapling_activation_height - 1))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if block_height < last_scanned_height - PRUNING_HEIGHT {
|
if block_height < last_scanned_height - PRUNING_HEIGHT {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
if let Some(h) = get_rewind_height(&wdb)? {
|
if let Some(h) = get_rewind_height(wdb)? {
|
||||||
if block_height > h {
|
if block_height > h {
|
||||||
return Err(SqliteClientError::RequestedRewindInvalid(h, block_height));
|
return Err(SqliteClientError::RequestedRewindInvalid(h, block_height));
|
||||||
}
|
}
|
||||||
|
@ -724,9 +724,12 @@ pub fn get_nullifiers<P>(
|
||||||
WHERE block IS NULL",
|
WHERE block IS NULL",
|
||||||
)?;
|
)?;
|
||||||
let nullifiers = stmt_fetch_nullifiers.query_map(NO_PARAMS, |row| {
|
let nullifiers = stmt_fetch_nullifiers.query_map(NO_PARAMS, |row| {
|
||||||
let account = AccountId(row.get(1)?);
|
let account: u32 = row.get(1)?;
|
||||||
let nf_bytes: Vec<u8> = row.get(2)?;
|
let nf_bytes: Vec<u8> = row.get(2)?;
|
||||||
Ok((account, Nullifier::from_slice(&nf_bytes).unwrap()))
|
Ok((
|
||||||
|
AccountId::from(account),
|
||||||
|
Nullifier::from_slice(&nf_bytes).unwrap(),
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
|
let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
|
||||||
|
@ -743,9 +746,12 @@ pub(crate) fn get_all_nullifiers<P>(
|
||||||
FROM received_notes rn",
|
FROM received_notes rn",
|
||||||
)?;
|
)?;
|
||||||
let nullifiers = stmt_fetch_nullifiers.query_map(NO_PARAMS, |row| {
|
let nullifiers = stmt_fetch_nullifiers.query_map(NO_PARAMS, |row| {
|
||||||
let account = AccountId(row.get(1)?);
|
let account: u32 = row.get(1)?;
|
||||||
let nf_bytes: Vec<u8> = row.get(2)?;
|
let nf_bytes: Vec<u8> = row.get(2)?;
|
||||||
Ok((account, Nullifier::from_slice(&nf_bytes).unwrap()))
|
Ok((
|
||||||
|
AccountId::from(account),
|
||||||
|
Nullifier::from_slice(&nf_bytes).unwrap(),
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
|
let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
|
||||||
|
@ -778,13 +784,13 @@ pub(crate) fn get_unspent_transparent_outputs<P: consensus::Parameters>(
|
||||||
|
|
||||||
let mut txid_bytes = [0u8; 32];
|
let mut txid_bytes = [0u8; 32];
|
||||||
txid_bytes.copy_from_slice(&id);
|
txid_bytes.copy_from_slice(&id);
|
||||||
let index: i32 = row.get(1)?;
|
let index: u32 = row.get(1)?;
|
||||||
let script_pubkey = Script(row.get(2)?);
|
let script_pubkey = Script(row.get(2)?);
|
||||||
let value = Amount::from_i64(row.get(3)?).unwrap();
|
let value = Amount::from_i64(row.get(3)?).unwrap();
|
||||||
let height: u32 = row.get(4)?;
|
let height: u32 = row.get(4)?;
|
||||||
|
|
||||||
Ok(WalletTransparentOutput {
|
Ok(WalletTransparentOutput {
|
||||||
outpoint: OutPoint::new(txid_bytes, index as u32),
|
outpoint: OutPoint::new(txid_bytes, index),
|
||||||
txout: TxOut {
|
txout: TxOut {
|
||||||
value,
|
value,
|
||||||
script_pubkey,
|
script_pubkey,
|
||||||
|
@ -920,14 +926,14 @@ pub(crate) fn mark_transparent_utxo_spent<'a, P>(
|
||||||
outpoint: &OutPoint,
|
outpoint: &OutPoint,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let sql_args: &[(&str, &dyn ToSql)] = &[
|
let sql_args: &[(&str, &dyn ToSql)] = &[
|
||||||
(&":spent_in_tx", &tx_ref),
|
(":spent_in_tx", &tx_ref),
|
||||||
(&":prevout_txid", &outpoint.hash().to_vec()),
|
(":prevout_txid", &outpoint.hash().to_vec()),
|
||||||
(&":prevout_idx", &outpoint.n()),
|
(":prevout_idx", &outpoint.n()),
|
||||||
];
|
];
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
.stmt_mark_transparent_utxo_spent
|
.stmt_mark_transparent_utxo_spent
|
||||||
.execute_named(&sql_args)?;
|
.execute_named(sql_args)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -940,19 +946,19 @@ pub(crate) fn put_received_transparent_utxo<'a, P: consensus::Parameters>(
|
||||||
) -> Result<UtxoId, SqliteClientError> {
|
) -> Result<UtxoId, SqliteClientError> {
|
||||||
let sql_args: &[(&str, &dyn ToSql)] = &[
|
let sql_args: &[(&str, &dyn ToSql)] = &[
|
||||||
(
|
(
|
||||||
&":address",
|
":address",
|
||||||
&output.address().encode(&stmts.wallet_db.params),
|
&output.address().encode(&stmts.wallet_db.params),
|
||||||
),
|
),
|
||||||
(&":prevout_txid", &output.outpoint.hash().to_vec()),
|
(":prevout_txid", &output.outpoint.hash().to_vec()),
|
||||||
(&":prevout_idx", &output.outpoint.n()),
|
(":prevout_idx", &output.outpoint.n()),
|
||||||
(&":script", &output.txout.script_pubkey.0),
|
(":script", &output.txout.script_pubkey.0),
|
||||||
(&":value_zat", &i64::from(output.txout.value)),
|
(":value_zat", &i64::from(output.txout.value)),
|
||||||
(&":height", &u32::from(output.height)),
|
(":height", &u32::from(output.height)),
|
||||||
];
|
];
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
.stmt_insert_received_transparent_utxo
|
.stmt_insert_received_transparent_utxo
|
||||||
.execute_named(&sql_args)?;
|
.execute_named(sql_args)?;
|
||||||
|
|
||||||
Ok(UtxoId(stmts.wallet_db.conn.last_insert_rowid()))
|
Ok(UtxoId(stmts.wallet_db.conn.last_insert_rowid()))
|
||||||
}
|
}
|
||||||
|
@ -969,11 +975,11 @@ pub fn delete_utxos_above<'a, P: consensus::Parameters>(
|
||||||
height: BlockHeight,
|
height: BlockHeight,
|
||||||
) -> Result<usize, SqliteClientError> {
|
) -> Result<usize, SqliteClientError> {
|
||||||
let sql_args: &[(&str, &dyn ToSql)] = &[
|
let sql_args: &[(&str, &dyn ToSql)] = &[
|
||||||
(&":address", &taddr.encode(&stmts.wallet_db.params)),
|
(":address", &taddr.encode(&stmts.wallet_db.params)),
|
||||||
(&":above_height", &u32::from(height)),
|
(":above_height", &u32::from(height)),
|
||||||
];
|
];
|
||||||
|
|
||||||
let rows = stmts.stmt_delete_utxos.execute_named(&sql_args)?;
|
let rows = stmts.stmt_delete_utxos.execute_named(sql_args)?;
|
||||||
|
|
||||||
Ok(rows)
|
Ok(rows)
|
||||||
}
|
}
|
||||||
|
@ -993,7 +999,7 @@ pub fn put_received_note<'a, P, T: ShieldedOutput>(
|
||||||
tx_ref: i64,
|
tx_ref: i64,
|
||||||
) -> Result<NoteId, SqliteClientError> {
|
) -> Result<NoteId, SqliteClientError> {
|
||||||
let rcm = output.note().rcm().to_repr();
|
let rcm = output.note().rcm().to_repr();
|
||||||
let account = output.account().0 as i64;
|
let account = u32::from(output.account());
|
||||||
let diversifier = output.to().diversifier().0.to_vec();
|
let diversifier = output.to().diversifier().0.to_vec();
|
||||||
let value = output.note().value as i64;
|
let value = output.note().value as i64;
|
||||||
let rcm = rcm.as_ref();
|
let rcm = rcm.as_ref();
|
||||||
|
@ -1004,21 +1010,21 @@ pub fn put_received_note<'a, P, T: ShieldedOutput>(
|
||||||
let nf_bytes = output.nullifier().map(|nf| nf.0.to_vec());
|
let nf_bytes = output.nullifier().map(|nf| nf.0.to_vec());
|
||||||
|
|
||||||
let sql_args: &[(&str, &dyn ToSql)] = &[
|
let sql_args: &[(&str, &dyn ToSql)] = &[
|
||||||
(&":account", &account),
|
(":account", &account),
|
||||||
(&":diversifier", &diversifier),
|
(":diversifier", &diversifier),
|
||||||
(&":value", &value),
|
(":value", &value),
|
||||||
(&":rcm", &rcm),
|
(":rcm", &rcm),
|
||||||
(&":nf", &nf_bytes),
|
(":nf", &nf_bytes),
|
||||||
(&":memo", &memo),
|
(":memo", &memo),
|
||||||
(&":is_change", &is_change),
|
(":is_change", &is_change),
|
||||||
(&":tx", &tx),
|
(":tx", &tx),
|
||||||
(&":output_index", &output_index),
|
(":output_index", &output_index),
|
||||||
];
|
];
|
||||||
|
|
||||||
// First try updating an existing received note into the database.
|
// First try updating an existing received note into the database.
|
||||||
if stmts.stmt_update_received_note.execute_named(&sql_args)? == 0 {
|
if stmts.stmt_update_received_note.execute_named(sql_args)? == 0 {
|
||||||
// It isn't there, so insert our note into the database.
|
// It isn't there, so insert our note into the database.
|
||||||
stmts.stmt_insert_received_note.execute_named(&sql_args)?;
|
stmts.stmt_insert_received_note.execute_named(sql_args)?;
|
||||||
|
|
||||||
Ok(NoteId::ReceivedNoteId(
|
Ok(NoteId::ReceivedNoteId(
|
||||||
stmts.wallet_db.conn.last_insert_rowid(),
|
stmts.wallet_db.conn.last_insert_rowid(),
|
||||||
|
@ -1099,8 +1105,8 @@ pub fn put_sent_note<'a, P: consensus::Parameters>(
|
||||||
let ivalue: i64 = value.into();
|
let ivalue: i64 = value.into();
|
||||||
// Try updating an existing sent note.
|
// Try updating an existing sent note.
|
||||||
if stmts.stmt_update_sent_note.execute(params![
|
if stmts.stmt_update_sent_note.execute(params![
|
||||||
account.0 as i64,
|
u32::from(account),
|
||||||
encode_payment_address_p(&stmts.wallet_db.params, &to),
|
encode_payment_address_p(&stmts.wallet_db.params, to),
|
||||||
ivalue,
|
ivalue,
|
||||||
&memo.map(|m| m.as_slice()),
|
&memo.map(|m| m.as_slice()),
|
||||||
tx_ref,
|
tx_ref,
|
||||||
|
@ -1109,7 +1115,7 @@ pub fn put_sent_note<'a, P: consensus::Parameters>(
|
||||||
])? == 0
|
])? == 0
|
||||||
{
|
{
|
||||||
// It isn't there, so insert.
|
// It isn't there, so insert.
|
||||||
insert_sent_note(stmts, tx_ref, output_index, account, &to, value, memo)?
|
insert_sent_note(stmts, tx_ref, output_index, account, to, value, memo)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1134,8 +1140,8 @@ pub fn put_sent_utxo<'a, P: consensus::Parameters>(
|
||||||
let ivalue: i64 = value.into();
|
let ivalue: i64 = value.into();
|
||||||
// Try updating an existing sent UTXO.
|
// Try updating an existing sent UTXO.
|
||||||
if stmts.stmt_update_sent_note.execute(params![
|
if stmts.stmt_update_sent_note.execute(params![
|
||||||
account.0 as i64,
|
u32::from(account),
|
||||||
encode_transparent_address_p(&stmts.wallet_db.params, &to),
|
encode_transparent_address_p(&stmts.wallet_db.params, to),
|
||||||
ivalue,
|
ivalue,
|
||||||
(None::<&[u8]>),
|
(None::<&[u8]>),
|
||||||
tx_ref,
|
tx_ref,
|
||||||
|
@ -1144,7 +1150,7 @@ pub fn put_sent_utxo<'a, P: consensus::Parameters>(
|
||||||
])? == 0
|
])? == 0
|
||||||
{
|
{
|
||||||
// It isn't there, so insert.
|
// It isn't there, so insert.
|
||||||
insert_sent_utxo(stmts, tx_ref, output_index, account, &to, value)?
|
insert_sent_utxo(stmts, tx_ref, output_index, account, to, value)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1176,7 +1182,7 @@ pub fn insert_sent_note<'a, P: consensus::Parameters>(
|
||||||
tx_ref,
|
tx_ref,
|
||||||
PoolType::Sapling.typecode(),
|
PoolType::Sapling.typecode(),
|
||||||
(output_index as i64),
|
(output_index as i64),
|
||||||
account.0,
|
u32::from(account),
|
||||||
to_str,
|
to_str,
|
||||||
ivalue,
|
ivalue,
|
||||||
memo.map(|m| m.as_slice().to_vec()),
|
memo.map(|m| m.as_slice().to_vec()),
|
||||||
|
@ -1204,8 +1210,8 @@ pub fn insert_sent_utxo<'a, P: consensus::Parameters>(
|
||||||
stmts.stmt_insert_sent_note.execute(params![
|
stmts.stmt_insert_sent_note.execute(params![
|
||||||
tx_ref,
|
tx_ref,
|
||||||
PoolType::Transparent.typecode(),
|
PoolType::Transparent.typecode(),
|
||||||
(output_index as i64),
|
output_index as i64,
|
||||||
account.0,
|
u32::from(account),
|
||||||
to_str,
|
to_str,
|
||||||
ivalue,
|
ivalue,
|
||||||
(None::<&[u8]>),
|
(None::<&[u8]>),
|
||||||
|
@ -1237,13 +1243,19 @@ mod tests {
|
||||||
tests::init_test_accounts_table(&db_data);
|
tests::init_test_accounts_table(&db_data);
|
||||||
|
|
||||||
// The account should be empty
|
// The account should be empty
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
|
|
||||||
// We can't get an anchor height, as we have not scanned any blocks.
|
// We can't get an anchor height, as we have not scanned any blocks.
|
||||||
assert_eq!((&db_data).get_target_and_anchor_heights(10).unwrap(), None);
|
assert_eq!((&db_data).get_target_and_anchor_heights(10).unwrap(), None);
|
||||||
|
|
||||||
// An invalid account has zero balance
|
// An invalid account has zero balance
|
||||||
assert!(get_address(&db_data, AccountId(1)).is_err());
|
assert!(get_address(&db_data, AccountId::from(1)).is_err());
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ pub fn init_wallet_db<P>(wdb: &WalletDb<P>) -> Result<(), rusqlite::Error> {
|
||||||
/// init_wallet_db(&db_data).unwrap();
|
/// init_wallet_db(&db_data).unwrap();
|
||||||
///
|
///
|
||||||
/// let seed = [0u8; 32]; // insecure; replace with a strong random seed
|
/// let seed = [0u8; 32]; // insecure; replace with a strong random seed
|
||||||
/// let account = AccountId(0);
|
/// let account = AccountId::from(0);
|
||||||
/// let extsk = sapling::spending_key(&seed, Network::TestNetwork.coin_type(), account);
|
/// let extsk = sapling::spending_key(&seed, Network::TestNetwork.coin_type(), account);
|
||||||
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
|
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
/// let ufvk = UnifiedFullViewingKey::new(account, None, Some(extfvk)).unwrap();
|
/// let ufvk = UnifiedFullViewingKey::new(account, None, Some(extfvk)).unwrap();
|
||||||
|
@ -222,7 +222,12 @@ pub fn init_accounts_table<P: consensus::Parameters>(
|
||||||
wdb.conn.execute(
|
wdb.conn.execute(
|
||||||
"INSERT INTO accounts (account, extfvk, address, transparent_address)
|
"INSERT INTO accounts (account, extfvk, address, transparent_address)
|
||||||
VALUES (?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?)",
|
||||||
params![key.account().0, extfvk_str, address_str, taddress_str,],
|
params![
|
||||||
|
u32::from(key.account()),
|
||||||
|
extfvk_str,
|
||||||
|
address_str,
|
||||||
|
taddress_str,
|
||||||
|
],
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
wdb.conn.execute("COMMIT", NO_PARAMS)?;
|
wdb.conn.execute("COMMIT", NO_PARAMS)?;
|
||||||
|
@ -323,7 +328,7 @@ mod tests {
|
||||||
init_accounts_table(&db_data, &[]).unwrap();
|
init_accounts_table(&db_data, &[]).unwrap();
|
||||||
|
|
||||||
let seed = [0u8; 32];
|
let seed = [0u8; 32];
|
||||||
let account = AccountId(0);
|
let account = AccountId::from(0);
|
||||||
|
|
||||||
// First call with data should initialise the accounts table
|
// First call with data should initialise the accounts table
|
||||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
||||||
|
@ -387,14 +392,14 @@ mod tests {
|
||||||
let seed = [0u8; 32];
|
let seed = [0u8; 32];
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let account_id = AccountId(0);
|
let account_id = AccountId::from(0);
|
||||||
let usk = UnifiedSpendingKey::from_seed(&tests::network(), &seed, account_id).unwrap();
|
let usk = UnifiedSpendingKey::from_seed(&tests::network(), &seed, account_id).unwrap();
|
||||||
let ufvk = usk.to_unified_full_viewing_key();
|
let ufvk = usk.to_unified_full_viewing_key();
|
||||||
let expected_address = ufvk.sapling().unwrap().default_address().1;
|
let expected_address = ufvk.sapling().unwrap().default_address().1;
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
|
|
||||||
// The account's address should be in the data DB
|
// The account's address should be in the data DB
|
||||||
let pa = get_address(&db_data, AccountId(0)).unwrap();
|
let pa = get_address(&db_data, AccountId::from(0)).unwrap();
|
||||||
assert_eq!(pa.unwrap(), expected_address);
|
assert_eq!(pa.unwrap(), expected_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub fn get_spendable_sapling_notes<P>(
|
||||||
// Select notes
|
// Select notes
|
||||||
let notes = stmt_select_notes.query_and_then_named::<_, SqliteClientError, _>(
|
let notes = stmt_select_notes.query_and_then_named::<_, SqliteClientError, _>(
|
||||||
named_params![
|
named_params![
|
||||||
":account": &i64::from(account.0),
|
":account": &u32::from(account),
|
||||||
":anchor_height": &u32::from(anchor_height),
|
":anchor_height": &u32::from(anchor_height),
|
||||||
],
|
],
|
||||||
to_spendable_note,
|
to_spendable_note,
|
||||||
|
@ -143,7 +143,7 @@ pub fn select_spendable_sapling_notes<P>(
|
||||||
// Select notes
|
// Select notes
|
||||||
let notes = stmt_select_notes.query_and_then_named::<_, SqliteClientError, _>(
|
let notes = stmt_select_notes.query_and_then_named::<_, SqliteClientError, _>(
|
||||||
named_params![
|
named_params![
|
||||||
":account": &i64::from(account.0),
|
":account": &u32::from(account),
|
||||||
":anchor_height": &u32::from(anchor_height),
|
":anchor_height": &u32::from(anchor_height),
|
||||||
":target_value": &i64::from(target_value),
|
":target_value": &i64::from(target_value),
|
||||||
],
|
],
|
||||||
|
@ -205,26 +205,28 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add two accounts to the wallet
|
// Add two accounts to the wallet
|
||||||
let extsk0 = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk0 = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extsk1 = sapling::spending_key(&[1u8; 32], network().coin_type(), AccountId(1));
|
let extsk1 = sapling::spending_key(&[1u8; 32], network().coin_type(), AccountId::from(1));
|
||||||
let extfvk0 = ExtendedFullViewingKey::from(&extsk0);
|
let extfvk0 = ExtendedFullViewingKey::from(&extsk0);
|
||||||
let extfvk1 = ExtendedFullViewingKey::from(&extsk1);
|
let extfvk1 = ExtendedFullViewingKey::from(&extsk1);
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvks = {
|
let ufvks = {
|
||||||
let tsk0 = transparent::AccountPrivKey::from_seed(&network(), &[0u8; 32], AccountId(0))
|
let tsk0 =
|
||||||
.unwrap();
|
transparent::AccountPrivKey::from_seed(&network(), &[0u8; 32], AccountId::from(0))
|
||||||
let tsk1 = transparent::AccountPrivKey::from_seed(&network(), &[1u8; 32], AccountId(1))
|
.unwrap();
|
||||||
.unwrap();
|
let tsk1 =
|
||||||
|
transparent::AccountPrivKey::from_seed(&network(), &[1u8; 32], AccountId::from(1))
|
||||||
|
.unwrap();
|
||||||
[
|
[
|
||||||
UnifiedFullViewingKey::new(
|
UnifiedFullViewingKey::new(
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
Some(tsk0.to_account_pubkey()),
|
Some(tsk0.to_account_pubkey()),
|
||||||
Some(extfvk0),
|
Some(extfvk0),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
UnifiedFullViewingKey::new(
|
UnifiedFullViewingKey::new(
|
||||||
AccountId(1),
|
AccountId::from(1),
|
||||||
Some(tsk1.to_account_pubkey()),
|
Some(tsk1.to_account_pubkey()),
|
||||||
Some(extfvk1),
|
Some(extfvk1),
|
||||||
)
|
)
|
||||||
|
@ -233,8 +235,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvks = [
|
let ufvks = [
|
||||||
UnifiedFullViewingKey::new(AccountId(0), Some(extfvk0)).unwrap(),
|
UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk0)).unwrap(),
|
||||||
UnifiedFullViewingKey::new(AccountId(1), Some(extfvk1)).unwrap(),
|
UnifiedFullViewingKey::new(AccountId::from(1), Some(extfvk1)).unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
init_accounts_table(&db_data, &ufvks).unwrap();
|
init_accounts_table(&db_data, &ufvks).unwrap();
|
||||||
|
@ -246,7 +248,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk1,
|
&extsk1,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(1).unwrap(),
|
Amount::from_u64(1).unwrap(),
|
||||||
|
@ -262,7 +264,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(1),
|
AccountId::from(1),
|
||||||
&extsk0,
|
&extsk0,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(1).unwrap(),
|
Amount::from_u64(1).unwrap(),
|
||||||
|
@ -282,13 +284,13 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk)).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk)).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk)).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk)).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
let to = extsk.default_address().1.into();
|
let to = extsk.default_address().1.into();
|
||||||
|
|
||||||
|
@ -298,7 +300,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(1).unwrap(),
|
Amount::from_u64(1).unwrap(),
|
||||||
|
@ -326,17 +328,20 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk)).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk)).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk)).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk)).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
let to = extsk.default_address().1.into();
|
let to = extsk.default_address().1.into();
|
||||||
|
|
||||||
// Account balance should be zero
|
// Account balance should be zero
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
assert_eq!(
|
||||||
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
|
Amount::zero()
|
||||||
|
);
|
||||||
|
|
||||||
// We cannot spend anything
|
// We cannot spend anything
|
||||||
let mut db_write = db_data.get_update_ops().unwrap();
|
let mut db_write = db_data.get_update_ops().unwrap();
|
||||||
|
@ -344,7 +349,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(1).unwrap(),
|
Amount::from_u64(1).unwrap(),
|
||||||
|
@ -371,12 +376,13 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk.clone())).unwrap();
|
let ufvk =
|
||||||
|
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk.clone())).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
|
|
||||||
// Add funds to the wallet in a single note
|
// Add funds to the wallet in a single note
|
||||||
|
@ -396,9 +402,9 @@ mod tests {
|
||||||
.get_target_and_anchor_heights(10)
|
.get_target_and_anchor_heights(10)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance_at(&db_data, AccountId(0), anchor_height).unwrap(),
|
get_balance_at(&db_data, AccountId::from(0), anchor_height).unwrap(),
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -418,11 +424,11 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
get_balance(&db_data, AccountId::from(0)).unwrap(),
|
||||||
(value + value).unwrap()
|
(value + value).unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance_at(&db_data, AccountId(0), anchor_height2).unwrap(),
|
get_balance_at(&db_data, AccountId::from(0), anchor_height2).unwrap(),
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -433,7 +439,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(70000).unwrap(),
|
Amount::from_u64(70000).unwrap(),
|
||||||
|
@ -466,7 +472,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(70000).unwrap(),
|
Amount::from_u64(70000).unwrap(),
|
||||||
|
@ -492,7 +498,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(70000).unwrap(),
|
Amount::from_u64(70000).unwrap(),
|
||||||
|
@ -514,12 +520,13 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk.clone())).unwrap();
|
let ufvk =
|
||||||
|
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk.clone())).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
|
|
||||||
// Add funds to the wallet in a single note
|
// Add funds to the wallet in a single note
|
||||||
|
@ -533,7 +540,7 @@ mod tests {
|
||||||
insert_into_cache(&db_cache, &cb);
|
insert_into_cache(&db_cache, &cb);
|
||||||
let mut db_write = db_data.get_update_ops().unwrap();
|
let mut db_write = db_data.get_update_ops().unwrap();
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
// Send some of the funds to another address
|
// Send some of the funds to another address
|
||||||
let extsk2 = ExtendedSpendingKey::master(&[]);
|
let extsk2 = ExtendedSpendingKey::master(&[]);
|
||||||
|
@ -542,7 +549,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(15000).unwrap(),
|
Amount::from_u64(15000).unwrap(),
|
||||||
|
@ -557,7 +564,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(2000).unwrap(),
|
Amount::from_u64(2000).unwrap(),
|
||||||
|
@ -590,7 +597,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(2000).unwrap(),
|
Amount::from_u64(2000).unwrap(),
|
||||||
|
@ -620,7 +627,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(2000).unwrap(),
|
Amount::from_u64(2000).unwrap(),
|
||||||
|
@ -643,12 +650,13 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network.coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network.coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk.clone())).unwrap();
|
let ufvk =
|
||||||
|
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk.clone())).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
|
|
||||||
// Add funds to the wallet in a single note
|
// Add funds to the wallet in a single note
|
||||||
|
@ -662,7 +670,7 @@ mod tests {
|
||||||
insert_into_cache(&db_cache, &cb);
|
insert_into_cache(&db_cache, &cb);
|
||||||
let mut db_write = db_data.get_update_ops().unwrap();
|
let mut db_write = db_data.get_update_ops().unwrap();
|
||||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
|
|
||||||
let extsk2 = ExtendedSpendingKey::master(&[]);
|
let extsk2 = ExtendedSpendingKey::master(&[]);
|
||||||
let addr2 = extsk2.default_address().1;
|
let addr2 = extsk2.default_address().1;
|
||||||
|
@ -673,7 +681,7 @@ mod tests {
|
||||||
db_write,
|
db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(15000).unwrap(),
|
Amount::from_u64(15000).unwrap(),
|
||||||
|
@ -753,12 +761,13 @@ mod tests {
|
||||||
init_wallet_db(&db_data).unwrap();
|
init_wallet_db(&db_data).unwrap();
|
||||||
|
|
||||||
// Add an account to the wallet
|
// Add an account to the wallet
|
||||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId(0));
|
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), None, Some(extfvk.clone())).unwrap();
|
let ufvk =
|
||||||
|
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let ufvk = UnifiedFullViewingKey::new(AccountId(0), Some(extfvk.clone())).unwrap();
|
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
|
||||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||||
|
|
||||||
// Add funds to the wallet in a single note
|
// Add funds to the wallet in a single note
|
||||||
|
@ -778,9 +787,9 @@ mod tests {
|
||||||
.get_target_and_anchor_heights(10)
|
.get_target_and_anchor_heights(10)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_balance_at(&db_data, AccountId(0), anchor_height).unwrap(),
|
get_balance_at(&db_data, AccountId::from(0), anchor_height).unwrap(),
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -789,7 +798,7 @@ mod tests {
|
||||||
&mut db_write,
|
&mut db_write,
|
||||||
&tests::network(),
|
&tests::network(),
|
||||||
test_prover(),
|
test_prover(),
|
||||||
AccountId(0),
|
AccountId::from(0),
|
||||||
&extsk,
|
&extsk,
|
||||||
&to,
|
&to,
|
||||||
Amount::from_u64(50000).unwrap(),
|
Amount::from_u64(50000).unwrap(),
|
||||||
|
|
|
@ -97,6 +97,8 @@ and this library adheres to Rust's notion of
|
||||||
account values.
|
account values.
|
||||||
- The `zcash_primitives::zip32::AccountId`, a type-safe wrapper for ZIP 32
|
- The `zcash_primitives::zip32::AccountId`, a type-safe wrapper for ZIP 32
|
||||||
account indices.
|
account indices.
|
||||||
|
- In `zcash_primitives::transaction::components::amount`:
|
||||||
|
- `impl Sum<&Amount> for Option<Amount>`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- MSRV is now 1.51.0.
|
- MSRV is now 1.51.0.
|
||||||
|
|
|
@ -29,7 +29,7 @@ impl BlockHash {
|
||||||
pub fn from_slice(bytes: &[u8]) -> Self {
|
pub fn from_slice(bytes: &[u8]) -> Self {
|
||||||
assert_eq!(bytes.len(), 32);
|
assert_eq!(bytes.len(), 32);
|
||||||
let mut hash = [0; 32];
|
let mut hash = [0; 32];
|
||||||
hash.copy_from_slice(&bytes);
|
hash.copy_from_slice(bytes);
|
||||||
BlockHash(hash)
|
BlockHash(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,16 @@ pub struct Witness<T> {
|
||||||
pub payload: T,
|
pub payload: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Witness<T> {
|
||||||
|
pub fn map_payload<U, F: FnOnce(T) -> U>(self, f: F) -> Witness<U> {
|
||||||
|
Witness {
|
||||||
|
extension_id: self.extension_id,
|
||||||
|
mode: self.mode,
|
||||||
|
payload: f(self.payload),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Witness<AuthData> {
|
impl Witness<AuthData> {
|
||||||
/// Produce the intermediate format for an extension-specific witness
|
/// Produce the intermediate format for an extension-specific witness
|
||||||
/// type.
|
/// type.
|
||||||
|
@ -155,7 +165,7 @@ pub trait Extension<C> {
|
||||||
self.verify_inner(
|
self.verify_inner(
|
||||||
&Self::Precondition::from_payload(precondition.mode, &precondition.payload)?,
|
&Self::Precondition::from_payload(precondition.mode, &precondition.payload)?,
|
||||||
&Self::Witness::from_payload(witness.mode, &witness.payload.0)?,
|
&Self::Witness::from_payload(witness.mode, &witness.payload.0)?,
|
||||||
&context,
|
context,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,10 @@ impl AccountPrivKey {
|
||||||
seed: &[u8],
|
seed: &[u8],
|
||||||
account: AccountId,
|
account: AccountId,
|
||||||
) -> Result<AccountPrivKey, hdwallet::error::Error> {
|
) -> Result<AccountPrivKey, hdwallet::error::Error> {
|
||||||
ExtendedPrivKey::with_seed(&seed)?
|
ExtendedPrivKey::with_seed(seed)?
|
||||||
.derive_private_key(KeyIndex::hardened_from_normalize_index(44)?)?
|
.derive_private_key(KeyIndex::hardened_from_normalize_index(44)?)?
|
||||||
.derive_private_key(KeyIndex::hardened_from_normalize_index(params.coin_type())?)?
|
.derive_private_key(KeyIndex::hardened_from_normalize_index(params.coin_type())?)?
|
||||||
.derive_private_key(KeyIndex::hardened_from_normalize_index(account.0)?)
|
.derive_private_key(KeyIndex::hardened_from_normalize_index(account.into())?)
|
||||||
.map(AccountPrivKey)
|
.map(AccountPrivKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn write_nonempty_frontier_v1<H: HashSer, W: Write>(
|
||||||
Optional::write(&mut writer, Some(b), |w, n| n.write(w))?;
|
Optional::write(&mut writer, Some(b), |w, n| n.write(w))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector::write(&mut writer, &frontier.ommers(), |w, e| e.write(w))?;
|
Vector::write(&mut writer, frontier.ommers(), |w, e| e.write(w))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,7 +253,7 @@ impl<P: consensus::Parameters> Domain for SaplingDomain<P> {
|
||||||
ivk: &Self::IncomingViewingKey,
|
ivk: &Self::IncomingViewingKey,
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> Option<(Self::Note, Self::Recipient)> {
|
) -> Option<(Self::Note, Self::Recipient)> {
|
||||||
sapling_parse_note_plaintext_without_memo(&self, plaintext, |diversifier| {
|
sapling_parse_note_plaintext_without_memo(self, plaintext, |diversifier| {
|
||||||
Some(diversifier.g_d()? * ivk.0)
|
Some(diversifier.g_d()? * ivk.0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ impl<P: consensus::Parameters> Domain for SaplingDomain<P> {
|
||||||
ephemeral_key: &EphemeralKeyBytes,
|
ephemeral_key: &EphemeralKeyBytes,
|
||||||
plaintext: &NotePlaintextBytes,
|
plaintext: &NotePlaintextBytes,
|
||||||
) -> Option<(Self::Note, Self::Recipient)> {
|
) -> Option<(Self::Note, Self::Recipient)> {
|
||||||
sapling_parse_note_plaintext_without_memo(&self, &plaintext.0, |diversifier| {
|
sapling_parse_note_plaintext_without_memo(self, &plaintext.0, |diversifier| {
|
||||||
if (diversifier.g_d()? * esk).to_bytes() == ephemeral_key.0 {
|
if (diversifier.g_d()? * esk).to_bytes() == ephemeral_key.0 {
|
||||||
Some(*pk_d)
|
Some(*pk_d)
|
||||||
} else {
|
} else {
|
||||||
|
@ -595,7 +595,7 @@ mod tests {
|
||||||
out_ciphertext: &[u8; OUT_CIPHERTEXT_SIZE],
|
out_ciphertext: &[u8; OUT_CIPHERTEXT_SIZE],
|
||||||
modify_plaintext: impl Fn(&mut [u8; NOTE_PLAINTEXT_SIZE]),
|
modify_plaintext: impl Fn(&mut [u8; NOTE_PLAINTEXT_SIZE]),
|
||||||
) {
|
) {
|
||||||
let ock = prf_ock(&ovk, &cv, &cmu.to_repr(), ephemeral_key);
|
let ock = prf_ock(ovk, cv, &cmu.to_repr(), ephemeral_key);
|
||||||
|
|
||||||
let mut op = [0; OUT_PLAINTEXT_SIZE];
|
let mut op = [0; OUT_PLAINTEXT_SIZE];
|
||||||
op.copy_from_slice(&out_ciphertext[..OUT_PLAINTEXT_SIZE]);
|
op.copy_from_slice(&out_ciphertext[..OUT_PLAINTEXT_SIZE]);
|
||||||
|
|
|
@ -87,7 +87,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut table: &[Vec<jubjub::SubgroupPoint>] =
|
let mut table: &[Vec<jubjub::SubgroupPoint>] =
|
||||||
&generators.next().expect("we don't have enough generators");
|
generators.next().expect("we don't have enough generators");
|
||||||
let window = PEDERSEN_HASH_EXP_WINDOW_SIZE as usize;
|
let window = PEDERSEN_HASH_EXP_WINDOW_SIZE as usize;
|
||||||
let window_mask = (1u64 << window) - 1;
|
let window_mask = (1u64 << window) - 1;
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ pub mod mock {
|
||||||
.commitment()
|
.commitment()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let rk = PublicKey(proof_generation_key.ak.clone().into())
|
let rk =
|
||||||
.randomize(ar, SPENDING_KEY_GENERATOR);
|
PublicKey(proof_generation_key.ak.into()).randomize(ar, SPENDING_KEY_GENERATOR);
|
||||||
|
|
||||||
Ok(([0u8; GROTH_PROOF_SIZE], cv, rk))
|
Ok(([0u8; GROTH_PROOF_SIZE], cv, rk))
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ impl Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrivateKey {
|
impl PrivateKey {
|
||||||
|
#[must_use]
|
||||||
pub fn randomize(&self, alpha: jubjub::Fr) -> Self {
|
pub fn randomize(&self, alpha: jubjub::Fr) -> Self {
|
||||||
let mut tmp = self.0;
|
let mut tmp = self.0;
|
||||||
tmp.add_assign(&alpha);
|
tmp.add_assign(&alpha);
|
||||||
|
@ -100,6 +101,7 @@ impl PublicKey {
|
||||||
PublicKey((p_g * privkey.0).into())
|
PublicKey((p_g * privkey.0).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn randomize(&self, alpha: jubjub::Fr, p_g: SubgroupPoint) -> Self {
|
pub fn randomize(&self, alpha: jubjub::Fr, p_g: SubgroupPoint) -> Self {
|
||||||
PublicKey(ExtendedPoint::from(p_g * alpha) + self.0)
|
PublicKey(ExtendedPoint::from(p_g * alpha) + self.0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ pub(crate) struct TestVector {
|
||||||
pub epk: [u8; 32],
|
pub epk: [u8; 32],
|
||||||
pub shared_secret: [u8; 32],
|
pub shared_secret: [u8; 32],
|
||||||
pub k_enc: [u8; 32],
|
pub k_enc: [u8; 32],
|
||||||
pub p_enc: [u8; 564],
|
pub _p_enc: [u8; 564],
|
||||||
pub c_enc: [u8; 580],
|
pub c_enc: [u8; 580],
|
||||||
pub ock: [u8; 32],
|
pub ock: [u8; 32],
|
||||||
pub op: [u8; 64],
|
pub _op: [u8; 64],
|
||||||
pub c_out: [u8; 80],
|
pub c_out: [u8; 80],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xb3, 0x3c, 0x3c, 0x32, 0x29, 0xfa, 0x0b, 0x91, 0x26, 0xf9, 0xdd, 0xdb, 0x43, 0x29,
|
0xb3, 0x3c, 0x3c, 0x32, 0x29, 0xfa, 0x0b, 0x91, 0x26, 0xf9, 0xdd, 0xdb, 0x43, 0x29,
|
||||||
0x66, 0x10, 0x00, 0x69,
|
0x66, 0x10, 0x00, 0x69,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39, 0x00, 0xe1,
|
0x01, 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39, 0x00, 0xe1,
|
||||||
0xf5, 0x05, 0x00, 0x00, 0x00, 0x00, 0x39, 0x17, 0x6d, 0xac, 0x39, 0xac, 0xe4, 0x98,
|
0xf5, 0x05, 0x00, 0x00, 0x00, 0x00, 0x39, 0x17, 0x6d, 0xac, 0x39, 0xac, 0xe4, 0x98,
|
||||||
0x0e, 0xcc, 0x8d, 0x77, 0x8e, 0x89, 0x86, 0x02, 0x55, 0xec, 0x36, 0x15, 0x06, 0x00,
|
0x0e, 0xcc, 0x8d, 0x77, 0x8e, 0x89, 0x86, 0x02, 0x55, 0xec, 0x36, 0x15, 0x06, 0x00,
|
||||||
|
@ -208,7 +208,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xca, 0x3a, 0xc6, 0x42, 0x2e, 0xc4, 0xfe, 0x21, 0xe5, 0xd1, 0x53, 0x86, 0x55, 0x8e,
|
0xca, 0x3a, 0xc6, 0x42, 0x2e, 0xc4, 0xfe, 0x21, 0xe5, 0xd1, 0x53, 0x86, 0x55, 0x8e,
|
||||||
0x4d, 0x37, 0x79, 0x6d,
|
0x4d, 0x37, 0x79, 0x6d,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0xdb, 0x4c, 0xd2, 0xb0, 0xaa, 0xc4, 0xf7, 0xeb, 0x8c, 0xa1, 0x31, 0xf1, 0x65, 0x67,
|
0xdb, 0x4c, 0xd2, 0xb0, 0xaa, 0xc4, 0xf7, 0xeb, 0x8c, 0xa1, 0x31, 0xf1, 0x65, 0x67,
|
||||||
0xc4, 0x45, 0xa9, 0x55, 0x51, 0x26, 0xd3, 0xc2, 0x9f, 0x14, 0xe3, 0xd7, 0x76, 0xe8,
|
0xc4, 0x45, 0xa9, 0x55, 0x51, 0x26, 0xd3, 0xc2, 0x9f, 0x14, 0xe3, 0xd7, 0x76, 0xe8,
|
||||||
0x41, 0xae, 0x74, 0x15, 0x81, 0xc7, 0xb2, 0x17, 0x1f, 0xf4, 0x41, 0x52, 0x50, 0xca,
|
0x41, 0xae, 0x74, 0x15, 0x81, 0xc7, 0xb2, 0x17, 0x1f, 0xf4, 0x41, 0x52, 0x50, 0xca,
|
||||||
|
@ -318,7 +318,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xa7, 0x02, 0x7a, 0x49, 0x36, 0x2a, 0xa2, 0xdd, 0x3b, 0x54, 0x36, 0xd8, 0x89, 0x75,
|
0xa7, 0x02, 0x7a, 0x49, 0x36, 0x2a, 0xa2, 0xdd, 0x3b, 0x54, 0x36, 0xd8, 0x89, 0x75,
|
||||||
0xe0, 0x2a, 0xd0, 0xca,
|
0xe0, 0x2a, 0xd0, 0xca,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81, 0x00, 0xc2,
|
0x01, 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81, 0x00, 0xc2,
|
||||||
0xeb, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x47, 0x8b, 0xa0, 0xee, 0x6e, 0x1a, 0x75, 0xb6,
|
0xeb, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x47, 0x8b, 0xa0, 0xee, 0x6e, 0x1a, 0x75, 0xb6,
|
||||||
0x00, 0x03, 0x6f, 0x26, 0xf1, 0x8b, 0x70, 0x15, 0xab, 0x55, 0x6b, 0xed, 0xdf, 0x8b,
|
0x00, 0x03, 0x6f, 0x26, 0xf1, 0x8b, 0x70, 0x15, 0xab, 0x55, 0x6b, 0xed, 0xdf, 0x8b,
|
||||||
|
@ -410,7 +410,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x4c, 0xa7, 0xe4, 0xa5, 0x82, 0x1d, 0x45, 0x5f, 0x0f, 0xa8, 0x2c, 0xd5, 0x44, 0xec,
|
0x4c, 0xa7, 0xe4, 0xa5, 0x82, 0x1d, 0x45, 0x5f, 0x0f, 0xa8, 0x2c, 0xd5, 0x44, 0xec,
|
||||||
0xb4, 0x20, 0x91, 0xfa,
|
0xb4, 0x20, 0x91, 0xfa,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0xa6, 0xb1, 0x3e, 0xa3, 0x36, 0xdd, 0xb7, 0xa6, 0x7b, 0xb0, 0x9a, 0x0e, 0x68, 0xe9,
|
0xa6, 0xb1, 0x3e, 0xa3, 0x36, 0xdd, 0xb7, 0xa6, 0x7b, 0xb0, 0x9a, 0x0e, 0x68, 0xe9,
|
||||||
0xd3, 0xcf, 0xb3, 0x92, 0x10, 0x83, 0x1e, 0xa3, 0xa2, 0x96, 0xba, 0x09, 0xa9, 0x22,
|
0xd3, 0xcf, 0xb3, 0x92, 0x10, 0x83, 0x1e, 0xa3, 0xa2, 0x96, 0xba, 0x09, 0xa9, 0x22,
|
||||||
0x06, 0x0f, 0xd3, 0x8b, 0xad, 0x4a, 0xd6, 0x24, 0x77, 0xc2, 0xc8, 0x83, 0xc8, 0xba,
|
0x06, 0x0f, 0xd3, 0x8b, 0xad, 0x4a, 0xd6, 0x24, 0x77, 0xc2, 0xc8, 0x83, 0xc8, 0xba,
|
||||||
|
@ -520,7 +520,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xa2, 0xd8, 0x06, 0x40, 0x53, 0x0a, 0x4c, 0xa9, 0x7b, 0x82, 0x92, 0xa5, 0xa5, 0x25,
|
0xa2, 0xd8, 0x06, 0x40, 0x53, 0x0a, 0x4c, 0xa9, 0x7b, 0x82, 0x92, 0xa5, 0xa5, 0x25,
|
||||||
0x0f, 0x1b, 0xf2, 0x40,
|
0x0f, 0x1b, 0xf2, 0x40,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6, 0x00, 0xa3,
|
0x01, 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6, 0x00, 0xa3,
|
||||||
0xe1, 0x11, 0x00, 0x00, 0x00, 0x00, 0x14, 0x7c, 0xf2, 0xb5, 0x1b, 0x4c, 0x7c, 0x63,
|
0xe1, 0x11, 0x00, 0x00, 0x00, 0x00, 0x14, 0x7c, 0xf2, 0xb5, 0x1b, 0x4c, 0x7c, 0x63,
|
||||||
0xcb, 0x77, 0xb9, 0x9e, 0x8b, 0x78, 0x3e, 0x5b, 0x51, 0x11, 0xdb, 0x0a, 0x7c, 0xa0,
|
0xcb, 0x77, 0xb9, 0x9e, 0x8b, 0x78, 0x3e, 0x5b, 0x51, 0x11, 0xdb, 0x0a, 0x7c, 0xa0,
|
||||||
|
@ -612,7 +612,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xcf, 0x0e, 0x49, 0xc3, 0x66, 0xae, 0x72, 0xc9, 0x79, 0xc4, 0x90, 0x49, 0xc9, 0x4b,
|
0xcf, 0x0e, 0x49, 0xc3, 0x66, 0xae, 0x72, 0xc9, 0x79, 0xc4, 0x90, 0x49, 0xc9, 0x4b,
|
||||||
0xd3, 0xc7, 0x5c, 0xf4,
|
0xd3, 0xc7, 0x5c, 0xf4,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x66, 0x14, 0x17, 0x39, 0x51, 0x4b, 0x28, 0xf0, 0x5d, 0xef, 0x8a, 0x18, 0xee, 0xee,
|
0x66, 0x14, 0x17, 0x39, 0x51, 0x4b, 0x28, 0xf0, 0x5d, 0xef, 0x8a, 0x18, 0xee, 0xee,
|
||||||
0x5e, 0xed, 0x4d, 0x44, 0xc6, 0x22, 0x5c, 0x3c, 0x65, 0xd8, 0x8d, 0xd9, 0x90, 0x77,
|
0x5e, 0xed, 0x4d, 0x44, 0xc6, 0x22, 0x5c, 0x3c, 0x65, 0xd8, 0x8d, 0xd9, 0x90, 0x77,
|
||||||
0x08, 0x01, 0x2f, 0x5a, 0x99, 0xaa, 0x10, 0xc0, 0x57, 0x88, 0x08, 0x1c, 0x0d, 0xa7,
|
0x08, 0x01, 0x2f, 0x5a, 0x99, 0xaa, 0x10, 0xc0, 0x57, 0x88, 0x08, 0x1c, 0x0d, 0xa7,
|
||||||
|
@ -722,7 +722,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x33, 0x0c, 0xf9, 0xc8, 0x2b, 0x1e, 0xb1, 0xfe, 0xe6, 0xa1, 0xa5, 0x54, 0x4a, 0x82,
|
0x33, 0x0c, 0xf9, 0xc8, 0x2b, 0x1e, 0xb1, 0xfe, 0xe6, 0xa1, 0xa5, 0x54, 0x4a, 0x82,
|
||||||
0xc7, 0xb3, 0x16, 0x82,
|
0xc7, 0xb3, 0x16, 0x82,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58, 0x00, 0x84,
|
0x01, 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58, 0x00, 0x84,
|
||||||
0xd7, 0x17, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa4, 0xb2, 0xa9, 0x14, 0x4f, 0xf5, 0xea,
|
0xd7, 0x17, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa4, 0xb2, 0xa9, 0x14, 0x4f, 0xf5, 0xea,
|
||||||
0x54, 0xef, 0xee, 0x87, 0xcf, 0x90, 0x1b, 0x5b, 0xed, 0x5e, 0x35, 0xd2, 0x1f, 0xbb,
|
0x54, 0xef, 0xee, 0x87, 0xcf, 0x90, 0x1b, 0x5b, 0xed, 0x5e, 0x35, 0xd2, 0x1f, 0xbb,
|
||||||
|
@ -814,7 +814,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xf1, 0x98, 0x4c, 0x9a, 0x8b, 0x98, 0xe0, 0x6e, 0xe5, 0xd8, 0x36, 0xce, 0x0e, 0x6c,
|
0xf1, 0x98, 0x4c, 0x9a, 0x8b, 0x98, 0xe0, 0x6e, 0xe5, 0xd8, 0x36, 0xce, 0x0e, 0x6c,
|
||||||
0x89, 0xab, 0x56, 0xfd,
|
0x89, 0xab, 0x56, 0xfd,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x25, 0xeb, 0x55, 0xfc, 0xcf, 0x76, 0x1f, 0xc6, 0x4e, 0x85, 0xa5, 0x88, 0xef, 0xe6,
|
0x25, 0xeb, 0x55, 0xfc, 0xcf, 0x76, 0x1f, 0xc6, 0x4e, 0x85, 0xa5, 0x88, 0xef, 0xe6,
|
||||||
0xea, 0xd7, 0x83, 0x2f, 0xb1, 0xf0, 0xf7, 0xa8, 0x31, 0x65, 0x89, 0x5b, 0xdf, 0xf9,
|
0xea, 0xd7, 0x83, 0x2f, 0xb1, 0xf0, 0xf7, 0xa8, 0x31, 0x65, 0x89, 0x5b, 0xdf, 0xf9,
|
||||||
0x42, 0x92, 0x5f, 0x5c, 0xbd, 0xde, 0x13, 0x81, 0xec, 0x9f, 0xf4, 0x21, 0xca, 0xfd,
|
0x42, 0x92, 0x5f, 0x5c, 0xbd, 0xde, 0x13, 0x81, 0xec, 0x9f, 0xf4, 0x21, 0xca, 0xfd,
|
||||||
|
@ -924,7 +924,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x7f, 0x26, 0x1f, 0xbb, 0x2d, 0xfa, 0xd8, 0x88, 0x66, 0xb4, 0x32, 0xff, 0x0d, 0xfa,
|
0x7f, 0x26, 0x1f, 0xbb, 0x2d, 0xfa, 0xd8, 0x88, 0x66, 0xb4, 0x32, 0xff, 0x0d, 0xfa,
|
||||||
0xee, 0xc5, 0xb2, 0xcf,
|
0xee, 0xc5, 0xb2, 0xcf,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4, 0x00, 0x65,
|
0x01, 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4, 0x00, 0x65,
|
||||||
0xcd, 0x1d, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x57, 0x85, 0x13, 0x55, 0x74, 0x7c, 0x09,
|
0xcd, 0x1d, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x57, 0x85, 0x13, 0x55, 0x74, 0x7c, 0x09,
|
||||||
0xac, 0x59, 0x01, 0x3c, 0xbd, 0xe8, 0x59, 0x80, 0x96, 0x4e, 0xc1, 0x84, 0x4d, 0x9c,
|
0xac, 0x59, 0x01, 0x3c, 0xbd, 0xe8, 0x59, 0x80, 0x96, 0x4e, 0xc1, 0x84, 0x4d, 0x9c,
|
||||||
|
@ -1016,7 +1016,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x3a, 0x4d, 0xb2, 0x81, 0x86, 0x37, 0x86, 0x88, 0xbe, 0xc6, 0x19, 0x56, 0x23, 0x2e,
|
0x3a, 0x4d, 0xb2, 0x81, 0x86, 0x37, 0x86, 0x88, 0xbe, 0xc6, 0x19, 0x56, 0x23, 0x2e,
|
||||||
0x42, 0xb7, 0x0a, 0xba,
|
0x42, 0xb7, 0x0a, 0xba,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x8b, 0x2a, 0x33, 0x7f, 0x03, 0x62, 0x2c, 0x24, 0xff, 0x38, 0x1d, 0x4c, 0x54, 0x6f,
|
0x8b, 0x2a, 0x33, 0x7f, 0x03, 0x62, 0x2c, 0x24, 0xff, 0x38, 0x1d, 0x4c, 0x54, 0x6f,
|
||||||
0x69, 0x77, 0xf9, 0x05, 0x22, 0xe9, 0x2f, 0xde, 0x44, 0xc9, 0xd1, 0xbb, 0x09, 0x97,
|
0x69, 0x77, 0xf9, 0x05, 0x22, 0xe9, 0x2f, 0xde, 0x44, 0xc9, 0xd1, 0xbb, 0x09, 0x97,
|
||||||
0x14, 0xb9, 0xdb, 0x2b, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, 0xd7,
|
0x14, 0xb9, 0xdb, 0x2b, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, 0xd7,
|
||||||
|
@ -1126,7 +1126,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x7c, 0xd0, 0x0c, 0xe0, 0xdc, 0x4b, 0x4d, 0x00, 0xcc, 0x8d, 0x8d, 0x3b, 0xa2, 0xce,
|
0x7c, 0xd0, 0x0c, 0xe0, 0xdc, 0x4b, 0x4d, 0x00, 0xcc, 0x8d, 0x8d, 0x3b, 0xa2, 0xce,
|
||||||
0x6e, 0xa9, 0xc2, 0x97,
|
0x6e, 0xa9, 0xc2, 0x97,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59, 0x00, 0x46,
|
0x01, 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59, 0x00, 0x46,
|
||||||
0xc3, 0x23, 0x00, 0x00, 0x00, 0x00, 0x68, 0xf0, 0x61, 0x04, 0x60, 0x6b, 0x0c, 0x54,
|
0xc3, 0x23, 0x00, 0x00, 0x00, 0x00, 0x68, 0xf0, 0x61, 0x04, 0x60, 0x6b, 0x0c, 0x54,
|
||||||
0x49, 0x84, 0x5f, 0xf4, 0xc6, 0x5f, 0x73, 0xe9, 0x0f, 0x45, 0xef, 0x5a, 0x43, 0xc9,
|
0x49, 0x84, 0x5f, 0xf4, 0xc6, 0x5f, 0x73, 0xe9, 0x0f, 0x45, 0xef, 0x5a, 0x43, 0xc9,
|
||||||
|
@ -1218,7 +1218,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x5a, 0x11, 0x75, 0x86, 0xae, 0x8a, 0xdd, 0x64, 0x99, 0x7d, 0x02, 0xec, 0xb8, 0xb5,
|
0x5a, 0x11, 0x75, 0x86, 0xae, 0x8a, 0xdd, 0x64, 0x99, 0x7d, 0x02, 0xec, 0xb8, 0xb5,
|
||||||
0xcb, 0xac, 0x14, 0x87,
|
0xcb, 0xac, 0x14, 0x87,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x6b, 0x27, 0xda, 0xcc, 0xb5, 0xa8, 0x20, 0x7f, 0x53, 0x2d, 0x10, 0xca, 0x23, 0x8f,
|
0x6b, 0x27, 0xda, 0xcc, 0xb5, 0xa8, 0x20, 0x7f, 0x53, 0x2d, 0x10, 0xca, 0x23, 0x8f,
|
||||||
0x97, 0x86, 0x64, 0x8a, 0x11, 0xb5, 0x96, 0x6e, 0x51, 0xa2, 0xf7, 0xd8, 0x9e, 0x15,
|
0x97, 0x86, 0x64, 0x8a, 0x11, 0xb5, 0x96, 0x6e, 0x51, 0xa2, 0xf7, 0xd8, 0x9e, 0x15,
|
||||||
0xd2, 0x9b, 0x8f, 0xdf, 0x4e, 0x41, 0x8c, 0x3c, 0x54, 0x3d, 0x6b, 0xf0, 0x15, 0x31,
|
0xd2, 0x9b, 0x8f, 0xdf, 0x4e, 0x41, 0x8c, 0x3c, 0x54, 0x3d, 0x6b, 0xf0, 0x15, 0x31,
|
||||||
|
@ -1328,7 +1328,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xba, 0x54, 0x76, 0x19, 0x8e, 0x29, 0x1d, 0xf7, 0x57, 0x8c, 0x2b, 0xef, 0x87, 0xe6,
|
0xba, 0x54, 0x76, 0x19, 0x8e, 0x29, 0x1d, 0xf7, 0x57, 0x8c, 0x2b, 0xef, 0x87, 0xe6,
|
||||||
0x4a, 0x71, 0x6a, 0xe7,
|
0x4a, 0x71, 0x6a, 0xe7,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6, 0x00, 0x27,
|
0x01, 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6, 0x00, 0x27,
|
||||||
0xb9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf9, 0x0b, 0x47, 0xfd, 0x52, 0xfe, 0xe7,
|
0xb9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf9, 0x0b, 0x47, 0xfd, 0x52, 0xfe, 0xe7,
|
||||||
0xc1, 0xc8, 0x1f, 0x0d, 0xcb, 0x5b, 0x74, 0xc3, 0xfb, 0x9b, 0x3e, 0x03, 0x97, 0x6f,
|
0xc1, 0xc8, 0x1f, 0x0d, 0xcb, 0x5b, 0x74, 0xc3, 0xfb, 0x9b, 0x3e, 0x03, 0x97, 0x6f,
|
||||||
|
@ -1420,7 +1420,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x14, 0x92, 0xd1, 0x8d, 0x5c, 0x85, 0x3c, 0x8f, 0x2f, 0x0c, 0xd5, 0xd1, 0x9d, 0x6d,
|
0x14, 0x92, 0xd1, 0x8d, 0x5c, 0x85, 0x3c, 0x8f, 0x2f, 0x0c, 0xd5, 0xd1, 0x9d, 0x6d,
|
||||||
0x34, 0xcf, 0x7c, 0x2d,
|
0x34, 0xcf, 0x7c, 0x2d,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0xd1, 0x1d, 0xa0, 0x1f, 0x0b, 0x43, 0xbd, 0xd5, 0x28, 0x8d, 0x32, 0x38, 0x5b, 0x87,
|
0xd1, 0x1d, 0xa0, 0x1f, 0x0b, 0x43, 0xbd, 0xd5, 0x28, 0x8d, 0x32, 0x38, 0x5b, 0x87,
|
||||||
0x71, 0xd2, 0x23, 0x49, 0x3c, 0x69, 0x80, 0x25, 0x44, 0x04, 0x3f, 0x77, 0xcf, 0x1d,
|
0x71, 0xd2, 0x23, 0x49, 0x3c, 0x69, 0x80, 0x25, 0x44, 0x04, 0x3f, 0x77, 0xcf, 0x1d,
|
||||||
0x71, 0xc1, 0xcb, 0x8c, 0x6d, 0xa9, 0x45, 0xd3, 0x03, 0x81, 0xc2, 0xee, 0xd2, 0xb8,
|
0x71, 0xc1, 0xcb, 0x8c, 0x6d, 0xa9, 0x45, 0xd3, 0x03, 0x81, 0xc2, 0xee, 0xd2, 0xb8,
|
||||||
|
@ -1530,7 +1530,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x39, 0x97, 0x42, 0xa9, 0x29, 0xbb, 0x23, 0x10, 0x0a, 0x7c, 0x51, 0xed, 0x32, 0xf9,
|
0x39, 0x97, 0x42, 0xa9, 0x29, 0xbb, 0x23, 0x10, 0x0a, 0x7c, 0x51, 0xed, 0x32, 0xf9,
|
||||||
0xcb, 0x45, 0x96, 0xc6,
|
0xcb, 0x45, 0x96, 0xc6,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3, 0x00, 0x08,
|
0x01, 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3, 0x00, 0x08,
|
||||||
0xaf, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x51, 0x65, 0xaf, 0xf2, 0x2d, 0xd4, 0xed, 0x56,
|
0xaf, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x51, 0x65, 0xaf, 0xf2, 0x2d, 0xd4, 0xed, 0x56,
|
||||||
0xb4, 0xd8, 0x1d, 0x1f, 0x17, 0x1c, 0xc3, 0xd6, 0x43, 0x2f, 0xed, 0x1b, 0xeb, 0xf2,
|
0xb4, 0xd8, 0x1d, 0x1f, 0x17, 0x1c, 0xc3, 0xd6, 0x43, 0x2f, 0xed, 0x1b, 0xeb, 0xf2,
|
||||||
|
@ -1622,7 +1622,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x83, 0xa9, 0x27, 0x7c, 0x61, 0x82, 0xa8, 0x08, 0xcc, 0x53, 0xa1, 0xbe, 0xdd, 0xd2,
|
0x83, 0xa9, 0x27, 0x7c, 0x61, 0x82, 0xa8, 0x08, 0xcc, 0x53, 0xa1, 0xbe, 0xdd, 0xd2,
|
||||||
0x03, 0x68, 0xb1, 0x0a,
|
0x03, 0x68, 0xb1, 0x0a,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x32, 0xcb, 0x28, 0x06, 0xb8, 0x82, 0xf1, 0x36, 0x8b, 0x0d, 0x4a, 0x89, 0x8f, 0x72,
|
0x32, 0xcb, 0x28, 0x06, 0xb8, 0x82, 0xf1, 0x36, 0x8b, 0x0d, 0x4a, 0x89, 0x8f, 0x72,
|
||||||
0xc4, 0xc8, 0xf7, 0x28, 0x13, 0x2c, 0xc1, 0x24, 0x56, 0x94, 0x6e, 0x7f, 0x4c, 0xb0,
|
0xc4, 0xc8, 0xf7, 0x28, 0x13, 0x2c, 0xc1, 0x24, 0x56, 0x94, 0x6e, 0x7f, 0x4c, 0xb0,
|
||||||
0xfb, 0x05, 0x8d, 0xa9, 0xab, 0x2a, 0xff, 0x03, 0x32, 0xd5, 0x43, 0xfd, 0x1d, 0x80,
|
0xfb, 0x05, 0x8d, 0xa9, 0xab, 0x2a, 0xff, 0x03, 0x32, 0xd5, 0x43, 0xfd, 0x1d, 0x80,
|
||||||
|
@ -1732,7 +1732,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xa6, 0xb9, 0xca, 0xbe, 0xfd, 0xba, 0x9e, 0x7a, 0x74, 0xf5, 0xba, 0x2f, 0x81, 0xb8,
|
0xa6, 0xb9, 0xca, 0xbe, 0xfd, 0xba, 0x9e, 0x7a, 0x74, 0xf5, 0xba, 0x2f, 0x81, 0xb8,
|
||||||
0x71, 0x40, 0x1f, 0x08,
|
0x71, 0x40, 0x1f, 0x08,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58, 0x00, 0xe9,
|
0x01, 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58, 0x00, 0xe9,
|
||||||
0xa4, 0x35, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x3e, 0x56, 0x44, 0x9d, 0xc8, 0x63, 0x54,
|
0xa4, 0x35, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x3e, 0x56, 0x44, 0x9d, 0xc8, 0x63, 0x54,
|
||||||
0xd3, 0x3b, 0x02, 0x5e, 0xf2, 0x79, 0x34, 0x60, 0xbc, 0xb1, 0x69, 0xf3, 0x32, 0x4e,
|
0xd3, 0x3b, 0x02, 0x5e, 0xf2, 0x79, 0x34, 0x60, 0xbc, 0xb1, 0x69, 0xf3, 0x32, 0x4e,
|
||||||
|
@ -1824,7 +1824,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xa5, 0xf3, 0x58, 0x05, 0xba, 0x78, 0x5a, 0x2c, 0x92, 0xa9, 0xaa, 0x62, 0x32, 0xb0,
|
0xa5, 0xf3, 0x58, 0x05, 0xba, 0x78, 0x5a, 0x2c, 0x92, 0xa9, 0xaa, 0x62, 0x32, 0xb0,
|
||||||
0x55, 0x1c, 0xf3, 0xf4,
|
0x55, 0x1c, 0xf3, 0xf4,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0x9e, 0x64, 0x17, 0x4b, 0x4a, 0xb9, 0x81, 0x40, 0x5c, 0x32, 0x3b, 0x5e, 0x12, 0x47,
|
0x9e, 0x64, 0x17, 0x4b, 0x4a, 0xb9, 0x81, 0x40, 0x5c, 0x32, 0x3b, 0x5e, 0x12, 0x47,
|
||||||
0x59, 0x45, 0xa4, 0x6d, 0x4f, 0xed, 0xf8, 0x06, 0x08, 0x28, 0x04, 0x1c, 0xd2, 0x0e,
|
0x59, 0x45, 0xa4, 0x6d, 0x4f, 0xed, 0xf8, 0x06, 0x08, 0x28, 0x04, 0x1c, 0xd2, 0x0e,
|
||||||
0x62, 0xfd, 0x2c, 0xef, 0xa5, 0x3d, 0x19, 0xf5, 0x69, 0x45, 0x95, 0xd5, 0xae, 0x63,
|
0x62, 0xfd, 0x2c, 0xef, 0xa5, 0x3d, 0x19, 0xf5, 0x69, 0x45, 0x95, 0xd5, 0xae, 0x63,
|
||||||
|
@ -1934,7 +1934,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0xc9, 0xc9, 0x60, 0xad, 0x7c, 0xcc, 0x59, 0x77, 0x43, 0x74, 0x4c, 0x18, 0xc9, 0xc2,
|
0xc9, 0xc9, 0x60, 0xad, 0x7c, 0xcc, 0x59, 0x77, 0x43, 0x74, 0x4c, 0x18, 0xc9, 0xc2,
|
||||||
0xa5, 0x62, 0xf6, 0x3a,
|
0xa5, 0x62, 0xf6, 0x3a,
|
||||||
],
|
],
|
||||||
p_enc: [
|
_p_enc: [
|
||||||
0x01, 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0, 0x00, 0xca,
|
0x01, 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0, 0x00, 0xca,
|
||||||
0x9a, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xbb, 0xed, 0x74, 0x36, 0x19, 0xa2, 0x56,
|
0x9a, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xbb, 0xed, 0x74, 0x36, 0x19, 0xa2, 0x56,
|
||||||
0xf9, 0xad, 0x2e, 0x85, 0x88, 0x0c, 0xfa, 0xa9, 0x09, 0x8a, 0x5f, 0xdb, 0x16, 0x29,
|
0xf9, 0xad, 0x2e, 0x85, 0x88, 0x0c, 0xfa, 0xa9, 0x09, 0x8a, 0x5f, 0xdb, 0x16, 0x29,
|
||||||
|
@ -2026,7 +2026,7 @@ pub(crate) fn make_test_vectors() -> Vec<TestVector> {
|
||||||
0x8c, 0xca, 0x55, 0x71, 0xee, 0xcc, 0x69, 0xb7, 0x22, 0xa0, 0xa3, 0xb8, 0x67, 0x50,
|
0x8c, 0xca, 0x55, 0x71, 0xee, 0xcc, 0x69, 0xb7, 0x22, 0xa0, 0xa3, 0xb8, 0x67, 0x50,
|
||||||
0x72, 0x92, 0x99, 0xa0,
|
0x72, 0x92, 0x99, 0xa0,
|
||||||
],
|
],
|
||||||
op: [
|
_op: [
|
||||||
0xb6, 0x8e, 0x9e, 0xe0, 0xc0, 0x67, 0x8d, 0x7b, 0x30, 0x36, 0x93, 0x1c, 0x83, 0x1a,
|
0xb6, 0x8e, 0x9e, 0xe0, 0xc0, 0x67, 0x8d, 0x7b, 0x30, 0x36, 0x93, 0x1c, 0x83, 0x1a,
|
||||||
0x25, 0x25, 0x5f, 0x7e, 0xe4, 0x87, 0x38, 0x5a, 0x30, 0x31, 0x6e, 0x15, 0xf6, 0x48,
|
0x25, 0x25, 0x5f, 0x7e, 0xe4, 0x87, 0x38, 0x5a, 0x30, 0x31, 0x6e, 0x15, 0xf6, 0x48,
|
||||||
0x2b, 0x87, 0x4f, 0xda, 0x29, 0x95, 0x89, 0x80, 0x69, 0x4f, 0x7f, 0x67, 0x08, 0x09,
|
0x2b, 0x87, 0x4f, 0xda, 0x29, 0x95, 0x89, 0x80, 0x69, 0x4f, 0x7f, 0x67, 0x08, 0x09,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! Structs for building transactions.
|
//! Structs for building transactions.
|
||||||
|
|
||||||
use std::array;
|
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
@ -267,7 +266,7 @@ impl<'a, P: consensus::Parameters, R: RngCore> Builder<'a, P, R> {
|
||||||
.ok_or(Error::InvalidAmount)?,
|
.ok_or(Error::InvalidAmount)?,
|
||||||
];
|
];
|
||||||
|
|
||||||
array::IntoIter::new(value_balances)
|
IntoIterator::into_iter(&value_balances)
|
||||||
.sum::<Option<_>>()
|
.sum::<Option<_>>()
|
||||||
.ok_or(Error::InvalidAmount)
|
.ok_or(Error::InvalidAmount)
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,6 +200,12 @@ impl Sum<Amount> for Option<Amount> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Sum<&'a Amount> for Option<Amount> {
|
||||||
|
fn sum<I: Iterator<Item = &'a Amount>>(iter: I) -> Self {
|
||||||
|
iter.fold(Some(Amount::zero()), |acc, a| acc? + *a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Neg for Amount {
|
impl Neg for Amount {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@ impl Authorization for Unauthorized {
|
||||||
type SpendAuth = ();
|
type SpendAuth = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MapAuth<A: Authorization, B: Authorization> {
|
||||||
|
fn map_spend_auth(&self, s: A::SpendAuth) -> B::SpendAuth;
|
||||||
|
fn map_authorization(&self, a: A) -> B;
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads an [`orchard::Bundle`] from a v5 transaction format.
|
/// Reads an [`orchard::Bundle`] from a v5 transaction format.
|
||||||
pub fn read_v5_bundle<R: Read>(
|
pub fn read_v5_bundle<R: Read>(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
|
@ -236,11 +241,11 @@ pub fn write_action_without_auth<W: Write>(
|
||||||
mut writer: W,
|
mut writer: W,
|
||||||
act: &Action<<Authorized as Authorization>::SpendAuth>,
|
act: &Action<<Authorized as Authorization>::SpendAuth>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
write_value_commitment(&mut writer, &act.cv_net())?;
|
write_value_commitment(&mut writer, act.cv_net())?;
|
||||||
write_nullifier(&mut writer, &act.nullifier())?;
|
write_nullifier(&mut writer, act.nullifier())?;
|
||||||
write_verification_key(&mut writer, &act.rk())?;
|
write_verification_key(&mut writer, act.rk())?;
|
||||||
write_cmx(&mut writer, &act.cmx())?;
|
write_cmx(&mut writer, act.cmx())?;
|
||||||
write_note_ciphertext(&mut writer, &act.encrypted_note())?;
|
write_note_ciphertext(&mut writer, act.encrypted_note())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,12 @@ impl Authorization for Authorized {
|
||||||
type AuthSig = redjubjub::Signature;
|
type AuthSig = redjubjub::Signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MapAuth<A: Authorization, B: Authorization> {
|
||||||
|
fn map_proof(&self, p: A::Proof) -> B::Proof;
|
||||||
|
fn map_auth_sig(&self, s: A::AuthSig) -> B::AuthSig;
|
||||||
|
fn map_authorization(&self, a: A) -> B;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Bundle<A: Authorization> {
|
pub struct Bundle<A: Authorization> {
|
||||||
pub shielded_spends: Vec<SpendDescription<A>>,
|
pub shielded_spends: Vec<SpendDescription<A>>,
|
||||||
|
@ -55,6 +61,39 @@ pub struct Bundle<A: Authorization> {
|
||||||
pub authorization: A,
|
pub authorization: A,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Authorization> Bundle<A> {
|
||||||
|
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
|
||||||
|
Bundle {
|
||||||
|
shielded_spends: self
|
||||||
|
.shielded_spends
|
||||||
|
.into_iter()
|
||||||
|
.map(|d| SpendDescription {
|
||||||
|
cv: d.cv,
|
||||||
|
anchor: d.anchor,
|
||||||
|
nullifier: d.nullifier,
|
||||||
|
rk: d.rk,
|
||||||
|
zkproof: f.map_proof(d.zkproof),
|
||||||
|
spend_auth_sig: f.map_auth_sig(d.spend_auth_sig),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
shielded_outputs: self
|
||||||
|
.shielded_outputs
|
||||||
|
.into_iter()
|
||||||
|
.map(|o| OutputDescription {
|
||||||
|
cv: o.cv,
|
||||||
|
cmu: o.cmu,
|
||||||
|
ephemeral_key: o.ephemeral_key,
|
||||||
|
enc_ciphertext: o.enc_ciphertext,
|
||||||
|
out_ciphertext: o.out_ciphertext,
|
||||||
|
zkproof: f.map_proof(o.zkproof),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
value_balance: self.value_balance,
|
||||||
|
authorization: f.map_authorization(self.authorization),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SpendDescription<A: Authorization> {
|
pub struct SpendDescription<A: Authorization> {
|
||||||
pub cv: jubjub::ExtendedPoint,
|
pub cv: jubjub::ExtendedPoint,
|
||||||
|
|
|
@ -18,9 +18,9 @@ pub struct Bundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
pub(crate) enum SproutProof {
|
pub(crate) enum SproutProof {
|
||||||
Groth([u8; GROTH_PROOF_SIZE]),
|
Groth([u8; GROTH_PROOF_SIZE]),
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
|
||||||
PHGR([u8; PHGR_PROOF_SIZE]),
|
PHGR([u8; PHGR_PROOF_SIZE]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@ impl Authorization for Authorized {
|
||||||
type ScriptSig = Script;
|
type ScriptSig = Script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MapAuth<A: Authorization, B: Authorization> {
|
||||||
|
fn map_script_sig(&self, s: A::ScriptSig) -> B::ScriptSig;
|
||||||
|
fn map_authorization(&self, s: A) -> B;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Bundle<A: Authorization> {
|
pub struct Bundle<A: Authorization> {
|
||||||
pub vin: Vec<TxIn<A>>,
|
pub vin: Vec<TxIn<A>>,
|
||||||
|
@ -41,6 +46,22 @@ impl<A: Authorization> Bundle<A> {
|
||||||
// return (vin.size() == 1 && vin[0].prevout.IsNull());
|
// return (vin.size() == 1 && vin[0].prevout.IsNull());
|
||||||
matches!(&self.vin[..], [input] if input.prevout.is_null())
|
matches!(&self.vin[..], [input] if input.prevout.is_null())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
|
||||||
|
Bundle {
|
||||||
|
vin: self
|
||||||
|
.vin
|
||||||
|
.into_iter()
|
||||||
|
.map(|txin| TxIn {
|
||||||
|
prevout: txin.prevout,
|
||||||
|
script_sig: f.map_script_sig(txin.script_sig),
|
||||||
|
sequence: txin.sequence,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
vout: self.vout,
|
||||||
|
authorization: f.map_authorization(self.authorization),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|
|
@ -222,7 +222,7 @@ impl Bundle<Unauthorized> {
|
||||||
#[cfg(feature = "transparent-inputs")] txid_parts_cache: &TxDigests<Blake2bHash>,
|
#[cfg(feature = "transparent-inputs")] txid_parts_cache: &TxDigests<Blake2bHash>,
|
||||||
) -> Bundle<Authorized> {
|
) -> Bundle<Authorized> {
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
let script_sigs: Vec<Script> = self
|
let script_sigs = self
|
||||||
.authorization
|
.authorization
|
||||||
.inputs
|
.inputs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -249,19 +249,18 @@ impl Bundle<Unauthorized> {
|
||||||
|
|
||||||
// P2PKH scriptSig
|
// P2PKH scriptSig
|
||||||
Script::default() << &sig_bytes[..] << &info.pubkey[..]
|
Script::default() << &sig_bytes[..] << &info.pubkey[..]
|
||||||
})
|
});
|
||||||
.collect();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "transparent-inputs"))]
|
#[cfg(not(feature = "transparent-inputs"))]
|
||||||
let script_sigs = vec![];
|
let script_sigs = std::iter::empty::<Script>();
|
||||||
|
|
||||||
transparent::Bundle {
|
transparent::Bundle {
|
||||||
vin: self
|
vin: self
|
||||||
.vin
|
.vin
|
||||||
.into_iter()
|
.iter()
|
||||||
.zip(script_sigs.into_iter())
|
.zip(script_sigs)
|
||||||
.map(|(txin, sig)| TxIn {
|
.map(|(txin, sig)| TxIn {
|
||||||
prevout: txin.prevout,
|
prevout: txin.prevout.clone(),
|
||||||
script_sig: sig,
|
script_sig: sig,
|
||||||
sequence: txin.sequence,
|
sequence: txin.sequence,
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,6 +28,11 @@ impl Authorization for Authorized {
|
||||||
type Witness = tze::AuthData;
|
type Witness = tze::AuthData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MapAuth<A: Authorization, B: Authorization> {
|
||||||
|
fn map_witness(&self, s: A::Witness) -> B::Witness;
|
||||||
|
fn map_authorization(&self, s: A) -> B;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Bundle<A: Authorization> {
|
pub struct Bundle<A: Authorization> {
|
||||||
pub vin: Vec<TzeIn<A::Witness>>,
|
pub vin: Vec<TzeIn<A::Witness>>,
|
||||||
|
@ -35,6 +40,23 @@ pub struct Bundle<A: Authorization> {
|
||||||
pub authorization: A,
|
pub authorization: A,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Authorization> Bundle<A> {
|
||||||
|
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
|
||||||
|
Bundle {
|
||||||
|
vin: self
|
||||||
|
.vin
|
||||||
|
.into_iter()
|
||||||
|
.map(|tzein| TzeIn {
|
||||||
|
prevout: tzein.prevout,
|
||||||
|
witness: tzein.witness.map_payload(|p| f.map_witness(p)),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
vout: self.vout,
|
||||||
|
authorization: f.map_authorization(self.authorization),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct OutPoint {
|
pub struct OutPoint {
|
||||||
txid: TxId,
|
txid: TxId,
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl<'a, BuildCtx> TzeBuilder<'a, BuildCtx> {
|
||||||
self.vin.push(TzeIn::new(outpoint, extension_id, mode));
|
self.vin.push(TzeIn::new(outpoint, extension_id, mode));
|
||||||
self.signers.push(TzeSigner {
|
self.signers.push(TzeSigner {
|
||||||
prevout,
|
prevout,
|
||||||
builder: Box::new(move |ctx| witness_builder(&ctx).map(|x| x.to_payload())),
|
builder: Box::new(move |ctx| witness_builder(ctx).map(|x| x.to_payload())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,6 +374,68 @@ impl<A: Authorization> TransactionData<A> {
|
||||||
digester.digest_tze(self.tze_bundle.as_ref()),
|
digester.digest_tze(self.tze_bundle.as_ref()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps the bundles from one type to another.
|
||||||
|
///
|
||||||
|
/// This shouldn't be necessary for most use cases; it is provided for handling the
|
||||||
|
/// cross-FFI builder logic in `zcashd`.
|
||||||
|
pub fn map_bundles<B: Authorization>(
|
||||||
|
self,
|
||||||
|
f_transparent: impl FnOnce(
|
||||||
|
Option<transparent::Bundle<A::TransparentAuth>>,
|
||||||
|
) -> Option<transparent::Bundle<B::TransparentAuth>>,
|
||||||
|
f_sapling: impl FnOnce(
|
||||||
|
Option<sapling::Bundle<A::SaplingAuth>>,
|
||||||
|
) -> Option<sapling::Bundle<B::SaplingAuth>>,
|
||||||
|
f_orchard: impl FnOnce(
|
||||||
|
Option<orchard::bundle::Bundle<A::OrchardAuth, Amount>>,
|
||||||
|
) -> Option<orchard::bundle::Bundle<B::OrchardAuth, Amount>>,
|
||||||
|
#[cfg(feature = "zfuture")] f_tze: impl FnOnce(
|
||||||
|
Option<tze::Bundle<A::TzeAuth>>,
|
||||||
|
) -> Option<tze::Bundle<B::TzeAuth>>,
|
||||||
|
) -> TransactionData<B> {
|
||||||
|
TransactionData {
|
||||||
|
version: self.version,
|
||||||
|
consensus_branch_id: self.consensus_branch_id,
|
||||||
|
lock_time: self.lock_time,
|
||||||
|
expiry_height: self.expiry_height,
|
||||||
|
transparent_bundle: f_transparent(self.transparent_bundle),
|
||||||
|
sprout_bundle: self.sprout_bundle,
|
||||||
|
sapling_bundle: f_sapling(self.sapling_bundle),
|
||||||
|
orchard_bundle: f_orchard(self.orchard_bundle),
|
||||||
|
#[cfg(feature = "zfuture")]
|
||||||
|
tze_bundle: f_tze(self.tze_bundle),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_authorization<B: Authorization>(
|
||||||
|
self,
|
||||||
|
f_transparent: impl transparent::MapAuth<A::TransparentAuth, B::TransparentAuth>,
|
||||||
|
f_sapling: impl sapling::MapAuth<A::SaplingAuth, B::SaplingAuth>,
|
||||||
|
mut f_orchard: impl orchard_serialization::MapAuth<A::OrchardAuth, B::OrchardAuth>,
|
||||||
|
#[cfg(feature = "zfuture")] f_tze: impl tze::MapAuth<A::TzeAuth, B::TzeAuth>,
|
||||||
|
) -> TransactionData<B> {
|
||||||
|
TransactionData {
|
||||||
|
version: self.version,
|
||||||
|
consensus_branch_id: self.consensus_branch_id,
|
||||||
|
lock_time: self.lock_time,
|
||||||
|
expiry_height: self.expiry_height,
|
||||||
|
transparent_bundle: self
|
||||||
|
.transparent_bundle
|
||||||
|
.map(|b| b.map_authorization(f_transparent)),
|
||||||
|
sprout_bundle: self.sprout_bundle,
|
||||||
|
sapling_bundle: self.sapling_bundle.map(|b| b.map_authorization(f_sapling)),
|
||||||
|
orchard_bundle: self.orchard_bundle.map(|b| {
|
||||||
|
b.authorize(
|
||||||
|
&mut f_orchard,
|
||||||
|
|f, _, s| f.map_spend_auth(s),
|
||||||
|
|f, a| f.map_authorization(a),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
#[cfg(feature = "zfuture")]
|
||||||
|
tze_bundle: self.tze_bundle.map(|b| b.map_authorization(f_tze)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Authorization> std::fmt::Debug for TransactionData<A> {
|
impl<A: Authorization> std::fmt::Debug for TransactionData<A> {
|
||||||
|
@ -509,6 +571,10 @@ impl Transaction {
|
||||||
Transaction { txid, data }
|
Transaction { txid, data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_data(self) -> TransactionData<Authorized> {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
|
||||||
pub fn txid(&self) -> TxId {
|
pub fn txid(&self) -> TxId {
|
||||||
self.txid
|
self.txid
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ fn shielded_spends_hash<A: sapling::Authorization<Proof = GrothProofBytes>>(
|
||||||
for s_spend in shielded_spends {
|
for s_spend in shielded_spends {
|
||||||
data.extend_from_slice(&s_spend.cv.to_bytes());
|
data.extend_from_slice(&s_spend.cv.to_bytes());
|
||||||
data.extend_from_slice(s_spend.anchor.to_repr().as_ref());
|
data.extend_from_slice(s_spend.anchor.to_repr().as_ref());
|
||||||
data.extend_from_slice(&s_spend.nullifier.as_ref());
|
data.extend_from_slice(s_spend.nullifier.as_ref());
|
||||||
s_spend.rk.write(&mut data).unwrap();
|
s_spend.rk.write(&mut data).unwrap();
|
||||||
data.extend_from_slice(&s_spend.zkproof);
|
data.extend_from_slice(&s_spend.zkproof);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ pub(crate) fn hash_sapling_spends<A: sapling::Authorization>(
|
||||||
let mut nh = hasher(ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION);
|
let mut nh = hasher(ZCASH_SAPLING_SPENDS_NONCOMPACT_HASH_PERSONALIZATION);
|
||||||
for s_spend in shielded_spends {
|
for s_spend in shielded_spends {
|
||||||
// we build the hash of nullifiers separately for compact blocks.
|
// we build the hash of nullifiers separately for compact blocks.
|
||||||
ch.write_all(&s_spend.nullifier.as_ref()).unwrap();
|
ch.write_all(s_spend.nullifier.as_ref()).unwrap();
|
||||||
|
|
||||||
nh.write_all(&s_spend.cv.to_bytes()).unwrap();
|
nh.write_all(&s_spend.cv.to_bytes()).unwrap();
|
||||||
nh.write_all(&s_spend.anchor.to_repr()).unwrap();
|
nh.write_all(&s_spend.anchor.to_repr()).unwrap();
|
||||||
|
@ -154,9 +154,9 @@ pub(crate) fn hash_sapling_spends<A: sapling::Authorization>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let compact_digest = ch.finalize();
|
let compact_digest = ch.finalize();
|
||||||
h.write_all(&compact_digest.as_bytes()).unwrap();
|
h.write_all(compact_digest.as_bytes()).unwrap();
|
||||||
let noncompact_digest = nh.finalize();
|
let noncompact_digest = nh.finalize();
|
||||||
h.write_all(&noncompact_digest.as_bytes()).unwrap();
|
h.write_all(noncompact_digest.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
h.finalize()
|
h.finalize()
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ pub(crate) fn hash_sapling_outputs<A>(shielded_outputs: &[OutputDescription<A>])
|
||||||
let mut mh = hasher(ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION);
|
let mut mh = hasher(ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION);
|
||||||
let mut nh = hasher(ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION);
|
let mut nh = hasher(ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION);
|
||||||
for s_out in shielded_outputs {
|
for s_out in shielded_outputs {
|
||||||
ch.write_all(&s_out.cmu.to_repr().as_ref()).unwrap();
|
ch.write_all(s_out.cmu.to_repr().as_ref()).unwrap();
|
||||||
ch.write_all(s_out.ephemeral_key.as_ref()).unwrap();
|
ch.write_all(s_out.ephemeral_key.as_ref()).unwrap();
|
||||||
ch.write_all(&s_out.enc_ciphertext[..52]).unwrap();
|
ch.write_all(&s_out.enc_ciphertext[..52]).unwrap();
|
||||||
|
|
||||||
|
@ -187,9 +187,9 @@ pub(crate) fn hash_sapling_outputs<A>(shielded_outputs: &[OutputDescription<A>])
|
||||||
nh.write_all(&s_out.out_ciphertext).unwrap();
|
nh.write_all(&s_out.out_ciphertext).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
h.write_all(&ch.finalize().as_bytes()).unwrap();
|
h.write_all(ch.finalize().as_bytes()).unwrap();
|
||||||
h.write_all(&mh.finalize().as_bytes()).unwrap();
|
h.write_all(mh.finalize().as_bytes()).unwrap();
|
||||||
h.write_all(&nh.finalize().as_bytes()).unwrap();
|
h.write_all(nh.finalize().as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
h.finalize()
|
h.finalize()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashSaplingFVFP";
|
||||||
pub const ZIP32_SAPLING_INT_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingInt";
|
pub const ZIP32_SAPLING_INT_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingInt";
|
||||||
|
|
||||||
/// A type-safe wrapper for account identifiers.
|
/// A type-safe wrapper for account identifiers.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct AccountId(pub u32);
|
pub struct AccountId(u32);
|
||||||
|
|
||||||
impl From<u32> for AccountId {
|
impl From<u32> for AccountId {
|
||||||
fn from(id: u32) -> Self {
|
fn from(id: u32) -> Self {
|
||||||
|
@ -35,9 +35,9 @@ impl From<u32> for AccountId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AccountId {
|
impl From<AccountId> for u32 {
|
||||||
fn default() -> Self {
|
fn from(id: AccountId) -> Self {
|
||||||
AccountId(0)
|
id.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ impl ChildIndex {
|
||||||
ChildIndex::from_index(0)
|
ChildIndex::from_index(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_index(&self) -> u32 {
|
fn value(&self) -> u32 {
|
||||||
match *self {
|
match *self {
|
||||||
ChildIndex::Hardened(i) => i + (1 << 31),
|
ChildIndex::Hardened(i) => i + (1 << 31),
|
||||||
ChildIndex::NonHardened(i) => i,
|
ChildIndex::NonHardened(i) => i,
|
||||||
|
@ -410,7 +410,7 @@ impl ExtendedSpendingKey {
|
||||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
writer.write_u8(self.depth)?;
|
writer.write_u8(self.depth)?;
|
||||||
writer.write_all(&self.parent_fvk_tag.0)?;
|
writer.write_all(&self.parent_fvk_tag.0)?;
|
||||||
writer.write_u32::<LittleEndian>(self.child_index.to_index())?;
|
writer.write_u32::<LittleEndian>(self.child_index.value())?;
|
||||||
writer.write_all(&self.chain_code.0)?;
|
writer.write_all(&self.chain_code.0)?;
|
||||||
writer.write_all(&self.expsk.to_bytes())?;
|
writer.write_all(&self.expsk.to_bytes())?;
|
||||||
writer.write_all(&self.dk.0)?;
|
writer.write_all(&self.dk.0)?;
|
||||||
|
@ -427,6 +427,7 @@ impl ExtendedSpendingKey {
|
||||||
xsk
|
xsk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
||||||
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
||||||
let tmp = match i {
|
let tmp = match i {
|
||||||
|
@ -477,6 +478,7 @@ impl ExtendedSpendingKey {
|
||||||
/// Derives an internal spending key given an external spending key.
|
/// Derives an internal spending key given an external spending key.
|
||||||
///
|
///
|
||||||
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-spending-key).
|
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-spending-key).
|
||||||
|
#[must_use]
|
||||||
pub fn derive_internal(&self) -> Self {
|
pub fn derive_internal(&self) -> Self {
|
||||||
let i = {
|
let i = {
|
||||||
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
||||||
|
@ -548,7 +550,7 @@ impl ExtendedFullViewingKey {
|
||||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
writer.write_u8(self.depth)?;
|
writer.write_u8(self.depth)?;
|
||||||
writer.write_all(&self.parent_fvk_tag.0)?;
|
writer.write_all(&self.parent_fvk_tag.0)?;
|
||||||
writer.write_u32::<LittleEndian>(self.child_index.to_index())?;
|
writer.write_u32::<LittleEndian>(self.child_index.value())?;
|
||||||
writer.write_all(&self.chain_code.0)?;
|
writer.write_all(&self.chain_code.0)?;
|
||||||
writer.write_all(&self.fvk.to_bytes())?;
|
writer.write_all(&self.fvk.to_bytes())?;
|
||||||
writer.write_all(&self.dk.0)?;
|
writer.write_all(&self.dk.0)?;
|
||||||
|
@ -619,6 +621,7 @@ impl ExtendedFullViewingKey {
|
||||||
/// only for internal transfers.
|
/// only for internal transfers.
|
||||||
///
|
///
|
||||||
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-full-viewing-key).
|
/// Specified in [ZIP 32](https://zips.z.cash/zip-0032#deriving-a-sapling-internal-full-viewing-key).
|
||||||
|
#[must_use]
|
||||||
pub fn derive_internal(&self) -> Self {
|
pub fn derive_internal(&self) -> Self {
|
||||||
let (fvk_internal, dk_internal) = sapling_derive_internal_fvk(&self.fvk, &self.dk);
|
let (fvk_internal, dk_internal) = sapling_derive_internal_fvk(&self.fvk, &self.dk);
|
||||||
|
|
||||||
|
|
|
@ -740,11 +740,11 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
|
||||||
jubjub::ExtendedPoint::from(value_commitment.commitment()).to_affine();
|
jubjub::ExtendedPoint::from(value_commitment.commitment()).to_affine();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_value_commitment.get_u(),
|
expected_value_commitment.get_u(),
|
||||||
bls12_381::Scalar::from_str_vartime(&expected_commitment_us[i as usize]).unwrap()
|
bls12_381::Scalar::from_str_vartime(expected_commitment_us[i as usize]).unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_value_commitment.get_v(),
|
expected_value_commitment.get_v(),
|
||||||
bls12_381::Scalar::from_str_vartime(&expected_commitment_vs[i as usize]).unwrap()
|
bls12_381::Scalar::from_str_vartime(expected_commitment_vs[i as usize]).unwrap()
|
||||||
);
|
);
|
||||||
let note = Note {
|
let note = Note {
|
||||||
value: value_commitment.value,
|
value: value_commitment.value,
|
||||||
|
|
|
@ -86,8 +86,7 @@ impl SaplingProvingContext {
|
||||||
let payment_address = viewing_key.to_payment_address(diversifier).ok_or(())?;
|
let payment_address = viewing_key.to_payment_address(diversifier).ok_or(())?;
|
||||||
|
|
||||||
// This is the result of the re-randomization, we compute it for the caller
|
// This is the result of the re-randomization, we compute it for the caller
|
||||||
let rk =
|
let rk = PublicKey(proof_generation_key.ak.into()).randomize(ar, SPENDING_KEY_GENERATOR);
|
||||||
PublicKey(proof_generation_key.ak.clone().into()).randomize(ar, SPENDING_KEY_GENERATOR);
|
|
||||||
|
|
||||||
// Let's compute the nullifier while we have the position
|
// Let's compute the nullifier while we have the position
|
||||||
let note = Note {
|
let note = Note {
|
||||||
|
|
Loading…
Reference in New Issue