Move Memo into zcash_primitives::memo
This commit is contained in:
parent
3a8e72936f
commit
48f7ef84a4
|
@ -7,8 +7,8 @@ use std::fmt::Debug;
|
|||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::BlockHeight,
|
||||
memo::Memo,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::Memo,
|
||||
primitives::{Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
transaction::{components::Amount, Transaction, TxId},
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt::Debug;
|
|||
|
||||
use zcash_primitives::{
|
||||
consensus::{self, BranchId, NetworkUpgrade},
|
||||
note_encryption::Memo,
|
||||
memo::Memo,
|
||||
prover::TxProver,
|
||||
transaction::{
|
||||
builder::Builder,
|
||||
|
|
|
@ -2,7 +2,8 @@ use std::collections::HashMap;
|
|||
|
||||
use zcash_primitives::{
|
||||
consensus::{self, BlockHeight},
|
||||
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery, Memo},
|
||||
memo::Memo,
|
||||
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery},
|
||||
primitives::{Note, PaymentAddress},
|
||||
transaction::Transaction,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
|
|
|
@ -152,7 +152,7 @@ impl ScanningKey for SaplingIvk {
|
|||
/// The implementation of [`ScanningKey`] may either support or omit the computation of
|
||||
/// the nullifiers for received notes; the implementation for [`ExtendedFullViewingKey`]
|
||||
/// will derive the nullifiers for received notes and return them as part of the resulting
|
||||
/// [`WalletShieldedOutput`]s, whereas since the implementation for [`SaplingIvk`] cannot
|
||||
/// [`WalletShieldedOutput`]s, whereas since the implementation for [`SaplingIvk`] cannot
|
||||
/// do so and it will return the unit value in those outputs instead.
|
||||
///
|
||||
/// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey
|
||||
|
@ -275,8 +275,9 @@ mod tests {
|
|||
use zcash_primitives::{
|
||||
consensus::{BlockHeight, Network},
|
||||
constants::SPENDING_KEY_GENERATOR,
|
||||
memo::Memo,
|
||||
merkle_tree::CommitmentTree,
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Note, Nullifier, SaplingIvk},
|
||||
transaction::components::Amount,
|
||||
util::generate_random_rseed,
|
||||
|
|
|
@ -545,7 +545,8 @@ mod tests {
|
|||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{BlockHeight, Network, NetworkUpgrade, Parameters},
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
memo::Memo,
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Note, Nullifier, PaymentAddress},
|
||||
transaction::components::Amount,
|
||||
util::generate_random_rseed,
|
||||
|
|
|
@ -7,8 +7,8 @@ use std::collections::HashMap;
|
|||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{self, BlockHeight, NetworkUpgrade},
|
||||
memo::Memo,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::Memo,
|
||||
primitives::{Note, Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
transaction::{components::Amount, Transaction, TxId},
|
||||
|
|
|
@ -3,7 +3,8 @@ use ff::Field;
|
|||
use rand_core::OsRng;
|
||||
use zcash_primitives::{
|
||||
consensus::{NetworkUpgrade::Canopy, Parameters, TEST_NETWORK},
|
||||
note_encryption::{try_sapling_note_decryption, Memo, SaplingNoteEncryption},
|
||||
memo::Memo,
|
||||
note_encryption::{try_sapling_note_decryption, SaplingNoteEncryption},
|
||||
primitives::{Diversifier, PaymentAddress, SaplingIvk, ValueCommitment},
|
||||
transaction::components::{OutputDescription, GROTH_PROOF_SIZE},
|
||||
util::generate_random_rseed,
|
||||
|
|
|
@ -13,6 +13,7 @@ pub mod constants;
|
|||
pub mod group_hash;
|
||||
pub mod keys;
|
||||
pub mod legacy;
|
||||
pub mod memo;
|
||||
pub mod merkle_tree;
|
||||
pub mod note_encryption;
|
||||
pub mod pedersen_hash;
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
//! Structs for handling encrypted memos.
|
||||
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
|
||||
/// Format a byte array as a colon-delimited hex string.
|
||||
///
|
||||
/// Source: https://github.com/tendermint/signatory
|
||||
/// License: MIT / Apache 2.0
|
||||
fn fmt_colon_delimited_hex<B>(f: &mut fmt::Formatter<'_>, bytes: B) -> fmt::Result
|
||||
where
|
||||
B: AsRef<[u8]>,
|
||||
{
|
||||
let len = bytes.as_ref().len();
|
||||
|
||||
for (i, byte) in bytes.as_ref().iter().enumerate() {
|
||||
write!(f, "{:02x}", byte)?;
|
||||
|
||||
if i != len - 1 {
|
||||
write!(f, ":")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An unencrypted memo received alongside a shielded note in a Zcash transaction.
|
||||
#[derive(Clone)]
|
||||
pub struct Memo(pub(crate) [u8; 512]);
|
||||
|
||||
impl fmt::Debug for Memo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Memo(")?;
|
||||
match self.to_utf8() {
|
||||
Some(Ok(memo)) => write!(f, "\"{}\"", memo)?,
|
||||
_ => fmt_colon_delimited_hex(f, &self.0[..])?,
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Memo {
|
||||
fn default() -> Self {
|
||||
// Empty memo field indication per ZIP 302
|
||||
let mut memo = [0u8; 512];
|
||||
memo[0] = 0xF6;
|
||||
Memo(memo)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Memo {
|
||||
fn eq(&self, rhs: &Memo) -> bool {
|
||||
self.0[..] == rhs.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Memo {
|
||||
/// Returns a `Memo` containing the given slice, appending with zero bytes if
|
||||
/// necessary, or `None` if the slice is too long. If the slice is empty,
|
||||
/// `Memo::default` is returned.
|
||||
pub fn from_bytes(memo: &[u8]) -> Option<Memo> {
|
||||
if memo.is_empty() {
|
||||
Some(Memo::default())
|
||||
} else if memo.len() <= 512 {
|
||||
let mut data = [0; 512];
|
||||
data[0..memo.len()].copy_from_slice(memo);
|
||||
Some(Memo(data))
|
||||
} else {
|
||||
// memo is too long
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the underlying bytes of the `Memo`.
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
|
||||
/// Returns:
|
||||
/// - `None` if the memo is not text
|
||||
/// - `Some(Ok(memo))` if the memo contains a valid UTF-8 string
|
||||
/// - `Some(Err(e))` if the memo contains invalid UTF-8
|
||||
pub fn to_utf8(&self) -> Option<Result<String, str::Utf8Error>> {
|
||||
// Check if it is a text or binary memo
|
||||
if self.0[0] < 0xF5 {
|
||||
// Check if it is valid UTF8
|
||||
Some(str::from_utf8(&self.0).map(|memo| {
|
||||
// Drop trailing zeroes
|
||||
memo.trim_end_matches(char::from(0)).to_owned()
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for Memo {
|
||||
type Err = ();
|
||||
|
||||
/// Returns a `Memo` containing the given string, or an error if the string is too long.
|
||||
fn from_str(memo: &str) -> Result<Self, Self::Err> {
|
||||
Memo::from_bytes(memo.as_bytes()).ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::Memo;
|
||||
|
||||
#[test]
|
||||
fn memo_from_str() {
|
||||
assert_eq!(
|
||||
Memo::from_str("").unwrap(),
|
||||
Memo([
|
||||
0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
])
|
||||
);
|
||||
assert_eq!(
|
||||
Memo::from_str(
|
||||
"thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
|
||||
veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong \
|
||||
meeeeeeeeeeeeeeeeeeemooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo \
|
||||
but it's just short enough"
|
||||
)
|
||||
.unwrap(),
|
||||
Memo([
|
||||
0x74, 0x68, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x73, 0x20, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x73, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x20, 0x76, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x72, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x20, 0x6c, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, 0x67, 0x20, 0x6d,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x20, 0x62, 0x75, 0x74, 0x20,
|
||||
0x69, 0x74, 0x27, 0x73, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x72,
|
||||
0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68
|
||||
])
|
||||
);
|
||||
assert_eq!(
|
||||
Memo::from_str(
|
||||
"thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
|
||||
veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong \
|
||||
meeeeeeeeeeeeeeeeeeemooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo \
|
||||
but it's now a bit too long"
|
||||
),
|
||||
Err(())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memo_to_utf8() {
|
||||
let memo = Memo::from_str("Test memo").unwrap();
|
||||
assert_eq!(memo.to_utf8(), Some(Ok("Test memo".to_owned())));
|
||||
assert_eq!(Memo::default().to_utf8(), None);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::{
|
||||
consensus::{self, BlockHeight, NetworkUpgrade::Canopy, ZIP212_GRACE_PERIOD},
|
||||
memo::Memo,
|
||||
primitives::{Diversifier, Note, PaymentAddress, Rseed, SaplingIvk},
|
||||
};
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
|
@ -11,8 +12,6 @@ use ff::PrimeField;
|
|||
use group::{cofactor::CofactorGroup, GroupEncoding};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
|
||||
use crate::keys::OutgoingViewingKey;
|
||||
|
||||
|
@ -29,106 +28,6 @@ const OUT_PLAINTEXT_SIZE: usize = 32 + // pk_d
|
|||
pub const ENC_CIPHERTEXT_SIZE: usize = NOTE_PLAINTEXT_SIZE + 16;
|
||||
pub const OUT_CIPHERTEXT_SIZE: usize = OUT_PLAINTEXT_SIZE + 16;
|
||||
|
||||
/// Format a byte array as a colon-delimited hex string.
|
||||
///
|
||||
/// Source: https://github.com/tendermint/signatory
|
||||
/// License: MIT / Apache 2.0
|
||||
fn fmt_colon_delimited_hex<B>(f: &mut fmt::Formatter<'_>, bytes: B) -> fmt::Result
|
||||
where
|
||||
B: AsRef<[u8]>,
|
||||
{
|
||||
let len = bytes.as_ref().len();
|
||||
|
||||
for (i, byte) in bytes.as_ref().iter().enumerate() {
|
||||
write!(f, "{:02x}", byte)?;
|
||||
|
||||
if i != len - 1 {
|
||||
write!(f, ":")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An unencrypted memo received alongside a shielded note in a Zcash transaction.
|
||||
#[derive(Clone)]
|
||||
pub struct Memo([u8; 512]);
|
||||
|
||||
impl fmt::Debug for Memo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Memo(")?;
|
||||
match self.to_utf8() {
|
||||
Some(Ok(memo)) => write!(f, "\"{}\"", memo)?,
|
||||
_ => fmt_colon_delimited_hex(f, &self.0[..])?,
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Memo {
|
||||
fn default() -> Self {
|
||||
// Empty memo field indication per ZIP 302
|
||||
let mut memo = [0u8; 512];
|
||||
memo[0] = 0xF6;
|
||||
Memo(memo)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Memo {
|
||||
fn eq(&self, rhs: &Memo) -> bool {
|
||||
self.0[..] == rhs.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Memo {
|
||||
/// Returns a `Memo` containing the given slice, appending with zero bytes if
|
||||
/// necessary, or `None` if the slice is too long. If the slice is empty,
|
||||
/// `Memo::default` is returned.
|
||||
pub fn from_bytes(memo: &[u8]) -> Option<Memo> {
|
||||
if memo.is_empty() {
|
||||
Some(Memo::default())
|
||||
} else if memo.len() <= 512 {
|
||||
let mut data = [0; 512];
|
||||
data[0..memo.len()].copy_from_slice(memo);
|
||||
Some(Memo(data))
|
||||
} else {
|
||||
// memo is too long
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the underlying bytes of the `Memo`.
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
|
||||
/// Returns:
|
||||
/// - `None` if the memo is not text
|
||||
/// - `Some(Ok(memo))` if the memo contains a valid UTF-8 string
|
||||
/// - `Some(Err(e))` if the memo contains invalid UTF-8
|
||||
pub fn to_utf8(&self) -> Option<Result<String, str::Utf8Error>> {
|
||||
// Check if it is a text or binary memo
|
||||
if self.0[0] < 0xF5 {
|
||||
// Check if it is valid UTF8
|
||||
Some(str::from_utf8(&self.0).map(|memo| {
|
||||
// Drop trailing zeroes
|
||||
memo.trim_end_matches(char::from(0)).to_owned()
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for Memo {
|
||||
type Err = ();
|
||||
|
||||
/// Returns a `Memo` containing the given string, or an error if the string is too long.
|
||||
fn from_str(memo: &str) -> Result<Self, Self::Err> {
|
||||
Memo::from_bytes(memo.as_bytes()).ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sapling key agreement for note encryption.
|
||||
///
|
||||
/// Implements section 5.4.4.3 of the Zcash Protocol Specification.
|
||||
|
@ -214,7 +113,8 @@ pub fn prf_ock(
|
|||
/// use rand_core::OsRng;
|
||||
/// use zcash_primitives::{
|
||||
/// keys::{OutgoingViewingKey, prf_expand},
|
||||
/// note_encryption::{Memo, SaplingNoteEncryption},
|
||||
/// memo::Memo,
|
||||
/// note_encryption::SaplingNoteEncryption,
|
||||
/// primitives::{Diversifier, PaymentAddress, Rseed, ValueCommitment},
|
||||
/// };
|
||||
///
|
||||
|
@ -666,12 +566,11 @@ mod tests {
|
|||
use rand_core::OsRng;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use std::convert::TryInto;
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::{
|
||||
kdf_sapling, prf_ock, sapling_ka_agree, try_sapling_compact_note_decryption,
|
||||
try_sapling_note_decryption, try_sapling_output_recovery,
|
||||
try_sapling_output_recovery_with_ock, Memo, OutgoingCipherKey, SaplingNoteEncryption,
|
||||
try_sapling_output_recovery_with_ock, OutgoingCipherKey, SaplingNoteEncryption,
|
||||
COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE, NOTE_PLAINTEXT_SIZE, OUT_CIPHERTEXT_SIZE,
|
||||
OUT_PLAINTEXT_SIZE,
|
||||
};
|
||||
|
@ -683,126 +582,11 @@ mod tests {
|
|||
Parameters, TEST_NETWORK, ZIP212_GRACE_PERIOD,
|
||||
},
|
||||
keys::OutgoingViewingKey,
|
||||
memo::Memo,
|
||||
primitives::{Diversifier, PaymentAddress, Rseed, SaplingIvk, ValueCommitment},
|
||||
util::generate_random_rseed,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn memo_from_str() {
|
||||
assert_eq!(
|
||||
Memo::from_str("").unwrap(),
|
||||
Memo([
|
||||
0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
])
|
||||
);
|
||||
assert_eq!(
|
||||
Memo::from_str(
|
||||
"thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
|
||||
veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong \
|
||||
meeeeeeeeeeeeeeeeeeemooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo \
|
||||
but it's just short enough"
|
||||
)
|
||||
.unwrap(),
|
||||
Memo([
|
||||
0x74, 0x68, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x73, 0x20, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x73, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x20, 0x76, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x72, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x20, 0x6c, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, 0x67, 0x20, 0x6d,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x20, 0x62, 0x75, 0x74, 0x20,
|
||||
0x69, 0x74, 0x27, 0x73, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x72,
|
||||
0x74, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68
|
||||
])
|
||||
);
|
||||
assert_eq!(
|
||||
Memo::from_str(
|
||||
"thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis \
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
|
||||
veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong \
|
||||
meeeeeeeeeeeeeeeeeeemooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo \
|
||||
but it's now a bit too long"
|
||||
),
|
||||
Err(())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memo_to_utf8() {
|
||||
let memo = Memo::from_str("Test memo").unwrap();
|
||||
assert_eq!(memo.to_utf8(), Some(Ok("Test memo".to_owned())));
|
||||
assert_eq!(Memo::default().to_utf8(), None);
|
||||
}
|
||||
|
||||
fn random_enc_ciphertext<R: RngCore + CryptoRng>(
|
||||
height: BlockHeight,
|
||||
mut rng: &mut R,
|
||||
|
|
|
@ -14,8 +14,9 @@ use crate::{
|
|||
consensus::{self, BlockHeight},
|
||||
keys::OutgoingViewingKey,
|
||||
legacy::TransparentAddress,
|
||||
memo::Memo,
|
||||
merkle_tree::MerklePath,
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Diversifier, Note, PaymentAddress},
|
||||
prover::TxProver,
|
||||
redjubjub::PrivateKey,
|
||||
|
|
Loading…
Reference in New Issue