zebra/zebra-chain/src/transaction/builder.rs

170 lines
6.8 KiB
Rust
Raw Normal View History

//! Methods for building transactions.
use crate::{
amount::{Amount, NonNegative},
block::Height,
parameters::{Network, NetworkUpgrade},
transaction::{LockTime, Transaction},
transparent,
};
impl Transaction {
/// Returns a new version 5 coinbase transaction for `network` and `height`,
/// which contains the specified `outputs`.
pub fn new_v5_coinbase(
change(chain): Remove `Copy` trait impl from `Network` (#8354) * removed derive copy from network, address and ledgerstate * changed is_max_block_time_enforced to accept ref * changed NetworkUpgrade::Current to accept ref * changed NetworkUpgrade::Next to accept ref * changed NetworkUpgrade::IsActivationHeight to accept ref * changed NetworkUpgrade::TargetSpacingForHeight to accept ref * changed NetworkUpgrade::TargetSpacings to accept ref * changed NetworkUpgrade::MinimumDifficultySpacing_forHeight to accept ref * changed NetworkUpgrade::IsTestnetMinDifficultyBlock to accept ref * changed NetworkUpgrade::AveragingWindowTimespanForHeight to accept ref * changed NetworkUpgrade::ActivationHeight to accept ref * changed sapling_activation_height to accept ref * fixed lifetime for target_spacings * fixed sapling_activation_height * changed transaction_to_fake_v5 and fake_v5_transactions_for_network to accept ref to network * changed Input::vec_strategy to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_history.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/primitives/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/viewing_key* to accept ref to network * changed functions in zebra-chain/src/transparent/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_primitives.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_note_encryption.rs to accept ref to network * changed functions in zebra-chain/src/primitives/history_tree* to accept ref to network * changed functions in zebra-chain/src/block* to accept ref to network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * fixed errors in zebra-chain/src/block/arbitrary.rs * finished fixing errors in zebra-chain - all crate tests pass * changed functions in zebra-state::service::finalized_state to accept &Network * changed functions in zebra-state::service::non_finalized_state to accept &Network * zebra-state tests run but fail with overflow error * zebra-state tests all pass * converted zebra-network -- all crate tests pass * applied all requested changes from review * converted zebra-consensus -- all crate tests pass * converted zebra-scan -- all crate tests pass * converted zebra-rpc -- all crate tests pass * converted zebra-grpc -- all crate tests pass * converted zebrad -- all crate tests pass * applied all requested changes from review * fixed all clippy errors * fixed build error in zebrad/src/components/mempool/crawler.rs
2024-03-19 13:45:27 -07:00
network: &Network,
height: Height,
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
extra_coinbase_data: Vec<u8>,
) -> Transaction {
// # Consensus
//
// These consensus rules apply to v5 coinbase transactions after NU5 activation:
//
// > If effectiveVersion ≥ 5 then this condition MUST hold:
// > tx_in_count > 0 or nSpendsSapling > 0 or
// > (nActionsOrchard > 0 and enableSpendsOrchard = 1).
//
// > A coinbase transaction for a block at block height greater than 0 MUST have
// > a script that, as its first item, encodes the block height height as follows. ...
// > let heightBytes be the signed little-endian representation of height,
// > using the minimum nonzero number of bytes such that the most significant byte
// > is < 0x80. The length of heightBytes MUST be in the range {1 .. 5}.
// > Then the encoding is the length of heightBytes encoded as one byte,
// > followed by heightBytes itself. This matches the encoding used by Bitcoin
// > in the implementation of [BIP-34]
// > (but the description here is to be considered normative).
//
// > A coinbase transaction script MUST have length in {2 .. 100} bytes.
//
// Zebra adds extra coinbase data if configured to do so.
//
// Since we're not using a lock time, any sequence number is valid here.
// See `Transaction::lock_time()` for the relevant consensus rules.
//
// <https://zips.z.cash/protocol/protocol.pdf#txnconsensus>
let inputs = vec![transparent::Input::new_coinbase(
height,
Some(extra_coinbase_data),
None,
)];
// > The block subsidy is composed of a miner subsidy and a series of funding streams.
//
// <https://zips.z.cash/protocol/protocol.pdf#subsidyconcepts>
//
// > The total value in zatoshi of transparent outputs from a coinbase transaction,
// > minus vbalanceSapling, minus vbalanceOrchard, MUST NOT be greater than
// > the value in zatoshi of block subsidy plus the transaction fees
// > paid by transactions in this block.
//
// > If effectiveVersion ≥ 5 then this condition MUST hold:
// > tx_out_count > 0 or nOutputsSapling > 0 or
// > (nActionsOrchard > 0 and enableOutputsOrchard = 1).
//
// <https://zips.z.cash/protocol/protocol.pdf#txnconsensus>
let outputs: Vec<_> = outputs
.into_iter()
.map(|(amount, lock_script)| transparent::Output::new_coinbase(amount, lock_script))
.collect();
assert!(
!outputs.is_empty(),
"invalid coinbase transaction: must have at least one output"
);
Transaction::V5 {
// > The transaction version number MUST be 4 or 5. ...
// > If the transaction version number is 5 then the version group ID
// > MUST be 0x26A7270A.
// > If effectiveVersion ≥ 5, the nConsensusBranchId field MUST match the consensus
// > branch ID used for SIGHASH transaction hashes, as specified in [ZIP-244].
network_upgrade: NetworkUpgrade::current(network, height),
// There is no documented consensus rule for the lock time field in coinbase
// transactions, so we just leave it unlocked. (We could also set it to `height`.)
lock_time: LockTime::unlocked(),
// > The nExpiryHeight field of a coinbase transaction MUST be equal to its
// > block height.
expiry_height: height,
inputs,
outputs,
// Zebra does not support shielded coinbase yet.
//
// > In a version 5 coinbase transaction, the enableSpendsOrchard flag MUST be 0.
// > In a version 5 transaction, the reserved bits 2 .. 7 of the flagsOrchard field
// > MUST be zero.
//
// See the Zcash spec for additional shielded coinbase consensus rules.
sapling_shielded_data: None,
orchard_shielded_data: None,
}
}
/// Returns a new version 4 coinbase transaction for `network` and `height`,
/// which contains the specified `outputs`.
///
/// If `like_zcashd` is true, try to match the coinbase transactions generated by `zcashd`
/// in the `getblocktemplate` RPC.
pub fn new_v4_coinbase(
change(chain): Remove `Copy` trait impl from `Network` (#8354) * removed derive copy from network, address and ledgerstate * changed is_max_block_time_enforced to accept ref * changed NetworkUpgrade::Current to accept ref * changed NetworkUpgrade::Next to accept ref * changed NetworkUpgrade::IsActivationHeight to accept ref * changed NetworkUpgrade::TargetSpacingForHeight to accept ref * changed NetworkUpgrade::TargetSpacings to accept ref * changed NetworkUpgrade::MinimumDifficultySpacing_forHeight to accept ref * changed NetworkUpgrade::IsTestnetMinDifficultyBlock to accept ref * changed NetworkUpgrade::AveragingWindowTimespanForHeight to accept ref * changed NetworkUpgrade::ActivationHeight to accept ref * changed sapling_activation_height to accept ref * fixed lifetime for target_spacings * fixed sapling_activation_height * changed transaction_to_fake_v5 and fake_v5_transactions_for_network to accept ref to network * changed Input::vec_strategy to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_history.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/history_tree.rs to accept ref to network * changed functions in zebra-chain/src/primitives/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/viewing_key* to accept ref to network * changed functions in zebra-chain/src/transparent/address.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_primitives.rs to accept ref to network * changed functions in zebra-chain/src/primitives/zcash_note_encryption.rs to accept ref to network * changed functions in zebra-chain/src/primitives/history_tree* to accept ref to network * changed functions in zebra-chain/src/block* to accept ref to network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain::parameters::network * fixed errors in zebra-chain * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * changed NonEmptyHistoryTree and InnerHistoryTree to hold value instead of ref * fixed errors in zebra-chain/src/block/arbitrary.rs * finished fixing errors in zebra-chain - all crate tests pass * changed functions in zebra-state::service::finalized_state to accept &Network * changed functions in zebra-state::service::non_finalized_state to accept &Network * zebra-state tests run but fail with overflow error * zebra-state tests all pass * converted zebra-network -- all crate tests pass * applied all requested changes from review * converted zebra-consensus -- all crate tests pass * converted zebra-scan -- all crate tests pass * converted zebra-rpc -- all crate tests pass * converted zebra-grpc -- all crate tests pass * converted zebrad -- all crate tests pass * applied all requested changes from review * fixed all clippy errors * fixed build error in zebrad/src/components/mempool/crawler.rs
2024-03-19 13:45:27 -07:00
_network: &Network,
height: Height,
outputs: impl IntoIterator<Item = (Amount<NonNegative>, transparent::Script)>,
like_zcashd: bool,
extra_coinbase_data: Vec<u8>,
) -> Transaction {
let mut extra_data = None;
let mut sequence = None;
// `zcashd` includes an extra byte after the coinbase height in the coinbase data,
// and a sequence number of u32::MAX.
if like_zcashd {
extra_data = Some(vec![0x00]);
sequence = Some(u32::MAX);
}
// Override like_zcashd if extra_coinbase_data was supplied
if !extra_coinbase_data.is_empty() {
extra_data = Some(extra_coinbase_data);
}
// # Consensus
//
// See the other consensus rules above in new_v5_coinbase().
//
// > If effectiveVersion < 5, then at least one of tx_in_count, nSpendsSapling,
// > and nJoinSplit MUST be nonzero.
let inputs = vec![transparent::Input::new_coinbase(
height, extra_data, sequence,
)];
// > If effectiveVersion < 5, then at least one of tx_out_count, nOutputsSapling,
// > and nJoinSplit MUST be nonzero.
let outputs: Vec<_> = outputs
.into_iter()
.map(|(amount, lock_script)| transparent::Output::new_coinbase(amount, lock_script))
.collect();
assert!(
!outputs.is_empty(),
"invalid coinbase transaction: must have at least one output"
);
// > The transaction version number MUST be 4 or 5. ...
// > If the transaction version number is 4 then the version group ID MUST be 0x892F2085.
Transaction::V4 {
lock_time: LockTime::unlocked(),
expiry_height: height,
inputs,
outputs,
// Zebra does not support shielded coinbase yet.
joinsplit_data: None,
sapling_shielded_data: None,
}
}
}