Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction primitives #39

Merged
merged 14 commits into from
Nov 30, 2018
Merged

Conversation

str4d
Copy link
Contributor

@str4d str4d commented Oct 11, 2018

Implements support for parsing all transaction versions, and the transaction digest algorithms from ZIP 143 and ZIP 243.

@str4d str4d requested review from daira and ebfull October 11, 2018 18:27
@str4d str4d mentioned this pull request Oct 11, 2018
str4d added 3 commits November 9, 2018 08:34
Users who have a Transaction can now only obtain an immutable reference
to its underlying data.
@str4d str4d force-pushed the zcash-transaction-primitives branch from 3cdc0dd to 1f11c40 Compare November 8, 2018 19:35
writer.write_u8(254)?;
writer.write_u32::<LittleEndian>(s as u32)
}
s => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this fail if s > 0x02000000?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know what the rationale was for that?

(I'd be terrified to change it, mind :-) )

n => Ok(n as usize),
}
}? {
s if s > 0x02000000 => Err(io::Error::new(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make a constant for 0x02000000?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's called MAX_SIZE in src/serialize.h.

zcash_primitives/src/serialize.rs Outdated Show resolved Hide resolved
zcash_primitives/src/transaction/tests.rs Show resolved Hide resolved
Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a migraine so I won't be able to review more tonight.

n => Ok(n as usize),
}
}? {
s if s > 0x02000000 => Err(io::Error::new(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's called MAX_SIZE in src/serialize.h.

}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed that these exactly match the behaviour of the C++ code.

writer.write_u8(254)?;
writer.write_u32::<LittleEndian>(s as u32)
}
s => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know what the rationale was for that?

(I'd be terrified to change it, mind :-) )


impl TxOut {
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
let value = Amount(reader.read_i64::<LittleEndian>()?);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we check that this is in {0..MAX_MONEY}?

Copy link
Contributor Author

@str4d str4d Nov 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowhere yet. I'll add a function to perform the necessary range check.


impl SpendDescription {
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
let cv = edwards::Point::<Bls12, Unknown>::read(&mut reader, &JUBJUB)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cv are rk are required to not be of small order (see section 4.4 of the spec). Where is that checked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is eventually checked during proof validation: 1f07d94#diff-43fed083a323e370f8efa22a3cf1b0ccR45

However, if you'd prefer that we also check these during parsing, I can do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't insist on rules being implemented in specific places, but for reviewability, it's important to be able to check that all (and only!) the consensus rules described in the spec are implemented somewhere.

Perhaps we can follow the following policy:

  • every consensus check (including implicit checks in parsing) should be documented with a comment referencing the section of the spec describing it;
  • if you might expect a consensus check but it's actually somewhere else in the code, add a comment pointing to the somewhere else.

One concern might be that the second category of comments could get stale, but I think that is manageable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(If rules are moved around in the spec, this requires updating the comments. Up to now they haven't moved around much, if at all.)


impl OutputDescription {
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
let cv = edwards::Point::<Bls12, Unknown>::read(&mut reader, &JUBJUB)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cv are epk are required to not be of small order (see section 4.5 of the spec). Where is that checked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is eventually checked during proof validation: 1f07d94#diff-43fed083a323e370f8efa22a3cf1b0ccR127

However, if you'd prefer that we also check these during parsing, I can do so.

impl JSDescription {
pub fn read<R: Read>(mut reader: R, use_groth: bool) -> io::Result<Self> {
let vpub_old = Amount(reader.read_i64::<LittleEndian>()?);
let vpub_new = Amount(reader.read_i64::<LittleEndian>()?);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically these fields are unsigned (section 7.2 of the spec). More precisely they're in the range {0..MAX_MONEY}.

Copy link
Contributor Author

@str4d str4d Nov 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amount parallels CAmount in zcashd, handling the fact that amounts may be subtracted with negative results. I'll add a function to perform the necessary range check as well as converting from u64 to i64, to make things clearer (so we use read_u64() to more closely match the spec).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there should be a RestrictedAmount or CheckedAmount trait that is guaranteed to be in the {0..MAX_MONEY} range, with checked arithmetic?

zcash_primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
zcash_primitives/src/transaction/mod.rs Show resolved Hide resolved
zcash_primitives/src/transaction/tests.rs Show resolved Hide resolved
Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ut(ACK+cov) modulo comments.

zcash_primitives/src/transaction/sighash.rs Show resolved Hide resolved
zcash_primitives/src/transaction/sighash.rs Outdated Show resolved Hide resolved
zcash_primitives/src/transaction/sighash.rs Show resolved Hide resolved
0xb0, 0x06, 0xc0, 0x62, 0x46, 0x8e, 0x4b, 0xd8, 0xf7, 0xdd, 0x9a, 0xf6, 0x98, 0xf5,
0x2a, 0xe8, 0x14, 0x63, 0x4e, 0x81, 0xd7, 0xf3, 0xe0, 0xc4, 0x20, 0x31, 0x7c, 0xac,
0xa9, 0xae, 0x48, 0x11, 0xc6, 0xaf, 0x06, 0xfe, 0x80, 0xa8, 0xc0, 0x2a, 0xb7, 0xa0,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not check these test vectors in my review.

zcash_primitives/src/transaction/sighash.rs Show resolved Hide resolved
0xe7, 0xe6, 0x15, 0x9c, 0x46, 0x69, 0x9f, 0x10, 0x07, 0x92, 0xd4, 0x67, 0x29, 0x50,
0x34, 0x8a, 0x90, 0x55, 0x2e, 0x45, 0x94, 0x3b, 0xee, 0xac, 0xf0, 0x3f, 0x32, 0x16,
0xf9, 0x4e, 0x27, 0x90, 0x6e, 0xdc, 0x63, 0x23, 0x19, 0xad, 0x8d, 0x37, 0x44, 0x7f,
0x5c, 0x59, 0xcc, 0xde
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not checked these test vectors either.

zcash_primitives/src/transaction/mod.rs Show resolved Hide resolved
zcash_primitives/src/serialize.rs Show resolved Hide resolved
zcash_primitives/src/transaction/components.rs Outdated Show resolved Hide resolved
@str4d
Copy link
Contributor Author

str4d commented Nov 30, 2018

Addressed @daira's remaining comments.

@daira
Copy link
Contributor

daira commented Nov 30, 2018

ut(ACK+cov) c9b23df.

@str4d str4d merged commit 8be50c9 into zcash:master Nov 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants