Closed hdevalence closed 4 years ago
I started writing some first-pass notes mapping out the zcash_primitives
crate. They are currently UNFINISHED, and I will keep editing this comment until they are done.
Notes on zcash_primitives
, starting from lib.rs
and working outwards. The order they appear here is the order in which I read through them, which is mostly arbitrary but attempts to be in internal module dependency order.
serialize
and util
modules, which
are private.jubjub::JubjubBls12
into the crate root.lazy_static!
'd JUBJUB
instance.struct CompactSize
with CompactSize
encoding and
decoding logic.CompactSize
instances are never constructed, they're only used to name the
encoding methods.CompactSize
.struct Vector
and struct Optional
, used for
encoding arrays and Option<T>
s, respectively.read
and write
methods outside of a trait.hash_to_scalar<E: JubjubEngine>
struct BlockHash(pub [u8; 32])
Display
impl reverses the bytes of the hash before hex encoding -- is this
to make the format line up with something else, and should we try to match?from_slice
constructorstruct BlockHeaderData
struct BlockHeader { hash: BlockHash, data: BlockHeaderData }
from_data
constructor (not a From
impl) computes a hashread
, write
functionsimpl Deref<Target=BlockHeaderData> for BlockHeader
seems like an abuse of
deref coercions to meBlockHeaderData
can be cachedenum Unknown {}
, enum PrimeOrder {}
, enum FixedGenerators { ... }
Unknown
and PrimeOrder
are enums rather than structs, which
is how I've seen this before – maybe for consistency with
FixedGenerators
?ToUniform
– generic hash-to-element interface?JubJubEngine
- extension to the pairing
Engine
trait adding the
embedded curve functionalityPhantomData
PhantomData
ff
traits.test_suite<E: JubjubEngine>
that calls each function in the test
suite#[test]
in mod.rs
, which doesn't seem
to be cfg
-gated?enum Personalization { NoteCommitment, MerkleTree(usize) }
pub fn Personalization::get_bits(&self) -> Vec<bool>
could save an
alloc by returning [bool; 6]
and may not need to be pub
?fn pedersen_hash
performs the pedersen hashprimitives
struct ValueCommitment
represents the opening of a value commitmentValueCommitment::cm
computes the commitment itselfstruct ProofGenerationKey
struct ViewingKey
ProofGenerationKey::to_viewing_key
performs the conversion, but needs an
&E::Params
so it can't be a From
impl -- is this avoidable?ViewingKey
has functions rk
, ivk
, etc., which presumably correspond to
the abbreviations in the spec, but there aren't doc comments if the
abbreviation isn't already clearstruct Diversifier
struct PaymentAddress
PartialEq
implementation, but not Eq
– could be replaced with
derived impls?PaymentAddress
es are constructed either from_parts
or from_bytes
from_parts_unchecked
function also exists for testing, but it's unclear
why test code couldn't just unwrap
or expect
on from_parts
struct Note
PartialEq
implementationpub fn prf_expand
, pub fn prf_expand_vec
seem to only ever be used here
and in zip32.rs
– do they need to be public?pub struct OutgoingViewingKey(pub [u8; 32])
pub struct ExpandedSpendingKey
has public fields ask
, nsk
, ovk
pub struct FullViewingKey
has vk: ViewingKey
and ovk: OutgoingViewingKey
vk
but outgoing are ovk
.ExpandedSpendingKey
has from_spending_key(sk: &[u8])
but there doesn't
appear to be a SpendingKey
type -- is the byte slice just a serialized form?read
and write
methods for ExpandedSpendingKey
serialize the whole esk,
but all of the data is derivable from the sk
above, so why serialize all
the data?impl Clone for FullViewingKey
that could probably be derivedFullViewingKey
has a from_expanded_spending_key
method that takes an
esk and a E::Params
.
E::Params
has to be passed around
because it means that it's not possible to write all of these type
conversions as From
impls.pub struct Script(pub Vec<u8>)
with read
, write
.impl Shl<OpCode> for Script
is used to implement concatenation like
a C++ iostream
std::ops::Shl
is an arithmetic operation!impl FromIterator<Opcode> for Script
pub enum TransparentAddress
is either a PublicKey([u8; 20])
or a
Script([u8; 20])
.TransparentAddress::script() -> Script
constructs a script for the addr.pub trait Hashable: Clone + Copy
read
, write
for serializationcombine
returns the parent node of two treesblank
returns a blank leaf nodeempty_root
returns the empty root for the given depthHashable
in this fileimpl Hashable for Node
in sapling.rs
struct PathFiller<Node: Hashable>
is a wrapper for VecDeque<Node>
that
wraps pop_front
with unwrap_or_else(|| Node::empty_root(depth))
empty
instead of Default
pub struct CommitmentTree<Node: Hashable>
provides a Merkle tree of note
commitments
new()
should be impl Default
read
, write
methodssize
computes the number of leaf nodes in the treeappend
adds a Node
by calling append_inner
with
SAPLING_COMMITMENT_TREE_DEPTH
root
returns the tree root, calls root_inner
with
SAPLING_COMMITMENT_TREE_DEPTH
and an empty PathFiller
pub struct IncrementalWitness<Node: Hashable>
pub struct CommitmentTreeWitness<Node: Hashable>
from_path
constructorfrom_slice
constructor from its serialized form -- is this serialization
consensus-critical? and where is the serialization defined?from_slice
reveals its use in FFI,
librustzcash_sapling_spend_proof
.pub struct Memo([u8; 512])
impl Default for Memo
constructs an empty memo field per ZIP302PartialEq
implementation -- could be derived instead?Memo::to_utf8
parses UTF-8impl str::FromStr for Memo
pub fn generate_esk(rng) -> Fs
?? shouldn't this be part of the
ExtendedSpendingKey
type, and why does it return a raw scalar?pub fn sapling_ka_agree
, fn kdf_sapling
do key agreement and kdf for note
encryption (protocol §5.4.4.3–4)fn prf_ock
does the sapling prf (protocol §5.4.2)pub struct SaplingNoteEncryption
is supposed to provide a safe API for
encrypting Sapling notes.
new
constructor takes an OutgoingViewingKey
, a Note<Bls12>
, a
PaymentAddress<Bls12>
, a Memo
, and an RNG.Bls12
parameter appears in Note
and
PaymentAddress
...esk
and epk
gettersencrypt_note_plaintext
creates an encCiphertext
as [u8; ENC_CIPHERTEXT_SIZE]
encrypt_outgoing_plaintext
creates an outCiphertext
as [u8; OUT_CIPHERTEXT_SIZE]
&self
fn parse_note_plaintext_without_memo
computes an Option<(Note<Bls12>, PaymentAddress<Bls12>)>
pub fn try_sapling_note_decryption
does "Trial decryption of the full note
plaintext by the recipient. Attempts to decrypt and validate the given
enc_ciphertext
using the given ivk
."
Option<(Note<Bls12>, PaymentAddress<Bls12>, Memo)>
ivk
, epk
, cmu
, enc_ciphertext
epk, cmu
do?IncomingViewingKey::trial_decrypt(ciphertext)
?pub fn try_sapling_compact_note_decryption
seems similar but skips the memo
field; corresponds to ZIP307pub fn try_sapling_output_recovery
does protocol spec §4.17.3
Option<(Note<Bls12>, PaymentAddress<Bls12>, Memo)>
try_sapling_note_decryption
?Look here re: #34
Now that this issue has been closed, can I assume the review above is "complete"? If so, I'll go through it next week and open librustzcash issues for anything that we definitely want to address.
I'm not sure I'd say it was "complete" so much as "abandoned", in the sense that the parts that there are notes on are completed, but the parts that there aren't notes on have not been completed, and because of other priorities the uncompleted parts probably won't be finished in the near term.
Now that the
zcash_primitives
crate has been published and we have mostly finished the networking code, we should analyze the overlap betweenzcash_primitives
andzebra_chain
, and decide:zcash_primitives
intozebra_chain
;zebra_chain
intozcash_primitives
and upstream the changes.