Compare commits
No commits in common. "strip-transparent-txs" and "main" have entirely different histories.
strip-tran
...
main
|
|
@ -161,7 +161,8 @@ impl TryFrom<&Transaction> for zp_tx::Transaction {
|
||||||
Transaction::V5 {
|
Transaction::V5 {
|
||||||
network_upgrade, ..
|
network_upgrade, ..
|
||||||
} => network_upgrade,
|
} => network_upgrade,
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. } => panic!("Zebra only uses librustzcash for V5 transactions"),
|
| Transaction::V4 { .. } => panic!("Zebra only uses librustzcash for V5 transactions"),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,16 @@ use crate::{
|
||||||
derive(Serialize)
|
derive(Serialize)
|
||||||
)]
|
)]
|
||||||
pub enum Transaction {
|
pub enum Transaction {
|
||||||
|
/// A fully transparent transaction (`version = 1`).
|
||||||
|
V1 {
|
||||||
|
/// The transparent inputs to the transaction.
|
||||||
|
inputs: Vec<transparent::Input>,
|
||||||
|
/// The transparent outputs from the transaction.
|
||||||
|
outputs: Vec<transparent::Output>,
|
||||||
|
/// The earliest time or block height that this transaction can be added to the
|
||||||
|
/// chain.
|
||||||
|
lock_time: LockTime,
|
||||||
|
},
|
||||||
/// A Sprout transaction (`version = 2`).
|
/// A Sprout transaction (`version = 2`).
|
||||||
V2 {
|
V2 {
|
||||||
/// The transparent inputs to the transaction.
|
/// The transparent inputs to the transaction.
|
||||||
|
|
@ -222,7 +232,8 @@ impl Transaction {
|
||||||
/// [ZIP-244]: https://zips.z.cash/zip-0244.
|
/// [ZIP-244]: https://zips.z.cash/zip-0244.
|
||||||
pub fn auth_digest(&self) -> Option<AuthDigest> {
|
pub fn auth_digest(&self) -> Option<AuthDigest> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. } => None,
|
| Transaction::V4 { .. } => None,
|
||||||
Transaction::V5 { .. } => Some(AuthDigest::from(self)),
|
Transaction::V5 { .. } => Some(AuthDigest::from(self)),
|
||||||
|
|
@ -297,7 +308,7 @@ impl Transaction {
|
||||||
/// Return if the `fOverwintered` flag of this transaction is set.
|
/// Return if the `fOverwintered` flag of this transaction is set.
|
||||||
pub fn is_overwintered(&self) -> bool {
|
pub fn is_overwintered(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. } => false,
|
Transaction::V1 { .. } | Transaction::V2 { .. } => false,
|
||||||
Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true,
|
Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -305,6 +316,7 @@ impl Transaction {
|
||||||
/// Return the version of this transaction.
|
/// Return the version of this transaction.
|
||||||
pub fn version(&self) -> u32 {
|
pub fn version(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 { .. } => 1,
|
||||||
Transaction::V2 { .. } => 2,
|
Transaction::V2 { .. } => 2,
|
||||||
Transaction::V3 { .. } => 3,
|
Transaction::V3 { .. } => 3,
|
||||||
Transaction::V4 { .. } => 4,
|
Transaction::V4 { .. } => 4,
|
||||||
|
|
@ -315,7 +327,8 @@ impl Transaction {
|
||||||
/// Get this transaction's lock time.
|
/// Get this transaction's lock time.
|
||||||
pub fn lock_time(&self) -> Option<LockTime> {
|
pub fn lock_time(&self) -> Option<LockTime> {
|
||||||
let lock_time = match self {
|
let lock_time = match self {
|
||||||
Transaction::V2 { lock_time, .. }
|
Transaction::V1 { lock_time, .. }
|
||||||
|
| Transaction::V2 { lock_time, .. }
|
||||||
| Transaction::V3 { lock_time, .. }
|
| Transaction::V3 { lock_time, .. }
|
||||||
| Transaction::V4 { lock_time, .. }
|
| Transaction::V4 { lock_time, .. }
|
||||||
| Transaction::V5 { lock_time, .. } => *lock_time,
|
| Transaction::V5 { lock_time, .. } => *lock_time,
|
||||||
|
|
@ -372,7 +385,7 @@ impl Transaction {
|
||||||
/// Get this transaction's expiry height, if any.
|
/// Get this transaction's expiry height, if any.
|
||||||
pub fn expiry_height(&self) -> Option<block::Height> {
|
pub fn expiry_height(&self) -> Option<block::Height> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. } => None,
|
Transaction::V1 { .. } | Transaction::V2 { .. } => None,
|
||||||
Transaction::V3 { expiry_height, .. }
|
Transaction::V3 { expiry_height, .. }
|
||||||
| Transaction::V4 { expiry_height, .. }
|
| Transaction::V4 { expiry_height, .. }
|
||||||
| Transaction::V5 { expiry_height, .. } => match expiry_height {
|
| Transaction::V5 { expiry_height, .. } => match expiry_height {
|
||||||
|
|
@ -393,8 +406,8 @@ impl Transaction {
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
pub fn expiry_height_mut(&mut self) -> &mut block::Height {
|
pub fn expiry_height_mut(&mut self) -> &mut block::Height {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. } => {
|
Transaction::V1 { .. } | Transaction::V2 { .. } => {
|
||||||
panic!("v2 transactions are not supported")
|
panic!("v1 and v2 transactions are not supported")
|
||||||
}
|
}
|
||||||
Transaction::V3 {
|
Transaction::V3 {
|
||||||
ref mut expiry_height,
|
ref mut expiry_height,
|
||||||
|
|
@ -417,7 +430,8 @@ impl Transaction {
|
||||||
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
/// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus
|
||||||
pub fn network_upgrade(&self) -> Option<NetworkUpgrade> {
|
pub fn network_upgrade(&self) -> Option<NetworkUpgrade> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. } => None,
|
| Transaction::V4 { .. } => None,
|
||||||
Transaction::V5 {
|
Transaction::V5 {
|
||||||
|
|
@ -431,6 +445,7 @@ impl Transaction {
|
||||||
/// Access the transparent inputs of this transaction, regardless of version.
|
/// Access the transparent inputs of this transaction, regardless of version.
|
||||||
pub fn inputs(&self) -> &[transparent::Input] {
|
pub fn inputs(&self) -> &[transparent::Input] {
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 { ref inputs, .. } => inputs,
|
||||||
Transaction::V2 { ref inputs, .. } => inputs,
|
Transaction::V2 { ref inputs, .. } => inputs,
|
||||||
Transaction::V3 { ref inputs, .. } => inputs,
|
Transaction::V3 { ref inputs, .. } => inputs,
|
||||||
Transaction::V4 { ref inputs, .. } => inputs,
|
Transaction::V4 { ref inputs, .. } => inputs,
|
||||||
|
|
@ -442,6 +457,7 @@ impl Transaction {
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
pub fn inputs_mut(&mut self) -> &mut Vec<transparent::Input> {
|
pub fn inputs_mut(&mut self) -> &mut Vec<transparent::Input> {
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 { ref mut inputs, .. } => inputs,
|
||||||
Transaction::V2 { ref mut inputs, .. } => inputs,
|
Transaction::V2 { ref mut inputs, .. } => inputs,
|
||||||
Transaction::V3 { ref mut inputs, .. } => inputs,
|
Transaction::V3 { ref mut inputs, .. } => inputs,
|
||||||
Transaction::V4 { ref mut inputs, .. } => inputs,
|
Transaction::V4 { ref mut inputs, .. } => inputs,
|
||||||
|
|
@ -459,6 +475,7 @@ impl Transaction {
|
||||||
/// Access the transparent outputs of this transaction, regardless of version.
|
/// Access the transparent outputs of this transaction, regardless of version.
|
||||||
pub fn outputs(&self) -> &[transparent::Output] {
|
pub fn outputs(&self) -> &[transparent::Output] {
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 { ref outputs, .. } => outputs,
|
||||||
Transaction::V2 { ref outputs, .. } => outputs,
|
Transaction::V2 { ref outputs, .. } => outputs,
|
||||||
Transaction::V3 { ref outputs, .. } => outputs,
|
Transaction::V3 { ref outputs, .. } => outputs,
|
||||||
Transaction::V4 { ref outputs, .. } => outputs,
|
Transaction::V4 { ref outputs, .. } => outputs,
|
||||||
|
|
@ -470,6 +487,9 @@ impl Transaction {
|
||||||
#[cfg(any(test, feature = "proptest-impl"))]
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
pub fn outputs_mut(&mut self) -> &mut Vec<transparent::Output> {
|
pub fn outputs_mut(&mut self) -> &mut Vec<transparent::Output> {
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 {
|
||||||
|
ref mut outputs, ..
|
||||||
|
} => outputs,
|
||||||
Transaction::V2 {
|
Transaction::V2 {
|
||||||
ref mut outputs, ..
|
ref mut outputs, ..
|
||||||
} => outputs,
|
} => outputs,
|
||||||
|
|
@ -522,7 +542,8 @@ impl Transaction {
|
||||||
} => Box::new(joinsplit_data.joinsplits()),
|
} => Box::new(joinsplit_data.joinsplits()),
|
||||||
|
|
||||||
// No JoinSplits / JoinSplits with BCTV14 proofs
|
// No JoinSplits / JoinSplits with BCTV14 proofs
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
|
|
@ -550,7 +571,8 @@ impl Transaction {
|
||||||
..
|
..
|
||||||
} => joinsplit_data.joinsplits().count(),
|
} => joinsplit_data.joinsplits().count(),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -588,7 +610,8 @@ impl Transaction {
|
||||||
..
|
..
|
||||||
} => Box::new(joinsplit_data.nullifiers()),
|
} => Box::new(joinsplit_data.nullifiers()),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -623,7 +646,8 @@ impl Transaction {
|
||||||
..
|
..
|
||||||
} => Some(joinsplit_data.pub_key),
|
} => Some(joinsplit_data.pub_key),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -643,7 +667,7 @@ impl Transaction {
|
||||||
pub fn has_sprout_joinsplit_data(&self) -> bool {
|
pub fn has_sprout_joinsplit_data(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V5 { .. } => false,
|
Transaction::V1 { .. } | Transaction::V5 { .. } => false,
|
||||||
|
|
||||||
// JoinSplits-on-BCTV14
|
// JoinSplits-on-BCTV14
|
||||||
Transaction::V2 { joinsplit_data, .. } | Transaction::V3 { joinsplit_data, .. } => {
|
Transaction::V2 { joinsplit_data, .. } | Transaction::V3 { joinsplit_data, .. } => {
|
||||||
|
|
@ -689,6 +713,7 @@ impl Transaction {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
| Transaction::V1 { .. }
|
||||||
| Transaction::V5 { .. } => Box::new(std::iter::empty()),
|
| Transaction::V5 { .. } => Box::new(std::iter::empty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -712,7 +737,8 @@ impl Transaction {
|
||||||
} => Box::new(sapling_shielded_data.anchors()),
|
} => Box::new(sapling_shielded_data.anchors()),
|
||||||
|
|
||||||
// No Spends
|
// No Spends
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -749,7 +775,8 @@ impl Transaction {
|
||||||
} => Box::new(sapling_shielded_data.spends_per_anchor()),
|
} => Box::new(sapling_shielded_data.spends_per_anchor()),
|
||||||
|
|
||||||
// No Spends
|
// No Spends
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -776,7 +803,8 @@ impl Transaction {
|
||||||
} => Box::new(sapling_shielded_data.outputs()),
|
} => Box::new(sapling_shielded_data.outputs()),
|
||||||
|
|
||||||
// No Outputs
|
// No Outputs
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -805,7 +833,8 @@ impl Transaction {
|
||||||
} => Box::new(sapling_shielded_data.nullifiers()),
|
} => Box::new(sapling_shielded_data.nullifiers()),
|
||||||
|
|
||||||
// No Spends
|
// No Spends
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -834,7 +863,8 @@ impl Transaction {
|
||||||
} => Box::new(sapling_shielded_data.note_commitments()),
|
} => Box::new(sapling_shielded_data.note_commitments()),
|
||||||
|
|
||||||
// No Spends
|
// No Spends
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -850,7 +880,7 @@ impl Transaction {
|
||||||
/// Return if the transaction has any Sapling shielded data.
|
/// Return if the transaction has any Sapling shielded data.
|
||||||
pub fn has_sapling_shielded_data(&self) -> bool {
|
pub fn has_sapling_shielded_data(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V2 { .. } | Transaction::V3 { .. } => false,
|
Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => false,
|
||||||
Transaction::V4 {
|
Transaction::V4 {
|
||||||
sapling_shielded_data,
|
sapling_shielded_data,
|
||||||
..
|
..
|
||||||
|
|
@ -875,7 +905,8 @@ impl Transaction {
|
||||||
} => orchard_shielded_data.as_ref(),
|
} => orchard_shielded_data.as_ref(),
|
||||||
|
|
||||||
// No Orchard shielded data
|
// No Orchard shielded data
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. } => None,
|
| Transaction::V4 { .. } => None,
|
||||||
}
|
}
|
||||||
|
|
@ -891,7 +922,8 @@ impl Transaction {
|
||||||
..
|
..
|
||||||
} => Some(orchard_shielded_data),
|
} => Some(orchard_shielded_data),
|
||||||
|
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. }
|
| Transaction::V4 { .. }
|
||||||
| Transaction::V5 {
|
| Transaction::V5 {
|
||||||
|
|
@ -1010,7 +1042,8 @@ impl Transaction {
|
||||||
.map(|joinsplit| &joinsplit.vpub_old),
|
.map(|joinsplit| &joinsplit.vpub_old),
|
||||||
),
|
),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -1058,7 +1091,8 @@ impl Transaction {
|
||||||
.map(|joinsplit| &mut joinsplit.vpub_old),
|
.map(|joinsplit| &mut joinsplit.vpub_old),
|
||||||
),
|
),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -1104,7 +1138,8 @@ impl Transaction {
|
||||||
.map(|joinsplit| &joinsplit.vpub_new),
|
.map(|joinsplit| &joinsplit.vpub_new),
|
||||||
),
|
),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -1152,7 +1187,8 @@ impl Transaction {
|
||||||
.map(|joinsplit| &mut joinsplit.vpub_new),
|
.map(|joinsplit| &mut joinsplit.vpub_new),
|
||||||
),
|
),
|
||||||
// No JoinSplits
|
// No JoinSplits
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -1192,7 +1228,8 @@ impl Transaction {
|
||||||
joinsplit_data: Some(joinsplit_data),
|
joinsplit_data: Some(joinsplit_data),
|
||||||
..
|
..
|
||||||
} => joinsplit_data.joinsplit_value_balances(),
|
} => joinsplit_data.joinsplit_value_balances(),
|
||||||
Transaction::V2 {
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 {
|
||||||
joinsplit_data: None,
|
joinsplit_data: None,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -1247,7 +1284,8 @@ impl Transaction {
|
||||||
..
|
..
|
||||||
} => sapling_shielded_data.value_balance,
|
} => sapling_shielded_data.value_balance,
|
||||||
|
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
@ -1277,7 +1315,8 @@ impl Transaction {
|
||||||
sapling_shielded_data: Some(sapling_shielded_data),
|
sapling_shielded_data: Some(sapling_shielded_data),
|
||||||
..
|
..
|
||||||
} => Some(&mut sapling_shielded_data.value_balance),
|
} => Some(&mut sapling_shielded_data.value_balance),
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 {
|
| Transaction::V4 {
|
||||||
sapling_shielded_data: None,
|
sapling_shielded_data: None,
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,21 @@ pub const MAX_ARBITRARY_ITEMS: usize = 4;
|
||||||
// TODO: if needed, fixup transaction outputs
|
// TODO: if needed, fixup transaction outputs
|
||||||
// (currently 0..=9 outputs, consensus rules require 1..)
|
// (currently 0..=9 outputs, consensus rules require 1..)
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
|
/// Generate a proptest strategy for V1 Transactions
|
||||||
|
pub fn v1_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
|
(
|
||||||
|
transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS),
|
||||||
|
vec(any::<transparent::Output>(), 0..MAX_ARBITRARY_ITEMS),
|
||||||
|
any::<LockTime>(),
|
||||||
|
)
|
||||||
|
.prop_map(|(inputs, outputs, lock_time)| Transaction::V1 {
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
lock_time,
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate a proptest strategy for V2 Transactions
|
/// Generate a proptest strategy for V2 Transactions
|
||||||
pub fn v2_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
pub fn v2_strategy(ledger_state: LedgerState) -> BoxedStrategy<Self> {
|
||||||
(
|
(
|
||||||
|
|
@ -745,6 +760,7 @@ impl Arbitrary for Transaction {
|
||||||
|
|
||||||
fn arbitrary_with(ledger_state: Self::Parameters) -> Self::Strategy {
|
fn arbitrary_with(ledger_state: Self::Parameters) -> Self::Strategy {
|
||||||
match ledger_state.transaction_version_override() {
|
match ledger_state.transaction_version_override() {
|
||||||
|
Some(1) => return Self::v1_strategy(ledger_state),
|
||||||
Some(2) => return Self::v2_strategy(ledger_state),
|
Some(2) => return Self::v2_strategy(ledger_state),
|
||||||
Some(3) => return Self::v3_strategy(ledger_state),
|
Some(3) => return Self::v3_strategy(ledger_state),
|
||||||
Some(4) => return Self::v4_strategy(ledger_state),
|
Some(4) => return Self::v4_strategy(ledger_state),
|
||||||
|
|
@ -754,8 +770,9 @@ impl Arbitrary for Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
match ledger_state.network_upgrade() {
|
match ledger_state.network_upgrade() {
|
||||||
//TODO - LOOK AT network_upgrade see where NetworkUpgrade::Genesis and
|
NetworkUpgrade::Genesis | NetworkUpgrade::BeforeOverwinter => {
|
||||||
// NetworkUpgrade::BeforeOverwinterare used
|
Self::v1_strategy(ledger_state)
|
||||||
|
}
|
||||||
NetworkUpgrade::Overwinter => Self::v2_strategy(ledger_state),
|
NetworkUpgrade::Overwinter => Self::v2_strategy(ledger_state),
|
||||||
NetworkUpgrade::Sapling => Self::v3_strategy(ledger_state),
|
NetworkUpgrade::Sapling => Self::v3_strategy(ledger_state),
|
||||||
NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => {
|
NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => {
|
||||||
|
|
@ -766,7 +783,6 @@ impl Arbitrary for Transaction {
|
||||||
Self::v5_strategy(ledger_state)
|
Self::v5_strategy(ledger_state)
|
||||||
]
|
]
|
||||||
.boxed(),
|
.boxed(),
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -843,6 +859,19 @@ pub fn transaction_to_fake_v5(
|
||||||
let block_nu = NetworkUpgrade::current(network, height);
|
let block_nu = NetworkUpgrade::current(network, height);
|
||||||
|
|
||||||
match trans {
|
match trans {
|
||||||
|
V1 {
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
lock_time,
|
||||||
|
} => V5 {
|
||||||
|
network_upgrade: block_nu,
|
||||||
|
inputs: inputs.to_vec(),
|
||||||
|
outputs: outputs.to_vec(),
|
||||||
|
lock_time: *lock_time,
|
||||||
|
expiry_height: height,
|
||||||
|
sapling_shielded_data: None,
|
||||||
|
orchard_shielded_data: None,
|
||||||
|
},
|
||||||
V2 {
|
V2 {
|
||||||
inputs,
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,20 @@ impl ZcashSerialize for Transaction {
|
||||||
writer.write_u32::<LittleEndian>(version)?;
|
writer.write_u32::<LittleEndian>(version)?;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
Transaction::V1 {
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
lock_time,
|
||||||
|
} => {
|
||||||
|
// Denoted as `tx_in_count` and `tx_in` in the spec.
|
||||||
|
inputs.zcash_serialize(&mut writer)?;
|
||||||
|
|
||||||
|
// Denoted as `tx_out_count` and `tx_out` in the spec.
|
||||||
|
outputs.zcash_serialize(&mut writer)?;
|
||||||
|
|
||||||
|
// Denoted as `lock_time` in the spec.
|
||||||
|
lock_time.zcash_serialize(&mut writer)?;
|
||||||
|
}
|
||||||
Transaction::V2 {
|
Transaction::V2 {
|
||||||
inputs,
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
|
|
@ -718,6 +732,14 @@ impl ZcashDeserialize for Transaction {
|
||||||
//
|
//
|
||||||
// https://zips.z.cash/protocol/protocol.pdf#txnconsensus
|
// https://zips.z.cash/protocol/protocol.pdf#txnconsensus
|
||||||
match (version, overwintered) {
|
match (version, overwintered) {
|
||||||
|
(1, false) => Ok(Transaction::V1 {
|
||||||
|
// Denoted as `tx_in_count` and `tx_in` in the spec.
|
||||||
|
inputs: Vec::zcash_deserialize(&mut limited_reader)?,
|
||||||
|
// Denoted as `tx_out_count` and `tx_out` in the spec.
|
||||||
|
outputs: Vec::zcash_deserialize(&mut limited_reader)?,
|
||||||
|
// Denoted as `lock_time` in the spec.
|
||||||
|
lock_time: LockTime::zcash_deserialize(&mut limited_reader)?,
|
||||||
|
}),
|
||||||
(2, false) => {
|
(2, false) => {
|
||||||
// Version 2 transactions use Sprout-on-BCTV14.
|
// Version 2 transactions use Sprout-on-BCTV14.
|
||||||
type OptV2Jsd = Option<JoinSplitData<Bctv14Proof>>;
|
type OptV2Jsd = Option<JoinSplitData<Bctv14Proof>>;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ impl<'a> TxIdBuilder<'a> {
|
||||||
/// Compute the Transaction ID for the previously specified transaction.
|
/// Compute the Transaction ID for the previously specified transaction.
|
||||||
pub(super) fn txid(self) -> Result<Hash, io::Error> {
|
pub(super) fn txid(self) -> Result<Hash, io::Error> {
|
||||||
match self.trans {
|
match self.trans {
|
||||||
Transaction::V2 { .. }
|
Transaction::V1 { .. }
|
||||||
|
| Transaction::V2 { .. }
|
||||||
| Transaction::V3 { .. }
|
| Transaction::V3 { .. }
|
||||||
| Transaction::V4 { .. } => self.txid_v1_to_v4(),
|
| Transaction::V4 { .. } => self.txid_v1_to_v4(),
|
||||||
Transaction::V5 { .. } => self.txid_v5(),
|
Transaction::V5 { .. } => self.txid_v5(),
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ impl From<Transaction> for UnminedTxId {
|
||||||
impl From<&Transaction> for UnminedTxId {
|
impl From<&Transaction> for UnminedTxId {
|
||||||
fn from(transaction: &Transaction) -> Self {
|
fn from(transaction: &Transaction) -> Self {
|
||||||
match transaction {
|
match transaction {
|
||||||
V2 { .. } | V3 { .. } | V4 { .. } => Legacy(transaction.into()),
|
V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } => Legacy(transaction.into()),
|
||||||
V5 { .. } => Witnessed(transaction.into()),
|
V5 { .. } => Witnessed(transaction.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ where
|
||||||
tracing::trace!(?tx_id, "got state UTXOs");
|
tracing::trace!(?tx_id, "got state UTXOs");
|
||||||
|
|
||||||
let mut async_checks = match tx.as_ref() {
|
let mut async_checks = match tx.as_ref() {
|
||||||
Transaction::V2 { .. } | Transaction::V3 { .. } => {
|
Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } => {
|
||||||
tracing::debug!(?tx, "got transaction with wrong version");
|
tracing::debug!(?tx, "got transaction with wrong version");
|
||||||
return Err(TransactionError::WrongVersion);
|
return Err(TransactionError::WrongVersion);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1510,7 +1510,7 @@ impl Chain {
|
||||||
sapling_shielded_data,
|
sapling_shielded_data,
|
||||||
orchard_shielded_data,
|
orchard_shielded_data,
|
||||||
),
|
),
|
||||||
V2 { .. } | V3 { .. } => unreachable!(
|
V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(
|
||||||
"older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint",
|
"older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint",
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
@ -1671,7 +1671,7 @@ impl UpdateWith<ContextuallyVerifiedBlock> for Chain {
|
||||||
sapling_shielded_data,
|
sapling_shielded_data,
|
||||||
orchard_shielded_data,
|
orchard_shielded_data,
|
||||||
),
|
),
|
||||||
V2 { .. } | V3 { .. } => unreachable!(
|
V1 { .. } | V2 { .. } | V3 { .. } => unreachable!(
|
||||||
"older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint",
|
"older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint",
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue