From d10a2b78b1100aba9122afb526f7d456c9cbedd1 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 27 Feb 2021 10:56:50 -0300 Subject: [PATCH 01/29] add transaction V5 stub --- zebra-chain/src/transaction.rs | 19 +++++++++++++++++++ zebra-chain/src/transaction/serialize.rs | 18 ++++++++++++++++++ zebra-chain/src/transaction/sighash.rs | 17 ++++++++++++----- zebra-consensus/src/transaction.rs | 5 ++++- zebra-consensus/src/transaction/check.rs | 10 ++++++++-- zebra-state/src/tests.rs | 1 + 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 1d8401f643e..23bd30258b8 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -99,6 +99,21 @@ pub enum Transaction { /// The shielded data for this transaction, if any. shielded_data: Option, }, + /// An Orchard transaction (`version = 5`). + V5 { + /// The transparent inputs to the transaction. + tx_in: Vec, + /// The transparent outputs from the transaction. + tx_out: Vec, + /// The earliest time or block height that this transaction can be added to the + /// chain. + lock_time: LockTime, + /// The latest block height that this transaction can be added to the chain. + expiry_height: block::Height, + + /// The rest of the transaction as bytes + rest: Vec, + }, } impl Transaction { @@ -114,6 +129,7 @@ impl Transaction { Transaction::V2 { ref inputs, .. } => inputs, Transaction::V3 { ref inputs, .. } => inputs, Transaction::V4 { ref inputs, .. } => inputs, + Transaction::V5 { ref tx_in, .. } => tx_in, } } @@ -124,6 +140,7 @@ impl Transaction { Transaction::V2 { ref outputs, .. } => outputs, Transaction::V3 { ref outputs, .. } => outputs, Transaction::V4 { ref outputs, .. } => outputs, + Transaction::V5 { ref tx_out, .. } => tx_out, } } @@ -134,6 +151,7 @@ impl Transaction { Transaction::V2 { lock_time, .. } => *lock_time, Transaction::V3 { lock_time, .. } => *lock_time, Transaction::V4 { lock_time, .. } => *lock_time, + Transaction::V5 { lock_time, .. } => *lock_time, } } @@ -144,6 +162,7 @@ impl Transaction { Transaction::V2 { .. } => None, Transaction::V3 { expiry_height, .. } => Some(*expiry_height), Transaction::V4 { expiry_height, .. } => Some(*expiry_height), + Transaction::V5 { expiry_height, .. } => Some(*expiry_height), } } diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index dc9c28fa776..2fa6fd8883f 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -18,6 +18,7 @@ use super::*; const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; +const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; impl ZcashDeserialize for jubjub::Fq { fn zcash_deserialize(mut reader: R) -> Result { @@ -182,6 +183,23 @@ impl ZcashSerialize for Transaction { None => {} } } + Transaction::V5 { + tx_in, + tx_out, + lock_time, + expiry_height, + rest, + } => { + // Write version 4 and set the fOverwintered bit. + writer.write_u32::(4 | (1 << 31))?; + writer.write_u32::(ORCHARD_VERSION_GROUP_ID)?; + tx_in.zcash_serialize(&mut writer)?; + tx_out.zcash_serialize(&mut writer)?; + lock_time.zcash_serialize(&mut writer)?; + writer.write_u32::(expiry_height.0)?; + // write the rest + writer.write_all(rest)?; + } } Ok(()) } diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index 525b503523e..fc5795386ce 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -14,6 +14,7 @@ static ZIP243_EXPLANATION: &str = "Invalid transaction version: after Sapling ac const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; +const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; const ZCASH_SIGHASH_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZcashSigHash"; const ZCASH_PREVOUTS_HASH_PERSONALIZATION: &[u8; 16] = b"ZcashPrevoutHash"; @@ -129,6 +130,7 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { .. } => 3 | overwintered_flag, Transaction::V4 { .. } => 4 | overwintered_flag, + Transaction::V5 { .. } => 5 | overwintered_flag, }) } @@ -137,6 +139,7 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { .. } => OVERWINTER_VERSION_GROUP_ID, Transaction::V4 { .. } => SAPLING_VERSION_GROUP_ID, + Transaction::V5 { .. } => ORCHARD_VERSION_GROUP_ID, }) } @@ -243,6 +246,7 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { joinsplit_data, .. } => joinsplit_data.is_some(), Transaction::V4 { joinsplit_data, .. } => joinsplit_data.is_some(), + Transaction::V5 { .. } => unimplemented!("v5 transaction"), }; if !has_joinsplits { @@ -398,14 +402,15 @@ impl<'a> SigHasher<'a> { use Transaction::*; let shielded_data = match self.trans { - Transaction::V4 { + V4 { shielded_data: Some(shielded_data), .. } => shielded_data, - Transaction::V4 { + V4 { shielded_data: None, .. } => return writer.write_all(&[0; 32]), + V5 { .. } => unimplemented!("v5 transaction"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; @@ -434,14 +439,15 @@ impl<'a> SigHasher<'a> { use Transaction::*; let shielded_data = match self.trans { - Transaction::V4 { + V4 { shielded_data: Some(shielded_data), .. } => shielded_data, - Transaction::V4 { + V4 { shielded_data: None, .. } => return writer.write_all(&[0; 32]), + V5 { .. } => unimplemented!("v5 transaction"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; @@ -465,7 +471,8 @@ impl<'a> SigHasher<'a> { use Transaction::*; let value_balance = match self.trans { - Transaction::V4 { value_balance, .. } => value_balance, + V4 { value_balance, .. } => value_balance, + V5 { .. } => unreachable!("NOT IMPLEMENTED YET!"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index ae684ae9fa4..33244f9ba44 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -132,7 +132,10 @@ where async move { tracing::trace!(?tx); match &*tx { - Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V5 { .. } => { tracing::debug!(?tx, "got transaction with wrong version"); Err(TransactionError::WrongVersion) } diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index fb2316ab8ba..710ede6bf3d 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -68,7 +68,10 @@ pub fn has_inputs_and_outputs(tx: &Transaction) -> Result<(), TransactionError> Ok(()) } } - Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V5 { .. } => { unreachable!("tx version is checked first") } } @@ -111,7 +114,10 @@ pub fn coinbase_tx_no_joinsplit_or_spend(tx: &Transaction) -> Result<(), Transac Transaction::V4 { .. } => Ok(()), - Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V5 { .. } => { unreachable!("tx version is checked first") } } diff --git a/zebra-state/src/tests.rs b/zebra-state/src/tests.rs index 8510504fe18..457a0dfe200 100644 --- a/zebra-state/src/tests.rs +++ b/zebra-state/src/tests.rs @@ -53,6 +53,7 @@ impl FakeChainHelper for Arc { Transaction::V2 { inputs, .. } => &mut inputs[0], Transaction::V3 { inputs, .. } => &mut inputs[0], Transaction::V4 { inputs, .. } => &mut inputs[0], + Transaction::V5 { tx_in, .. } => &mut tx_in[0], }; match input { From dc014d5eef06e4386bebc2992359d534da058ae6 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 27 Feb 2021 13:58:23 -0300 Subject: [PATCH 02/29] add v5_strategy --- zebra-chain/src/transaction/arbitrary.rs | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index c34da137b33..cea6caf416c 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -104,6 +104,26 @@ impl Transaction { ) .boxed() } + /// Generate a proptest strategy for V5 Transactions + pub fn v5_strategy(ledger_state: LedgerState) -> BoxedStrategy { + ( + transparent::Input::vec_strategy(ledger_state, 10), + vec(any::(), 0..10), + any::(), + any::(), + any::>(), + ) + .prop_map( + |(tx_in, tx_out, lock_time, expiry_height, rest)| Transaction::V5 { + tx_in, + tx_out, + lock_time, + expiry_height, + rest, + }, + ) + .boxed() + } /// Proptest Strategy for creating a Vector of transactions where the first /// transaction is always the only coinbase transaction @@ -236,9 +256,8 @@ impl Arbitrary for Transaction { NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) } - NetworkUpgrade::NU5 => { - unimplemented!("NU5 upgrade can use v4 or v5 transactions, as specified in ZIP-225") - } + // Blocked by #1823 + //NetworkUpgrade::NU5 => Self::v5_strategy(ledger_state), } } From 402aa9ed24f8d5a62906f0184b1d539382f12b0d Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 27 Feb 2021 14:52:01 -0300 Subject: [PATCH 03/29] deduplicate version group ids --- zebra-chain/src/parameters.rs | 2 ++ zebra-chain/src/parameters/transaction.rs | 8 ++++++++ zebra-chain/src/transaction/serialize.rs | 5 +---- zebra-chain/src/transaction/sighash.rs | 9 ++++----- 4 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 zebra-chain/src/parameters/transaction.rs diff --git a/zebra-chain/src/parameters.rs b/zebra-chain/src/parameters.rs index 0fa86428d44..ff369e79853 100644 --- a/zebra-chain/src/parameters.rs +++ b/zebra-chain/src/parameters.rs @@ -15,10 +15,12 @@ mod genesis; mod network; mod network_upgrade; +mod transaction; pub use genesis::*; pub use network::Network; pub use network_upgrade::*; +pub use transaction::*; #[cfg(test)] mod tests; diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs new file mode 100644 index 00000000000..a0857dd10a9 --- /dev/null +++ b/zebra-chain/src/parameters/transaction.rs @@ -0,0 +1,8 @@ +//! Transaction consensus and utility parameters. + +///The Overwinter version group ID. +pub const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; +///The Sapling version group ID. +pub const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; +///The Orchard version group ID. +pub const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 2fa6fd8883f..d6ac55b6e23 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -6,6 +6,7 @@ use std::{io, sync::Arc}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crate::{ + parameters::{ORCHARD_VERSION_GROUP_ID, OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID}, primitives::ZkSnarkProof, serialization::{ ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashDeserializeInto, @@ -16,10 +17,6 @@ use crate::{ use super::*; -const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; -const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; -const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; - impl ZcashDeserialize for jubjub::Fq { fn zcash_deserialize(mut reader: R) -> Result { let possible_scalar = jubjub::Fq::from_bytes(&reader.read_32_bytes()?); diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index fc5795386ce..033cb17fc6e 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -1,6 +1,9 @@ use super::Transaction; use crate::{ - parameters::{ConsensusBranchId, NetworkUpgrade}, + parameters::{ + ConsensusBranchId, NetworkUpgrade, ORCHARD_VERSION_GROUP_ID, OVERWINTER_VERSION_GROUP_ID, + SAPLING_VERSION_GROUP_ID, + }, serialization::{WriteZcashExt, ZcashSerialize}, transparent, }; @@ -12,10 +15,6 @@ use std::io; static ZIP143_EXPLANATION: &str = "Invalid transaction version: after Overwinter activation transaction versions 1 and 2 are rejected"; static ZIP243_EXPLANATION: &str = "Invalid transaction version: after Sapling activation transaction versions 1, 2, and 3 are rejected"; -const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; -const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; -const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; - const ZCASH_SIGHASH_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZcashSigHash"; const ZCASH_PREVOUTS_HASH_PERSONALIZATION: &[u8; 16] = b"ZcashPrevoutHash"; const ZCASH_SEQUENCE_HASH_PERSONALIZATION: &[u8; 16] = b"ZcashSequencHash"; From ba1890f2be06271628a8099895289bd7fa2a318a Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 27 Feb 2021 14:58:56 -0300 Subject: [PATCH 04/29] fix version in serialize --- zebra-chain/src/transaction/serialize.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index d6ac55b6e23..440b03260fd 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -187,8 +187,8 @@ impl ZcashSerialize for Transaction { expiry_height, rest, } => { - // Write version 4 and set the fOverwintered bit. - writer.write_u32::(4 | (1 << 31))?; + // Write version 5 and set the fOverwintered bit. + writer.write_u32::(5 | (1 << 31))?; writer.write_u32::(ORCHARD_VERSION_GROUP_ID)?; tx_in.zcash_serialize(&mut writer)?; tx_out.zcash_serialize(&mut writer)?; From 5745db89735a528b0e4cc2e21f2256780da7f81a Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 27 Feb 2021 20:29:30 -0300 Subject: [PATCH 05/29] replace an unreachable --- zebra-chain/src/transaction/sighash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index 033cb17fc6e..400c50a02a2 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -471,7 +471,7 @@ impl<'a> SigHasher<'a> { let value_balance = match self.trans { V4 { value_balance, .. } => value_balance, - V5 { .. } => unreachable!("NOT IMPLEMENTED YET!"), + V5 { .. } => unimplemented!("v5 transaction"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; From 7356b861e2616fe5aa24d1ae93283813bdcf19b8 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 1 Mar 2021 11:35:18 +1000 Subject: [PATCH 06/29] Update comment for V5 transactions --- zebra-chain/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 23bd30258b8..1a64a78cf37 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -42,7 +42,7 @@ use crate::{ /// internally by different enum variants. Because we checkpoint on Sapling /// activation, we do not validate any pre-Sapling transaction types. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -// XXX consider boxing the Optional fields of V4 txs +// XXX consider boxing the Optional fields of V4 and V5 txs #[allow(clippy::large_enum_variant)] pub enum Transaction { /// A fully transparent transaction (`version = 1`). From 32fdcff0d65d6c4b7e69581525f1cc839dc02166 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 1 Mar 2021 12:30:05 +1000 Subject: [PATCH 07/29] Add V5 transactions to non_finalized_state Currently these are all `unimplemented!(...)` --- zebra-state/src/service/non_finalized_state/chain.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 82946e6ceef..7aa5d1268ae 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -165,14 +165,16 @@ impl UpdateWith for Chain { .zip(transaction_hashes.iter().cloned()) .enumerate() { + use transaction::Transaction::*; let (inputs, shielded_data, joinsplit_data) = match transaction.deref() { - transaction::Transaction::V4 { + V4 { inputs, shielded_data, joinsplit_data, .. } => (inputs, shielded_data, joinsplit_data), - _ => unreachable!( + V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), + V1 | V2 | V3 => unreachable!( "older transaction versions only exist in finalized blocks pre sapling", ), }; @@ -223,14 +225,16 @@ impl UpdateWith for Chain { for (transaction, transaction_hash) in block.transactions.iter().zip(transaction_hashes.iter()) { + use transaction::Transaction::*; let (inputs, shielded_data, joinsplit_data) = match transaction.deref() { - transaction::Transaction::V4 { + V4 { inputs, shielded_data, joinsplit_data, .. } => (inputs, shielded_data, joinsplit_data), - _ => unreachable!( + V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), + V1 | V2 | V3 => unreachable!( "older transaction versions only exist in finalized blocks pre sapling", ), }; From 092543be9d3fec946f8015b57009190e6c6eb9c8 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 1 Mar 2021 13:08:20 +1000 Subject: [PATCH 08/29] Fix struct matches --- zebra-state/src/service/non_finalized_state/chain.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 7aa5d1268ae..1a302e6f394 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -174,7 +174,7 @@ impl UpdateWith for Chain { .. } => (inputs, shielded_data, joinsplit_data), V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), - V1 | V2 | V3 => unreachable!( + V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks pre sapling", ), }; @@ -234,7 +234,7 @@ impl UpdateWith for Chain { .. } => (inputs, shielded_data, joinsplit_data), V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), - V1 | V2 | V3 => unreachable!( + V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks pre sapling", ), }; From c19c8dce9d83ab2b8c22353925987b383b62af11 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 1 Mar 2021 13:40:15 +1000 Subject: [PATCH 09/29] Apply trivial panic message changes --- zebra-chain/src/transaction/sighash.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index 400c50a02a2..e9122a81974 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -245,7 +245,7 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { joinsplit_data, .. } => joinsplit_data.is_some(), Transaction::V4 { joinsplit_data, .. } => joinsplit_data.is_some(), - Transaction::V5 { .. } => unimplemented!("v5 transaction"), + Transaction::V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), }; if !has_joinsplits { @@ -409,7 +409,7 @@ impl<'a> SigHasher<'a> { shielded_data: None, .. } => return writer.write_all(&[0; 32]), - V5 { .. } => unimplemented!("v5 transaction"), + V5 { .. } => unimplemented!("v5 transaction hash as specified in ZIP-225 and ZIP-244"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; @@ -446,7 +446,7 @@ impl<'a> SigHasher<'a> { shielded_data: None, .. } => return writer.write_all(&[0; 32]), - V5 { .. } => unimplemented!("v5 transaction"), + V5 { .. } => unimplemented!("v5 transaction hash as specified in ZIP-225 and ZIP-244"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; @@ -471,7 +471,7 @@ impl<'a> SigHasher<'a> { let value_balance = match self.trans { V4 { value_balance, .. } => value_balance, - V5 { .. } => unimplemented!("v5 transaction"), + V5 { .. } => unimplemented!("v5 transaction hash as specified in ZIP-225 and ZIP-244"), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(ZIP243_EXPLANATION), }; From 3817ecdc5a5bb104afc475fd39cc57e3d775f0cd Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 1 Mar 2021 13:44:49 +1000 Subject: [PATCH 10/29] rustfmt --- zebra-chain/src/transaction/sighash.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index e9122a81974..7db2238eeb6 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -245,7 +245,9 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { joinsplit_data, .. } => joinsplit_data.is_some(), Transaction::V4 { joinsplit_data, .. } => joinsplit_data.is_some(), - Transaction::V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), + Transaction::V5 { .. } => { + unimplemented!("v5 transaction format as specified in ZIP-225") + } }; if !has_joinsplits { From 7bf53563aa2800d59aa6239b3afcc7bcaa178fc3 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 10:07:35 -0300 Subject: [PATCH 11/29] use TX_V5_VERSION_GROUP_ID --- zebra-chain/src/parameters/transaction.rs | 13 +++++++++---- zebra-chain/src/transaction/serialize.rs | 4 ++-- zebra-chain/src/transaction/sighash.rs | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index a0857dd10a9..01d5175b940 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -1,8 +1,13 @@ //! Transaction consensus and utility parameters. -///The Overwinter version group ID. +///The version group ID for Overwinter transactions. pub const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; -///The Sapling version group ID. + +///The version group ID for Sapling transactions. pub const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; -///The Orchard version group ID. -pub const ORCHARD_VERSION_GROUP_ID: u32 = 0x6A7_270A; + +/// The version group ID for version 5 transactions. +/// +/// Orchard transactions must use transaction version 5 and this version +/// group ID. Sapling transactions can use v4 or v5 transactions. +pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 440b03260fd..31adcea2346 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -6,7 +6,7 @@ use std::{io, sync::Arc}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crate::{ - parameters::{ORCHARD_VERSION_GROUP_ID, OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID}, + parameters::{OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID}, primitives::ZkSnarkProof, serialization::{ ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashDeserializeInto, @@ -189,7 +189,7 @@ impl ZcashSerialize for Transaction { } => { // Write version 5 and set the fOverwintered bit. writer.write_u32::(5 | (1 << 31))?; - writer.write_u32::(ORCHARD_VERSION_GROUP_ID)?; + writer.write_u32::(TX_V5_VERSION_GROUP_ID)?; tx_in.zcash_serialize(&mut writer)?; tx_out.zcash_serialize(&mut writer)?; lock_time.zcash_serialize(&mut writer)?; diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index 7db2238eeb6..b63d2688681 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -1,8 +1,8 @@ use super::Transaction; use crate::{ parameters::{ - ConsensusBranchId, NetworkUpgrade, ORCHARD_VERSION_GROUP_ID, OVERWINTER_VERSION_GROUP_ID, - SAPLING_VERSION_GROUP_ID, + ConsensusBranchId, NetworkUpgrade, OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, + TX_V5_VERSION_GROUP_ID, }, serialization::{WriteZcashExt, ZcashSerialize}, transparent, @@ -138,7 +138,7 @@ impl<'a> SigHasher<'a> { Transaction::V1 { .. } | Transaction::V2 { .. } => unreachable!(ZIP143_EXPLANATION), Transaction::V3 { .. } => OVERWINTER_VERSION_GROUP_ID, Transaction::V4 { .. } => SAPLING_VERSION_GROUP_ID, - Transaction::V5 { .. } => ORCHARD_VERSION_GROUP_ID, + Transaction::V5 { .. } => TX_V5_VERSION_GROUP_ID, }) } From 2d428ff9078355fd95a424a2e475a3466cbdde4b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 10:10:44 -0300 Subject: [PATCH 12/29] fix comment, spacing --- zebra-chain/src/parameters/transaction.rs | 4 ++-- zebra-chain/src/transaction.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index 01d5175b940..bab59e794db 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -1,9 +1,9 @@ //! Transaction consensus and utility parameters. -///The version group ID for Overwinter transactions. +/// The version group ID for Overwinter transactions. pub const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C4_8270; -///The version group ID for Sapling transactions. +/// The version group ID for Sapling transactions. pub const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; /// The version group ID for version 5 transactions. diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 1a64a78cf37..ab75b564d27 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -99,7 +99,7 @@ pub enum Transaction { /// The shielded data for this transaction, if any. shielded_data: Option, }, - /// An Orchard transaction (`version = 5`). + /// A `version = 5` transaction, which supports `Sapling` and `Orchard`. V5 { /// The transparent inputs to the transaction. tx_in: Vec, From 37eadb7775a8bb5925bf49d9bb090c8c9a81cb1e Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 12:37:53 -0300 Subject: [PATCH 13/29] add zcash_deserialize for V5 --- zebra-chain/src/transaction/serialize.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 31adcea2346..900c0bce523 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -300,6 +300,23 @@ impl ZcashDeserialize for Transaction { joinsplit_data, }) } + (5, false) => { + let id = reader.read_u32::()?; + if id != TX_V5_VERSION_GROUP_ID { + return Err(SerializationError::Parse("expected TX_V5_VERSION_GROUP_ID")); + } + Ok(Transaction::V5 { + tx_in: Vec::zcash_deserialize(&mut reader)?, + tx_out: Vec::zcash_deserialize(&mut reader)?, + lock_time: LockTime::zcash_deserialize(&mut reader)?, + expiry_height: block::Height(reader.read_u32::()?), + rest: { + let mut buffer = Vec::new(); + reader.read_to_end(&mut buffer)?; + buffer + }, + }) + } (_, _) => Err(SerializationError::Parse("bad tx header")), } } From 8c333820b31b617d8e20c1a4ed55232be4267b36 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 14:05:34 -0300 Subject: [PATCH 14/29] change blocked code in arbitrary --- zebra-chain/src/transaction/arbitrary.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index cea6caf416c..c0297937009 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -256,8 +256,13 @@ impl Arbitrary for Transaction { NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) } - // Blocked by #1823 - //NetworkUpgrade::NU5 => Self::v5_strategy(ledger_state), + // Blocked by #1823 and #1824, see #1826 + /* + NetworkUpgrade::NU5 => prop_oneof!( + Self::v4_strategy(ledger_state), + Self::v5_strategy(ledger_state) + ), + */ } } From 21fd59b0294555bfa0ca4ba3002a99c66ad9ee16 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 14:35:35 -0300 Subject: [PATCH 15/29] make all tx versions explicit in sprout and sapling nullifier functions --- zebra-chain/src/transaction.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ab75b564d27..6fd9aed9cbd 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -194,7 +194,8 @@ impl Transaction { .flat_map(|joinsplit| joinsplit.nullifiers.iter()), ), // No JoinSplits - _ => Box::new(std::iter::empty()), + Transaction::V1 { .. } | Transaction::V5 { .. } => Box::new(std::iter::empty()), + _ => Box::new(std::iter::empty()) } } @@ -208,8 +209,10 @@ impl Transaction { shielded_data: Some(shielded_data), .. } => Box::new(shielded_data.nullifiers()), + Transaction::V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), // No JoinSplits - _ => Box::new(std::iter::empty()), + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => Box::new(std::iter::empty()), + _ => Box::new(std::iter::empty()) } } From e8510471bc6f6138502b5b1ced661a40e51201b4 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 14:38:57 -0300 Subject: [PATCH 16/29] rustfmt --- zebra-chain/src/transaction/arbitrary.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index c0297937009..1ef7a01d24d 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -255,14 +255,13 @@ impl Arbitrary for Transaction { NetworkUpgrade::Sapling => Self::v3_strategy(ledger_state), NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) - } - // Blocked by #1823 and #1824, see #1826 - /* - NetworkUpgrade::NU5 => prop_oneof!( - Self::v4_strategy(ledger_state), - Self::v5_strategy(ledger_state) - ), - */ + } // Blocked by #1823 and #1824, see #1826 + /* + NetworkUpgrade::NU5 => prop_oneof!( + Self::v4_strategy(ledger_state), + Self::v5_strategy(ledger_state) + ), + */ } } From 41d0c695c3c977c46d6e8037d440e80f54894250 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 14:57:46 -0300 Subject: [PATCH 17/29] rustfmt --- zebra-chain/src/transaction.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 6fd9aed9cbd..732ba332793 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -195,7 +195,7 @@ impl Transaction { ), // No JoinSplits Transaction::V1 { .. } | Transaction::V5 { .. } => Box::new(std::iter::empty()), - _ => Box::new(std::iter::empty()) + _ => Box::new(std::iter::empty()), } } @@ -209,10 +209,14 @@ impl Transaction { shielded_data: Some(shielded_data), .. } => Box::new(shielded_data.nullifiers()), - Transaction::V5 { .. } => unimplemented!("v5 transaction format as specified in ZIP-225"), + Transaction::V5 { .. } => { + unimplemented!("v5 transaction format as specified in ZIP-225") + } // No JoinSplits - Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => Box::new(std::iter::empty()), - _ => Box::new(std::iter::empty()) + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + Box::new(std::iter::empty()) + } + _ => Box::new(std::iter::empty()), } } From 68346ea8c95804094e751f5219ed9d905ca7cdd9 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 15:51:34 -0300 Subject: [PATCH 18/29] replace some unreacheables with unimplemented --- zebra-consensus/src/transaction.rs | 3 +-- zebra-consensus/src/transaction/check.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 33244f9ba44..ee0ab877b2d 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -136,8 +136,7 @@ where | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V5 { .. } => { - tracing::debug!(?tx, "got transaction with wrong version"); - Err(TransactionError::WrongVersion) + unimplemented!("v5 transaction validation as specified in ZIP-216, ZIP-224, ZIP-225, and ZIP-244") } Transaction::V4 { inputs, diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index 710ede6bf3d..2b10d314a47 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -72,7 +72,7 @@ pub fn has_inputs_and_outputs(tx: &Transaction) -> Result<(), TransactionError> | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V5 { .. } => { - unreachable!("tx version is checked first") + unimplemented!("v5 transaction format as specified in ZIP-225") } } } @@ -118,7 +118,7 @@ pub fn coinbase_tx_no_joinsplit_or_spend(tx: &Transaction) -> Result<(), Transac | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V5 { .. } => { - unreachable!("tx version is checked first") + unimplemented!("v5 coinbase validation as specified in ZIP-225 and the draft spec") } } } else { From ef8f0f2954140774a6b487ffac241bc68872d4b1 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 1 Mar 2021 21:24:30 -0300 Subject: [PATCH 19/29] replace tx_in and tx_out with inputs and outputs --- zebra-chain/src/transaction.rs | 8 ++++---- zebra-chain/src/transaction/arbitrary.rs | 6 +++--- zebra-chain/src/transaction/serialize.rs | 12 ++++++------ zebra-state/src/tests.rs | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 732ba332793..df410222cd6 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -102,9 +102,9 @@ pub enum Transaction { /// A `version = 5` transaction, which supports `Sapling` and `Orchard`. V5 { /// The transparent inputs to the transaction. - tx_in: Vec, + inputs: Vec, /// The transparent outputs from the transaction. - tx_out: Vec, + outputs: Vec, /// The earliest time or block height that this transaction can be added to the /// chain. lock_time: LockTime, @@ -129,7 +129,7 @@ impl Transaction { Transaction::V2 { ref inputs, .. } => inputs, Transaction::V3 { ref inputs, .. } => inputs, Transaction::V4 { ref inputs, .. } => inputs, - Transaction::V5 { ref tx_in, .. } => tx_in, + Transaction::V5 { ref inputs, .. } => inputs, } } @@ -140,7 +140,7 @@ impl Transaction { Transaction::V2 { ref outputs, .. } => outputs, Transaction::V3 { ref outputs, .. } => outputs, Transaction::V4 { ref outputs, .. } => outputs, - Transaction::V5 { ref tx_out, .. } => tx_out, + Transaction::V5 { ref outputs, .. } => outputs, } } diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 1ef7a01d24d..a79fda2f859 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -114,9 +114,9 @@ impl Transaction { any::>(), ) .prop_map( - |(tx_in, tx_out, lock_time, expiry_height, rest)| Transaction::V5 { - tx_in, - tx_out, + |(inputs, outputs, lock_time, expiry_height, rest)| Transaction::V5 { + inputs, + outputs, lock_time, expiry_height, rest, diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 900c0bce523..315c2d07095 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -181,8 +181,8 @@ impl ZcashSerialize for Transaction { } } Transaction::V5 { - tx_in, - tx_out, + inputs, + outputs, lock_time, expiry_height, rest, @@ -190,8 +190,8 @@ impl ZcashSerialize for Transaction { // Write version 5 and set the fOverwintered bit. writer.write_u32::(5 | (1 << 31))?; writer.write_u32::(TX_V5_VERSION_GROUP_ID)?; - tx_in.zcash_serialize(&mut writer)?; - tx_out.zcash_serialize(&mut writer)?; + inputs.zcash_serialize(&mut writer)?; + outputs.zcash_serialize(&mut writer)?; lock_time.zcash_serialize(&mut writer)?; writer.write_u32::(expiry_height.0)?; // write the rest @@ -306,8 +306,8 @@ impl ZcashDeserialize for Transaction { return Err(SerializationError::Parse("expected TX_V5_VERSION_GROUP_ID")); } Ok(Transaction::V5 { - tx_in: Vec::zcash_deserialize(&mut reader)?, - tx_out: Vec::zcash_deserialize(&mut reader)?, + inputs: Vec::zcash_deserialize(&mut reader)?, + outputs: Vec::zcash_deserialize(&mut reader)?, lock_time: LockTime::zcash_deserialize(&mut reader)?, expiry_height: block::Height(reader.read_u32::()?), rest: { diff --git a/zebra-state/src/tests.rs b/zebra-state/src/tests.rs index 457a0dfe200..247a80aa76d 100644 --- a/zebra-state/src/tests.rs +++ b/zebra-state/src/tests.rs @@ -53,7 +53,7 @@ impl FakeChainHelper for Arc { Transaction::V2 { inputs, .. } => &mut inputs[0], Transaction::V3 { inputs, .. } => &mut inputs[0], Transaction::V4 { inputs, .. } => &mut inputs[0], - Transaction::V5 { tx_in, .. } => &mut tx_in[0], + Transaction::V5 { inputs, .. } => &mut inputs[0], }; match input { From 02e1ff5a067d4f1dcf063aafb03b5c20372ec05c Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 10:10:41 -0300 Subject: [PATCH 20/29] match exhaustively in sprout and sapling nullifier functions --- zebra-chain/src/transaction.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index df410222cd6..f8c076db453 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -194,8 +194,20 @@ impl Transaction { .flat_map(|joinsplit| joinsplit.nullifiers.iter()), ), // No JoinSplits - Transaction::V1 { .. } | Transaction::V5 { .. } => Box::new(std::iter::empty()), - _ => Box::new(std::iter::empty()), + Transaction::V1 { .. } + | Transaction::V2 { + joinsplit_data: None, + .. + } + | Transaction::V3 { + joinsplit_data: None, + .. + } + | Transaction::V4 { + joinsplit_data: None, + .. + } + | Transaction::V5 { .. } => Box::new(std::iter::empty()), } } @@ -213,10 +225,13 @@ impl Transaction { unimplemented!("v5 transaction format as specified in ZIP-225") } // No JoinSplits - Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { - Box::new(std::iter::empty()) - } - _ => Box::new(std::iter::empty()), + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { + shielded_data: None, + .. + } => Box::new(std::iter::empty()), } } From 5fb99635659dccc4adf1a6383dd0fbeb598d7433 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 10:23:47 -0300 Subject: [PATCH 21/29] follow V4 let binding pattern --- zebra-chain/src/transaction/serialize.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 315c2d07095..3beb04d0ed5 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -305,16 +305,19 @@ impl ZcashDeserialize for Transaction { if id != TX_V5_VERSION_GROUP_ID { return Err(SerializationError::Parse("expected TX_V5_VERSION_GROUP_ID")); } + let inputs = Vec::zcash_deserialize(&mut reader)?; + let outputs = Vec::zcash_deserialize(&mut reader)?; + let lock_time = LockTime::zcash_deserialize(&mut reader)?; + let expiry_height = block::Height(reader.read_u32::()?); + let mut rest = Vec::new(); + reader.read_to_end(&mut rest)?; + Ok(Transaction::V5 { - inputs: Vec::zcash_deserialize(&mut reader)?, - outputs: Vec::zcash_deserialize(&mut reader)?, - lock_time: LockTime::zcash_deserialize(&mut reader)?, - expiry_height: block::Height(reader.read_u32::()?), - rest: { - let mut buffer = Vec::new(); - reader.read_to_end(&mut buffer)?; - buffer - }, + inputs, + outputs, + lock_time, + expiry_height, + rest, }) } (_, _) => Err(SerializationError::Parse("bad tx header")), From 8302d8dcfc463dea8dd34ca52b9128142b2a4397 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 10:40:14 -0300 Subject: [PATCH 22/29] fix matches in zebra-consensus --- zebra-consensus/src/transaction.rs | 11 ++++++----- zebra-consensus/src/transaction/check.rs | 17 +++++++++-------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index ee0ab877b2d..a2716dff12e 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -132,11 +132,9 @@ where async move { tracing::trace!(?tx); match &*tx { - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V5 { .. } => { - unimplemented!("v5 transaction validation as specified in ZIP-216, ZIP-224, ZIP-225, and ZIP-244") + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + tracing::debug!(?tx, "got transaction with wrong version"); + Err(TransactionError::WrongVersion) } Transaction::V4 { inputs, @@ -260,6 +258,9 @@ where Ok(tx.hash()) } + Transaction::V5 { .. } => { + unimplemented!("v5 transaction validation as specified in ZIP-216, ZIP-224, ZIP-225, and ZIP-244") + } } } .instrument(span) diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index 2b10d314a47..621ac71dd9a 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -68,10 +68,10 @@ pub fn has_inputs_and_outputs(tx: &Transaction) -> Result<(), TransactionError> Ok(()) } } - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V5 { .. } => { + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + unreachable!("tx version is checked first") + } + Transaction::V5 { .. } => { unimplemented!("v5 transaction format as specified in ZIP-225") } } @@ -114,10 +114,11 @@ pub fn coinbase_tx_no_joinsplit_or_spend(tx: &Transaction) -> Result<(), Transac Transaction::V4 { .. } => Ok(()), - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V5 { .. } => { + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => { + unreachable!("tx version is checked first") + } + + Transaction::V5 { .. } => { unimplemented!("v5 coinbase validation as specified in ZIP-225 and the draft spec") } } From d5f25197421b08f515effe58be7da914173b88da Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 19:39:12 -0300 Subject: [PATCH 23/29] change transaction fields order --- zebra-chain/src/transaction.rs | 9 ++++----- zebra-chain/src/transaction/serialize.rs | 16 ++++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index f8c076db453..ea6c271524f 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -101,16 +101,15 @@ pub enum Transaction { }, /// A `version = 5` transaction, which supports `Sapling` and `Orchard`. V5 { - /// The transparent inputs to the transaction. - inputs: Vec, - /// The transparent outputs from the transaction. - outputs: Vec, /// The earliest time or block height that this transaction can be added to the /// chain. lock_time: LockTime, /// The latest block height that this transaction can be added to the chain. expiry_height: block::Height, - + /// The transparent inputs to the transaction. + inputs: Vec, + /// The transparent outputs from the transaction. + outputs: Vec, /// The rest of the transaction as bytes rest: Vec, }, diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 3beb04d0ed5..742da3ba2c6 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -181,19 +181,19 @@ impl ZcashSerialize for Transaction { } } Transaction::V5 { - inputs, - outputs, lock_time, expiry_height, + inputs, + outputs, rest, } => { // Write version 5 and set the fOverwintered bit. writer.write_u32::(5 | (1 << 31))?; writer.write_u32::(TX_V5_VERSION_GROUP_ID)?; - inputs.zcash_serialize(&mut writer)?; - outputs.zcash_serialize(&mut writer)?; lock_time.zcash_serialize(&mut writer)?; writer.write_u32::(expiry_height.0)?; + inputs.zcash_serialize(&mut writer)?; + outputs.zcash_serialize(&mut writer)?; // write the rest writer.write_all(rest)?; } @@ -305,18 +305,18 @@ impl ZcashDeserialize for Transaction { if id != TX_V5_VERSION_GROUP_ID { return Err(SerializationError::Parse("expected TX_V5_VERSION_GROUP_ID")); } - let inputs = Vec::zcash_deserialize(&mut reader)?; - let outputs = Vec::zcash_deserialize(&mut reader)?; let lock_time = LockTime::zcash_deserialize(&mut reader)?; let expiry_height = block::Height(reader.read_u32::()?); + let inputs = Vec::zcash_deserialize(&mut reader)?; + let outputs = Vec::zcash_deserialize(&mut reader)?; let mut rest = Vec::new(); reader.read_to_end(&mut rest)?; Ok(Transaction::V5 { - inputs, - outputs, lock_time, expiry_height, + inputs, + outputs, rest, }) } From 510b571eb1d7202283a7634f344518cf70938a90 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 20:03:45 -0300 Subject: [PATCH 24/29] fix unblocked NU5 strategy --- zebra-chain/src/transaction/arbitrary.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index a79fda2f859..33ce6e090f9 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -255,13 +255,12 @@ impl Arbitrary for Transaction { NetworkUpgrade::Sapling => Self::v3_strategy(ledger_state), NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) - } // Blocked by #1823 and #1824, see #1826 - /* - NetworkUpgrade::NU5 => prop_oneof!( - Self::v4_strategy(ledger_state), - Self::v5_strategy(ledger_state) - ), - */ + } + NetworkUpgrade::NU5 => prop_oneof![ + Self::v4_strategy(ledger_state), + Self::v5_strategy(ledger_state) + ] + .boxed(), } } From 21b85a33f715408c04f8c4b314516d10fa1e7b6f Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 2 Mar 2021 21:40:47 -0300 Subject: [PATCH 25/29] change fields order in arbitrary --- zebra-chain/src/transaction/arbitrary.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 33ce6e090f9..80950803fbe 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -107,18 +107,18 @@ impl Transaction { /// Generate a proptest strategy for V5 Transactions pub fn v5_strategy(ledger_state: LedgerState) -> BoxedStrategy { ( - transparent::Input::vec_strategy(ledger_state, 10), - vec(any::(), 0..10), any::(), any::(), + transparent::Input::vec_strategy(ledger_state, 10), + vec(any::(), 0..10), any::>(), ) .prop_map( - |(inputs, outputs, lock_time, expiry_height, rest)| Transaction::V5 { - inputs, - outputs, + |(lock_time, expiry_height, inputs, outputs, rest)| Transaction::V5 { lock_time, expiry_height, + inputs, + outputs, rest, }, ) From 9de491fdf7e48d70803b5aaf2595a49b2961af91 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 3 Mar 2021 16:41:50 +1000 Subject: [PATCH 26/29] We're still deciding if v5 transactions support Sprout --- zebra-chain/src/transaction.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ea6c271524f..f9e6b304390 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -100,6 +100,8 @@ pub enum Transaction { shielded_data: Option, }, /// A `version = 5` transaction, which supports `Sapling` and `Orchard`. + // TODO: does this transaction type support `Sprout`? + // Check for ZIP-225 updates after the decision on 2021-03-05. V5 { /// The earliest time or block height that this transaction can be added to the /// chain. @@ -192,6 +194,12 @@ impl Transaction { .joinsplits() .flat_map(|joinsplit| joinsplit.nullifiers.iter()), ), + // Maybe JoinSplits, maybe not, we're still deciding + Transaction::V5 { .. } => { + unimplemented!( + "v5 transaction format as specified in ZIP-225 after decision on 2021-03-05" + ) + } // No JoinSplits Transaction::V1 { .. } | Transaction::V2 { @@ -205,8 +213,7 @@ impl Transaction { | Transaction::V4 { joinsplit_data: None, .. - } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + } => Box::new(std::iter::empty()), } } From 433626c426f9e5a4253f2d1c4682f5119a15f2d7 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 3 Mar 2021 16:42:35 +1000 Subject: [PATCH 27/29] Minor log and comment tweaks --- zebra-chain/src/transaction/sighash.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index b63d2688681..b8cc9ea345b 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -246,7 +246,7 @@ impl<'a> SigHasher<'a> { Transaction::V3 { joinsplit_data, .. } => joinsplit_data.is_some(), Transaction::V4 { joinsplit_data, .. } => joinsplit_data.is_some(), Transaction::V5 { .. } => { - unimplemented!("v5 transaction format as specified in ZIP-225") + unimplemented!("v5 transaction hash as specified in ZIP-225 and ZIP-244") } }; @@ -261,7 +261,7 @@ impl<'a> SigHasher<'a> { // This code, and the check above for has_joinsplits cannot be combined // into a single branch because the `joinsplit_data` type of each - // tranaction kind has a different type. + // transaction kind has a different type. // // For v3 joinsplit_data is a JoinSplitData // For v4 joinsplit_data is a JoinSplitData @@ -269,6 +269,8 @@ impl<'a> SigHasher<'a> { // The type parameter on these types prevents them from being unified, // which forces us to duplicate the logic in each branch even though the // code within each branch is identical. + // + // TODO: use a generic function to remove the duplicate code match self.trans { Transaction::V3 { joinsplit_data: Some(jsd), From 48fb77e69e35b17c54dc92f14531f358f44a8db9 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 3 Mar 2021 16:42:51 +1000 Subject: [PATCH 28/29] Add a missing V5 transaction match case --- zebra-chain/src/transaction/sighash.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index b8cc9ea345b..2b7544b5478 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -290,7 +290,20 @@ impl<'a> SigHasher<'a> { } (&mut hash).write_all(&<[u8; 32]>::from(jsd.pub_key)[..])?; } - _ => unreachable!("already checked transaction kind above"), + Transaction::V5 { .. } => { + unimplemented!("v5 transaction hash as specified in ZIP-225 and ZIP-244") + } + + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { + joinsplit_data: None, + .. + } + | Transaction::V4 { + joinsplit_data: None, + .. + } => unreachable!("already checked transaction kind above"), }; writer.write_all(hash.finalize().as_ref()) From 04c7def7ee6f6d4e18876b390a53415fa338bd05 Mon Sep 17 00:00:00 2001 From: teor Date: Thu, 4 Mar 2021 07:54:25 +1000 Subject: [PATCH 29/29] Fix decision date --- zebra-chain/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index f9e6b304390..4f2c1285bab 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -197,7 +197,7 @@ impl Transaction { // Maybe JoinSplits, maybe not, we're still deciding Transaction::V5 { .. } => { unimplemented!( - "v5 transaction format as specified in ZIP-225 after decision on 2021-03-05" + "v5 transaction format as specified in ZIP-225 after decision on 2021-03-12" ) } // No JoinSplits