Skip to content

Commit

Permalink
feat: Add constructor for fee-gobbler transaction details
Browse files Browse the repository at this point in the history
Specifically, method `fee_gobbler` on `TransactionDetails`.

Also:
 - Move and factor out common code that does not depend on
   `GlobalState` away from `GlobalState`.
 - Rename `COINASE_TIME_LOCK_PERIOD` to
   `MINING_REWARD_TIME_LOCK_PERIOD`.
 - Add convenience function `native_currency` on `TxOutput`.

Co-authored-by: Thorkil Schmidiger <[email protected]>
  • Loading branch information
aszepieniec and Sword-Smith committed Dec 19, 2024
1 parent f97275e commit 71f1cf6
Show file tree
Hide file tree
Showing 34 changed files with 239 additions and 169 deletions.
2 changes: 1 addition & 1 deletion benches/archival_mmr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use neptune_cash::database::storage::storage_vec::traits::StorageVecBase;
use neptune_cash::database::NeptuneLevelDb;
use neptune_cash::util_types::mutator_set::archival_mmr::ArchivalMmr;
use rand::random;
use tasm_lib::twenty_first::util_types::mmr::shared_advanced::num_leafs_to_num_nodes;
use tasm_lib::prelude::Digest;
use tasm_lib::twenty_first::util_types::mmr::shared_advanced::num_leafs_to_num_nodes;

fn main() {
divan::main();
Expand Down
2 changes: 1 addition & 1 deletion src/mine_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ pub(crate) async fn make_coinbase_transaction(
receiving_address.into(),
owned,
)
.with_time_lock(timestamp + COINBASE_TIME_LOCK_PERIOD + Timestamp::minutes(30));
.with_time_lock(timestamp + MINING_REWARD_TIME_LOCK_PERIOD + Timestamp::minutes(30));

let transaction_details = TransactionDetails::new_with_coinbase(
vec![],
Expand Down
7 changes: 4 additions & 3 deletions src/models/blockchain/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ use crate::util_types::mutator_set::mutator_set_accumulator::MutatorSetAccumulat
/// blocks with many outputs.
pub(crate) const MAX_BLOCK_SIZE: usize = 250_000;

/// Duration of timelock for half the block subsidy.
/// Duration of timelock for half of all mining rewards.
///
/// Half the block subsidy is liquid immediately. Half of it is locked for this
/// time period.
pub(crate) const COINBASE_TIME_LOCK_PERIOD: Timestamp = Timestamp::years(3);
/// time period. Likewise, half the guesser fee is liquid immediately; and half
/// is time locked for this period.
pub(crate) const MINING_REWARD_TIME_LOCK_PERIOD: Timestamp = Timestamp::years(3);

/// All blocks have proofs except the genesis block
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, BFieldCodec, GetSize, Default)]
Expand Down
2 changes: 1 addition & 1 deletion src/models/blockchain/block/validity/appendix_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use serde::Deserialize;
use serde::Serialize;
use tasm_lib::memory::encode_to_memory;
use tasm_lib::memory::FIRST_NON_DETERMINISTICALLY_INITIALIZED_MEMORY_ADDRESS;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::TasmObject;
use tasm_lib::triton_vm;
use tasm_lib::triton_vm::prelude::BFieldCodec;
Expand All @@ -15,7 +16,6 @@ use tasm_lib::triton_vm::stark::Stark;
use tasm_lib::triton_vm::vm::NonDeterminism;
use tasm_lib::triton_vm::vm::PublicInput;
use tasm_lib::verifier::stark_verify::StarkVerify;
use tasm_lib::prelude::Digest;

use super::block_primitive_witness::BlockPrimitiveWitness;
use super::block_program::BlockProgram;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::OnceLock;

use tasm_lib::twenty_first::prelude::Mmr;
use tasm_lib::prelude::Digest;
use tasm_lib::twenty_first::prelude::Mmr;

use crate::models::blockchain::block::block_body::BlockBody;
use crate::models::blockchain::block::block_header::BlockHeader;
Expand Down Expand Up @@ -134,8 +134,8 @@ pub(crate) mod test {
use proptest::strategy::Strategy;
use proptest::test_runner::TestRunner;
use proptest_arbitrary_interop::arb;
use tasm_lib::triton_vm::prelude::Tip5;
use tasm_lib::prelude::Digest;
use tasm_lib::triton_vm::prelude::Tip5;

use super::BlockPrimitiveWitness;
use crate::job_queue::triton_vm::TritonVmJobPriority;
Expand Down
2 changes: 1 addition & 1 deletion src/models/blockchain/block/validity/block_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use tasm_lib::triton_vm::proof::Claim;
use tasm_lib::triton_vm::proof::Proof;
use tasm_lib::triton_vm::stark::Stark;

use tasm_lib::verifier::stark_verify::StarkVerify;
use tasm_lib::prelude::Digest;
use tasm_lib::verifier::stark_verify::StarkVerify;

use super::appendix_witness::AppendixWitness;
use crate::models::blockchain::block::block_body::BlockBody;
Expand Down
1 change: 1 addition & 0 deletions src/models/blockchain/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::models::proof_abstractions::mast_hash::MastHash;
use crate::models::proof_abstractions::tasm::program::ConsensusProgram;
use crate::models::proof_abstractions::tasm::program::TritonVmProofJobOptions;
use crate::models::proof_abstractions::SecretWitness;
use crate::models::state::transaction_details::TransactionDetails;
use crate::models::state::wallet::expected_utxo::ExpectedUtxo;
use crate::models::state::wallet::expected_utxo::UtxoNotifier;
use crate::prelude::twenty_first;
Expand Down
140 changes: 134 additions & 6 deletions src/models/blockchain/transaction/primitive_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use proptest_arbitrary_interop::arb;
use rand::rngs::StdRng;
use rand::thread_rng;
use rand::Rng;
use rand::SeedableRng;
use serde::Deserialize;
use serde::Serialize;
use tasm_lib::prelude::Digest;
Expand All @@ -30,7 +31,9 @@ use super::transaction_kernel::TransactionKernel;
use super::transaction_kernel::TransactionKernelProxy;
use super::utxo::Utxo;
use super::PublicAnnouncement;
use crate::models::blockchain::block::COINBASE_TIME_LOCK_PERIOD;
use super::TransactionDetails;
use crate::models::blockchain::block::MINING_REWARD_TIME_LOCK_PERIOD;
use crate::models::blockchain::type_scripts::known_type_scripts::match_type_script_and_generate_witness;
use crate::models::blockchain::type_scripts::native_currency::NativeCurrencyWitness;
use crate::models::blockchain::type_scripts::neptune_coins::NeptuneCoins;
use crate::models::blockchain::type_scripts::time_lock::TimeLock;
Expand All @@ -41,6 +44,7 @@ use crate::models::blockchain::type_scripts::TypeScriptWitness;
use crate::models::proof_abstractions::mast_hash::MastHash;
use crate::models::proof_abstractions::timestamp::Timestamp;
use crate::models::state::wallet::address::generation_address;
use crate::models::state::wallet::unlocked_utxo::UnlockedUtxo;
use crate::util_types::mutator_set::commit;
use crate::util_types::mutator_set::ms_membership_proof::MsMembershipProof;
use crate::util_types::mutator_set::msa_and_records::MsaAndRecords;
Expand Down Expand Up @@ -166,6 +170,130 @@ impl Display for PrimitiveWitness {
}

impl PrimitiveWitness {
/// Generate a primitive witness for a transaction from various disparate witness data.
///
/// # Panics
/// Panics if transaction validity cannot be satisfied.
fn generate_primitive_witness(
unlocked_utxos: Vec<UnlockedUtxo>,
output_utxos: Vec<Utxo>,
sender_randomnesses: Vec<Digest>,
receiver_digests: Vec<Digest>,
transaction_kernel: TransactionKernel,
mutator_set_accumulator: MutatorSetAccumulator,
) -> PrimitiveWitness {
/// Generate a salt to use for [SaltedUtxos], deterministically.
fn generate_secure_pseudorandom_seed(
input_utxos: &Vec<Utxo>,
output_utxos: &Vec<Utxo>,
sender_randomnesses: &Vec<Digest>,
) -> [u8; 32] {
let preimage = [
input_utxos.encode(),
output_utxos.encode(),
sender_randomnesses.encode(),
]
.concat();
let seed = Tip5::hash_varlen(&preimage);
let seed: [u8; Digest::BYTES] = seed.into();

seed[0..32].try_into().unwrap()
}

let input_utxos = unlocked_utxos
.iter()
.map(|unlocker| unlocker.utxo.to_owned())
.collect_vec();
let salt_seed =
generate_secure_pseudorandom_seed(&input_utxos, &output_utxos, &sender_randomnesses);

let mut rng = StdRng::from_seed(salt_seed);
let salted_output_utxos = SaltedUtxos::new_with_rng(output_utxos.to_vec(), &mut rng);
let salted_input_utxos = SaltedUtxos::new_with_rng(input_utxos.clone(), &mut rng);

let type_script_hashes = input_utxos
.iter()
.chain(output_utxos.iter())
.flat_map(|utxo| utxo.coins().iter().map(|coin| coin.type_script_hash))
.unique()
.collect_vec();
let type_scripts_and_witnesses = type_script_hashes
.into_iter()
.map(|type_script_hash| {
match_type_script_and_generate_witness(
type_script_hash,
transaction_kernel.clone(),
salted_input_utxos.clone(),
salted_output_utxos.clone(),
)
.expect("type script hash should be known.")
})
.collect_vec();
let input_lock_scripts_and_witnesses = unlocked_utxos
.iter()
.map(|unlocker| unlocker.lock_script_and_witness())
.cloned()
.collect_vec();
let input_membership_proofs = unlocked_utxos
.iter()
.map(|unlocker| unlocker.mutator_set_mp().to_owned())
.collect_vec();

PrimitiveWitness {
input_utxos: salted_input_utxos,
lock_scripts_and_witnesses: input_lock_scripts_and_witnesses,
type_scripts_and_witnesses,
input_membership_proofs,
output_utxos: salted_output_utxos,
output_sender_randomnesses: sender_randomnesses.to_vec(),
output_receiver_digests: receiver_digests.to_vec(),
mutator_set_accumulator,
kernel: transaction_kernel,
}
}

/// Create a [`PrimitiveWitness`] from [`TransactionDetails`].
pub(crate) fn from_transaction_details(transaction_details: TransactionDetails) -> Self {
let TransactionDetails {
tx_inputs,
tx_outputs,
fee,
coinbase,
timestamp,
mutator_set_accumulator,
} = transaction_details;

// complete transaction kernel
let removal_records = tx_inputs
.iter()
.map(|txi| txi.removal_record(&mutator_set_accumulator))
.collect_vec();
let kernel = TransactionKernelProxy {
inputs: removal_records,
outputs: tx_outputs.addition_records(),
public_announcements: tx_outputs.public_announcements(),
fee,
timestamp,
coinbase,
mutator_set_hash: mutator_set_accumulator.hash(),
}
.into_kernel();

// populate witness
let output_utxos = tx_outputs.utxos();
let unlocked_utxos = tx_inputs;
let sender_randomnesses = tx_outputs.sender_randomnesses();
let receiver_digests = tx_outputs.receiver_digests();
Self::generate_primitive_witness(
unlocked_utxos,
output_utxos,
sender_randomnesses,
receiver_digests,
kernel.clone(),
mutator_set_accumulator,
)
}

pub fn transaction_inputs_from_address_seeds_and_amounts(
address_seeds: &[Digest],
input_amounts: &[NeptuneCoins],
Expand Down Expand Up @@ -546,7 +674,7 @@ impl PrimitiveWitness {
let output_utxos = Self::valid_tx_outputs_from_amounts_and_address_seeds(
&output_amounts,
&output_address_seeds,
maybe_coinbase.map(|_| timestamp + COINBASE_TIME_LOCK_PERIOD),
maybe_coinbase.map(|_| timestamp + MINING_REWARD_TIME_LOCK_PERIOD),
);
Self::arbitrary_primitive_witness_with_timestamp_and(
&input_utxos,
Expand Down Expand Up @@ -949,7 +1077,7 @@ mod test {
// Notice that we're in the general case timelocking more than we have to here.
let max_timestamp = *timestamps.iter().max().unwrap();
*utxo = utxo.clone().with_time_lock(
max_timestamp + COINBASE_TIME_LOCK_PERIOD,
max_timestamp + MINING_REWARD_TIME_LOCK_PERIOD,
);
timelocked_cb_acc = timelocked_cb_acc + amount;
}
Expand Down Expand Up @@ -1284,7 +1412,7 @@ mod test {
mut timestamp,
extra_amount,
)| {
while timestamp + COINBASE_TIME_LOCK_PERIOD < timestamp {
while timestamp + MINING_REWARD_TIME_LOCK_PERIOD < timestamp {
timestamp = Timestamp::millis(timestamp.to_millis() >> 1);
}

Expand All @@ -1307,7 +1435,7 @@ mod test {
LockScript::hash_lock(output_seeds[0]),
timelocked_amount,
)
.with_time_lock(timestamp + COINBASE_TIME_LOCK_PERIOD);
.with_time_lock(timestamp + MINING_REWARD_TIME_LOCK_PERIOD);

let mut liquid_amount =
total_amount.checked_sub(&timelocked_amount).unwrap();
Expand Down Expand Up @@ -1335,7 +1463,7 @@ mod test {
LockScript::hash_lock(output_seeds[0]),
first_amount,
)
.with_time_lock(timestamp + COINBASE_TIME_LOCK_PERIOD);
.with_time_lock(timestamp + MINING_REWARD_TIME_LOCK_PERIOD);

let second_amount = total_amount
.checked_sub(&first_amount)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use tasm_lib::structure::verify_nd_si_integrity::VerifyNdSiIntegrity;
use tasm_lib::triton_vm::prelude::*;
use tasm_lib::twenty_first::bfieldcodec_derive::BFieldCodec;


use crate::models::blockchain::shared::Hash;
use crate::models::blockchain::transaction::primitive_witness::PrimitiveWitness;
use crate::models::blockchain::transaction::primitive_witness::SaltedUtxos;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod tests {
use strum::VariantArray;
use tasm_lib::hashing::merkle_verify::MERKLE_AUTHENTICATION_ROOT_MISMATCH_ERROR;
use tasm_lib::memory::encode_to_memory;
use tasm_lib::prelude::Digest;
use tasm_lib::snippet_bencher::BenchmarkCase;
use tasm_lib::test_helpers::test_assertion_failure;
use tasm_lib::traits::read_only_algorithm::ReadOnlyAlgorithm;
Expand All @@ -85,7 +86,6 @@ mod tests {
use tasm_lib::traits::rust_shadow::RustShadow;
use tasm_lib::twenty_first::bfe;
use tasm_lib::twenty_first::prelude::*;
use tasm_lib::prelude::Digest;

use super::*;
use crate::models::blockchain::transaction::primitive_witness::PrimitiveWitness;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use tasm_lib::data_type::DataType;
use tasm_lib::field;
use tasm_lib::field_with_size;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::*;
use tasm_lib::traits::basic_snippet::BasicSnippet;
use tasm_lib::triton_vm::prelude::*;
use tasm_lib::prelude::Digest;

use crate::models::blockchain::transaction::validity::collect_lock_scripts::CollectLockScripts;
use crate::models::blockchain::transaction::validity::proof_collection::ProofCollection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use tasm_lib::data_type::DataType;
use tasm_lib::field;
use tasm_lib::field_with_size;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::*;
use tasm_lib::traits::basic_snippet::BasicSnippet;
use tasm_lib::triton_vm::prelude::*;
use tasm_lib::prelude::Digest;

use crate::models::blockchain::transaction::validity::collect_type_scripts::CollectTypeScripts;
use crate::models::blockchain::transaction::validity::proof_collection::ProofCollection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use tasm_lib::data_type::DataType;
use tasm_lib::field;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::*;
use tasm_lib::traits::basic_snippet::BasicSnippet;
use tasm_lib::triton_vm::prelude::*;
use tasm_lib::prelude::Digest;

use crate::models::blockchain::transaction::validity::kernel_to_outputs::KernelToOutputs;
use crate::models::blockchain::transaction::validity::proof_collection::ProofCollection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ mod test {
use rand::SeedableRng;
use tasm_lib::memory::encode_to_memory;
use tasm_lib::prelude::BasicSnippet;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::TasmObject;
use tasm_lib::snippet_bencher::BenchmarkCase;
use tasm_lib::traits::function::Function;
Expand All @@ -84,7 +85,6 @@ mod test {
use tasm_lib::traits::rust_shadow::RustShadow;
use tasm_lib::triton_vm::prelude::BFieldElement;
use tasm_lib::twenty_first::bfe;
use tasm_lib::prelude::Digest;

use super::GenerateLockScriptClaimTemplate;
use crate::job_queue::triton_vm::TritonVmJobPriority;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use tasm_lib::data_type::DataType;
use tasm_lib::field;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::*;
use tasm_lib::traits::basic_snippet::BasicSnippet;
use tasm_lib::triton_vm::prelude::*;
use tasm_lib::prelude::Digest;

use crate::models::blockchain::transaction::validity::proof_collection::ProofCollection;
use crate::models::blockchain::transaction::validity::removal_records_integrity::RemovalRecordsIntegrity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ mod tests {
use tasm_lib::traits::function::ShadowedFunction;
use tasm_lib::traits::rust_shadow::RustShadow;


use super::*;
use crate::models::blockchain::transaction::primitive_witness::PrimitiveWitness;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use tasm_lib::traits::function::FunctionInitialState;
use tasm_lib::triton_vm::prelude::*;
use twenty_first::math::bfield_codec::BFieldCodec;


use crate::models::blockchain::shared::Hash;
use crate::models::blockchain::transaction::utxo::pseudorandom_utxo;
use crate::models::blockchain::transaction::utxo::Utxo;
Expand Down
Loading

0 comments on commit 71f1cf6

Please sign in to comment.