Create a consensus::BranchId enum for type safety

Includes all currently-known consensus branch IDs for the Zcash network.
This commit is contained in:
Jack Grigg 2019-11-25 15:41:14 +00:00
parent 141821d3c1
commit c24024b8e1
No known key found for this signature in database
GPG Key ID: 9E8255172BBF9898
5 changed files with 93 additions and 34 deletions

View File

@ -0,0 +1,48 @@
//! Consensus parameters.
/// A globally-unique identifier for a set of consensus rules within the Zcash chain.
///
/// Each branch ID in this enum corresponds to one of the epochs between a pair of Zcash
/// network upgrades. For example, `BranchId::Overwinter` corresponds to the blocks
/// starting at Overwinter activation, and ending the block before Sapling activation.
///
/// The main use of the branch ID is in signature generation: transactions commit to a
/// specific branch ID by including it as part of [`signature_hash`]. This ensures
/// two-way replay protection for transactions across network upgrades.
///
/// See [ZIP 200](https://zips.z.cash/zip-0200) for more details.
///
/// [`signature_hash`]: crate::transaction::signature_hash
#[derive(Clone, Copy, Debug)]
pub enum BranchId {
/// The consensus rules at the launch of Zcash.
Sprout,
/// The consensus rules deployed in the [Overwinter] network upgrade.
///
/// [Overwinter]: https://z.cash/upgrade/overwinter/
Overwinter,
/// The consensus rules deployed in the [Sapling] network upgrade.
///
/// [Sapling]: https://z.cash/upgrade/sapling/
Sapling,
/// The consensus rules deployed in the [Blossom] network upgrade.
///
/// [Blossom]: https://z.cash/upgrade/blossom/
Blossom,
/// The consensus rules deployed in the [Heartwood] network upgrade.
///
/// [Heartwood]: https://z.cash/upgrade/heartwood/
Heartwood,
}
impl From<BranchId> for u32 {
fn from(consensus_branch_id: BranchId) -> u32 {
match consensus_branch_id {
BranchId::Sprout => 0,
BranchId::Overwinter => 0x5ba8_1b19,
BranchId::Sapling => 0x76b8_09bb,
BranchId::Blossom => 0x2bb4_0e60,
BranchId::Heartwood => 0xf5b9_230b,
}
}
}

View File

@ -9,6 +9,7 @@
use lazy_static::lazy_static;
pub mod block;
pub mod consensus;
pub mod constants;
pub mod group_hash;
pub mod jubjub;

View File

@ -10,6 +10,7 @@ use pairing::bls12_381::{Bls12, Fr};
use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore};
use crate::{
consensus,
keys::OutgoingViewingKey,
legacy::TransparentAddress,
merkle_tree::{CommitmentTreeWitness, IncrementalWitness},
@ -211,7 +212,11 @@ impl TransparentInputs {
}
#[cfg(feature = "transparent-inputs")]
fn apply_signatures(&self, mtx: &mut TransactionData, consensus_branch_id: u32) {
fn apply_signatures(
&self,
mtx: &mut TransactionData,
consensus_branch_id: consensus::BranchId,
) {
let mut sighash = [0u8; 32];
for (i, info) in self.inputs.iter().enumerate() {
sighash.copy_from_slice(&signature_hash_data(
@ -234,7 +239,7 @@ impl TransparentInputs {
}
#[cfg(not(feature = "transparent-inputs"))]
fn apply_signatures(&self, _: &mut TransactionData, _: u32) {}
fn apply_signatures(&self, _: &mut TransactionData, _: consensus::BranchId) {}
}
/// Metadata about a transaction created by a [`Builder`].
@ -430,7 +435,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
/// the network.
pub fn build(
mut self,
consensus_branch_id: u32,
consensus_branch_id: consensus::BranchId,
prover: impl TxProver,
) -> Result<(Transaction, TransactionMetadata), Error> {
let mut tx_metadata = TransactionMetadata::new();
@ -666,6 +671,7 @@ mod tests {
use super::{Builder, Error};
use crate::{
consensus,
legacy::TransparentAddress,
merkle_tree::{CommitmentTree, IncrementalWitness},
prover::mock::MockTxProver,
@ -713,7 +719,7 @@ mod tests {
{
let builder = Builder::new(0);
assert_eq!(
builder.build(1, MockTxProver),
builder.build(consensus::BranchId::Sapling, MockTxProver),
Err(Error::ChangeIsNegative(Amount::from_i64(-10000).unwrap()))
);
}
@ -735,7 +741,7 @@ mod tests {
)
.unwrap();
assert_eq!(
builder.build(1, MockTxProver),
builder.build(consensus::BranchId::Sapling, MockTxProver),
Err(Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()))
);
}
@ -751,7 +757,7 @@ mod tests {
)
.unwrap();
assert_eq!(
builder.build(1, MockTxProver),
builder.build(consensus::BranchId::Sapling, MockTxProver),
Err(Error::ChangeIsNegative(Amount::from_i64(-60000).unwrap()))
);
}
@ -791,7 +797,7 @@ mod tests {
)
.unwrap();
assert_eq!(
builder.build(1, MockTxProver),
builder.build(consensus::BranchId::Sapling, MockTxProver),
Err(Error::ChangeIsNegative(Amount::from_i64(-1).unwrap()))
);
}
@ -824,7 +830,10 @@ mod tests {
Amount::from_u64(20000).unwrap(),
)
.unwrap();
assert_eq!(builder.build(1, MockTxProver), Err(Error::BindingSig))
assert_eq!(
builder.build(consensus::BranchId::Sapling, MockTxProver),
Err(Error::BindingSig)
)
}
}
}

View File

@ -7,7 +7,7 @@ use super::{
Transaction, TransactionData, OVERWINTER_VERSION_GROUP_ID, SAPLING_TX_VERSION,
SAPLING_VERSION_GROUP_ID,
};
use crate::legacy::Script;
use crate::{consensus, legacy::Script};
const ZCASH_SIGHASH_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZcashSigHash";
const ZCASH_PREVOUTS_HASH_PERSONALIZATION: &[u8; 16] = b"ZcashPrevoutHash";
@ -152,7 +152,7 @@ fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash {
pub fn signature_hash_data(
tx: &TransactionData,
consensus_branch_id: u32,
consensus_branch_id: consensus::BranchId,
hash_type: u32,
transparent_input: Option<(usize, &Script, Amount)>,
) -> Vec<u8> {
@ -162,7 +162,7 @@ pub fn signature_hash_data(
let mut personal = [0; 16];
(&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX);
(&mut personal[12..])
.write_u32::<LittleEndian>(consensus_branch_id)
.write_u32::<LittleEndian>(consensus_branch_id.into())
.unwrap();
let mut h = Blake2bParams::new()
@ -230,7 +230,7 @@ pub fn signature_hash_data(
pub fn signature_hash(
tx: &Transaction,
consensus_branch_id: u32,
consensus_branch_id: consensus::BranchId,
hash_type: u32,
transparent_input: Option<(usize, &Script, Amount)>,
) -> Vec<u8> {

View File

@ -5,6 +5,7 @@ use rand_core::OsRng;
use crate::jubjub::{fs::Fs, FixedGenerators};
use super::{components::Amount, sighash::signature_hash, Transaction, TransactionData};
use crate::consensus;
use crate::legacy::Script;
use crate::redjubjub::PrivateKey;
use crate::JUBJUB;
@ -216,7 +217,7 @@ fn zip_0143() {
transparent_input: Option<u32>,
hash_type: u32,
amount: i64,
consensus_branch_id: u32,
consensus_branch_id: consensus::BranchId,
sighash: [u8; 32],
};
@ -233,7 +234,7 @@ fn zip_0143() {
transparent_input: None,
hash_type: 1,
amount: 1672704339313879,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0xa1, 0xf1, 0xa4, 0xe5, 0xcd, 0x9b, 0xd5, 0x22, 0x32, 0x2d, 0x66, 0x1e, 0xdd, 0x2a,
0xf1, 0xbf, 0x2a, 0x70, 0x19, 0xcf, 0xab, 0x94, 0xec, 0xe1, 0x8f, 0x4b, 0xa9, 0x35,
@ -522,7 +523,7 @@ fn zip_0143() {
transparent_input: Some(1),
hash_type: 3,
amount: 365293780364847,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x23, 0x65, 0x2e, 0x76, 0xcb, 0x13, 0xb8, 0x5a, 0x0e, 0x33, 0x63, 0xbb, 0x5f, 0xca,
0x06, 0x1f, 0xa7, 0x91, 0xc4, 0x0c, 0x53, 0x3e, 0xcc, 0xee, 0x89, 0x93, 0x64, 0xe6,
@ -682,7 +683,7 @@ fn zip_0143() {
transparent_input: Some(0),
hash_type: 3,
amount: 711752082734717,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0xb3, 0x8e, 0x31, 0x70, 0x8c, 0xb7, 0x8e, 0xee, 0xc7, 0x66, 0x3e, 0xca, 0x1e, 0x01,
0xb7, 0x53, 0x9e, 0x26, 0xb7, 0x30, 0xcf, 0x44, 0x6d, 0x3b, 0xf5, 0x7a, 0x99, 0x8e,
@ -964,7 +965,7 @@ fn zip_0143() {
transparent_input: None,
hash_type: 1,
amount: 379068098637835,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x92, 0xe7, 0xb4, 0x8f, 0x32, 0x81, 0x87, 0x71, 0x26, 0x87, 0xaf, 0x4d, 0xc1, 0x7a,
0x73, 0xfe, 0x0a, 0x70, 0xac, 0x07, 0x8d, 0x24, 0xcd, 0xcd, 0xd4, 0x58, 0xa3, 0xd6,
@ -1123,7 +1124,7 @@ fn zip_0143() {
transparent_input: Some(0),
hash_type: 3,
amount: 1437866676382615,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0xd8, 0xe9, 0xb9, 0x72, 0xb2, 0x89, 0x8e, 0xfc, 0xca, 0x8e, 0x96, 0xbc, 0x98, 0x70,
0x00, 0x8c, 0xdb, 0xc1, 0x9d, 0x45, 0xb7, 0x8d, 0x09, 0xef, 0xb1, 0x02, 0xf2, 0xd7,
@ -1143,7 +1144,7 @@ fn zip_0143() {
transparent_input: None,
hash_type: 1,
amount: 1993227025071196,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x2b, 0x62, 0xff, 0x0c, 0x8d, 0xec, 0x4d, 0xf1, 0x8b, 0x99, 0x56, 0x61, 0x5b, 0x57,
0x4d, 0xda, 0x39, 0x42, 0xfe, 0x45, 0x2d, 0x91, 0x78, 0xb0, 0xbb, 0xb2, 0xea, 0xee,
@ -1166,7 +1167,7 @@ fn zip_0143() {
transparent_input: Some(1),
hash_type: 130,
amount: 449567650863240,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x49, 0x3d, 0x49, 0xc3, 0xe2, 0x22, 0x5d, 0x11, 0xc4, 0x64, 0x05, 0x18, 0x20, 0x14,
0x76, 0x25, 0xf3, 0x90, 0x9f, 0xa7, 0x18, 0x9f, 0x61, 0xc7, 0xea, 0xec, 0xfc, 0x6d,
@ -1448,7 +1449,7 @@ fn zip_0143() {
transparent_input: None,
hash_type: 1,
amount: 1712463999734827,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0xbb, 0x10, 0x30, 0x0e, 0x4d, 0xaf, 0xe3, 0x0c, 0x3f, 0xf0, 0x26, 0x34, 0xd0, 0xe0,
0x03, 0x2f, 0x17, 0x15, 0xb0, 0x0c, 0xbc, 0x77, 0x3d, 0xf6, 0xb0, 0x9e, 0x00, 0x43,
@ -1606,7 +1607,7 @@ fn zip_0143() {
transparent_input: Some(1),
hash_type: 1,
amount: 1564816348934332,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x21, 0x46, 0x62, 0xc6, 0x74, 0x50, 0x60, 0x3d, 0x8a, 0xa7, 0x3b, 0xea, 0xbb, 0xf7,
0x51, 0x8d, 0x03, 0x6c, 0xe9, 0x1d, 0xc8, 0x7b, 0x01, 0x81, 0xe8, 0xa0, 0xf3, 0xfa,
@ -1889,7 +1890,7 @@ fn zip_0143() {
transparent_input: Some(0),
hash_type: 2,
amount: 483959951916902,
consensus_branch_id: 1537743641,
consensus_branch_id: consensus::BranchId::Overwinter,
sighash: [
0x29, 0x6f, 0xd7, 0x63, 0xf2, 0x54, 0x5e, 0x64, 0xfb, 0x5d, 0x7d, 0x49, 0xc0, 0x00,
0xd2, 0xb4, 0x18, 0xb9, 0x3b, 0xde, 0x22, 0x34, 0xf8, 0x74, 0x29, 0x11, 0xe8, 0xaf,
@ -1925,7 +1926,7 @@ fn zip_0243() {
transparent_input: Option<u32>,
hash_type: u32,
amount: i64,
consensus_branch_id: u32,
consensus_branch_id: consensus::BranchId,
sighash: [u8; 32],
};
@ -2233,7 +2234,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1969273897303781,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x63, 0xd1, 0x85, 0x34, 0xde, 0x5f, 0x2d, 0x1c, 0x9e, 0x16, 0x9b, 0x73, 0xf9, 0xc7,
0x83, 0x71, 0x8a, 0xdb, 0xef, 0x5c, 0x8a, 0x7d, 0x55, 0xb5, 0xe7, 0xa3, 0x7a, 0xff,
@ -2466,7 +2467,7 @@ fn zip_0243() {
transparent_input: Some(1),
hash_type: 2,
amount: 652655344020909,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0xbb, 0xe6, 0xd8, 0x4f, 0x57, 0xc5, 0x6b, 0x29, 0xb9, 0x14, 0xc6, 0x94, 0xba, 0xac,
0xcb, 0x89, 0x12, 0x97, 0xe9, 0x61, 0xde, 0x3e, 0xb4, 0x6c, 0x68, 0xe3, 0xc8, 0x9c,
@ -3052,7 +3053,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1345602751504862,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x15, 0x53, 0xd4, 0xf1, 0x07, 0x45, 0x10, 0x71, 0x81, 0x99, 0x00, 0x5f, 0xef, 0xaa,
0xa8, 0x3e, 0x29, 0xd1, 0x63, 0xee, 0xbd, 0xf3, 0xc0, 0x33, 0x82, 0x79, 0x08, 0xac,
@ -3373,7 +3374,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1039204199089370,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x6c, 0x4e, 0x32, 0x44, 0xc2, 0xd2, 0xbf, 0xb8, 0xd6, 0xf6, 0x69, 0x97, 0x77, 0xa1,
0x1a, 0x64, 0xad, 0xfe, 0xe4, 0x9b, 0x2f, 0xc7, 0x81, 0xe6, 0x95, 0x15, 0x34, 0xf9,
@ -3523,7 +3524,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 691732482992802,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x5d, 0x40, 0x5a, 0x1c, 0x4d, 0xed, 0x19, 0x87, 0x98, 0x8a, 0x10, 0x03, 0x64, 0xa3,
0xcd, 0x6f, 0xe0, 0xba, 0x22, 0x20, 0xa6, 0xab, 0xce, 0x08, 0xc5, 0x17, 0x13, 0x59,
@ -3923,7 +3924,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1152393991505765,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x58, 0x11, 0x0e, 0x23, 0x19, 0xad, 0x85, 0x50, 0x4a, 0x69, 0x8f, 0x73, 0xe7, 0xac,
0x31, 0xa7, 0x23, 0xa0, 0x29, 0xec, 0x07, 0xb7, 0x72, 0xfb, 0xb3, 0x2f, 0xba, 0x17,
@ -4087,7 +4088,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1788797765223798,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0xcb, 0xfa, 0x22, 0x69, 0x9b, 0x04, 0xbe, 0xb7, 0x67, 0x07, 0xb5, 0x1d, 0x62, 0x5e,
0x94, 0xd2, 0x6c, 0x0d, 0xf8, 0xad, 0xa7, 0xcf, 0x68, 0xfc, 0xde, 0xd9, 0x60, 0x65,
@ -4685,7 +4686,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1871432121379810,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x36, 0x77, 0xa9, 0x48, 0x4f, 0x04, 0x04, 0xfb, 0x50, 0x64, 0x58, 0x56, 0xf4, 0xd4,
0xa7, 0x0b, 0x2e, 0x2b, 0x1c, 0x2d, 0x86, 0x2f, 0x1d, 0x4e, 0xf6, 0x8d, 0x52, 0x09,
@ -5194,7 +5195,7 @@ fn zip_0243() {
transparent_input: None,
hash_type: 1,
amount: 1501997449504444,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0xa1, 0xcf, 0x50, 0xcf, 0xfe, 0x59, 0xbe, 0x5f, 0x31, 0x5f, 0xfe, 0x51, 0x6e, 0x28,
0x9e, 0xe8, 0x02, 0x5e, 0x59, 0x38, 0xf1, 0xe8, 0xe1, 0x88, 0x53, 0x7f, 0xf1, 0xa8,
@ -5384,7 +5385,7 @@ fn zip_0243() {
transparent_input: Some(0),
hash_type: 3,
amount: 391892287957268,
consensus_branch_id: 1991772603,
consensus_branch_id: consensus::BranchId::Sapling,
sighash: [
0x6a, 0x3b, 0x2b, 0xcc, 0x15, 0x57, 0x89, 0xa2, 0x74, 0x39, 0xaa, 0x27, 0x5c, 0xa9,
0x9e, 0xc6, 0x48, 0xdd, 0xd5, 0x88, 0xe8, 0x2e, 0xfa, 0xe4, 0xac, 0x46, 0xba, 0x3f,