iuna

iuna - experimental devnet protocol
git clone https://iuna.jhx.app/git/iuna.git
Log | Files | Refs | README | LICENSE

commit b25639af59541215beb21c4065ce2233c2798b84
parent e336832e1b30ad7e9aaf16be67bea0a12313ed14
Author: Joris Hartog <jorishartog@hotmail.com>
Date:   Fri, 24 Jul 2026 14:05:19 +0200

Revert "Use mine action for genesis issuance"

This reverts commit 2c1dcedf8fd9f7e3e9f8923ebadcf4f542b7e7f2.

Diffstat:
Msrc/domain.rs | 64++--------------------------------------------------------------
Msrc/main.rs | 57++++++++++++++++++++-------------------------------------
2 files changed, 22 insertions(+), 99 deletions(-)

diff --git a/src/domain.rs b/src/domain.rs @@ -110,28 +110,6 @@ pub enum Transaction { } impl Transaction { - pub fn genesis_mine(to: impl Into<String>) -> Result<Self> { - let output = TxOutput { - address: to.into(), - amount: MINE_REWARD, - }; - let anchor = genesis_mine_anchor(); - let difficulty_bits = MINE_DIFFICULTY_BITS; - for nonce in 0..u64::MAX { - let signature = mine_signature(&output, &anchor, nonce, difficulty_bits); - if hash_meets_difficulty(&signature, difficulty_bits) { - return Ok(Self::Mine { - output, - anchor, - nonce, - difficulty_bits, - signature, - }); - } - } - bail!("could not find valid genesis mine proof"); - } - pub fn genesis_burn(from: impl Into<String>, amount: Amount) -> Self { let from = from.into(); Self::genesis_burn_with_change(from, amount, Vec::new()) @@ -475,10 +453,6 @@ fn mine_signature(output: &TxOutput, anchor: &str, nonce: u64, difficulty_bits: hex_hash(mine_payload(output, anchor, nonce, difficulty_bits)) } -fn genesis_mine_anchor() -> String { - "0".repeat(64) -} - fn hash_meets_difficulty(hash: &str, difficulty_bits: u32) -> bool { let full_zero_nibbles = (difficulty_bits / 4) as usize; let remaining_bits = difficulty_bits % 4; @@ -910,14 +884,6 @@ impl Ledger { Self::new_with_genesis_transactions(genesis_allocations, transactions, vdf_rounds) } - pub fn new_with_genesis_mine(recipient: impl Into<String>, vdf_rounds: u32) -> Result<Self> { - Self::new_with_genesis_transactions( - BTreeMap::new(), - vec![Transaction::genesis_mine(recipient)?], - vdf_rounds, - ) - } - fn new_with_genesis_transactions( genesis_allocations: BTreeMap<String, Amount>, genesis_transactions: Vec<Transaction>, @@ -2277,12 +2243,8 @@ fn utxos_after_genesis( for transaction in &genesis.transactions { match transaction { Transaction::Burn { .. } => apply_transaction(transaction, &mut utxos)?, - Transaction::Mine { .. } => { - validate_genesis_mine_transaction(transaction)?; - apply_transaction(transaction, &mut utxos)?; - } - Transaction::Transfer { .. } => { - bail!("genesis only supports burn and mine transactions") + Transaction::Transfer { .. } | Transaction::Mine { .. } => { + bail!("genesis only supports burn transactions") } } } @@ -2359,28 +2321,6 @@ fn validate_genesis_block(block: &Block) -> Result<()> { Ok(()) } -fn validate_genesis_mine_transaction(transaction: &Transaction) -> Result<()> { - let Transaction::Mine { - output, - anchor, - difficulty_bits, - .. - } = transaction - else { - bail!("genesis transaction is not a mine transaction"); - }; - if output.amount != MINE_REWARD { - bail!("genesis mine reward is invalid"); - } - if anchor != &genesis_mine_anchor() { - bail!("genesis mine anchor is invalid"); - } - if *difficulty_bits != MINE_DIFFICULTY_BITS { - bail!("genesis mine difficulty is invalid"); - } - transaction.verify_signature() -} - fn genesis_miner( genesis_allocations: &BTreeMap<String, Amount>, transactions: &[Transaction], diff --git a/src/main.rs b/src/main.rs @@ -11,12 +11,12 @@ use anyhow::{Context, Result, bail}; use luun::{ adapters::{chain_store::SqliteChainStore, config_store, http, p2p, wallet_store}, app::{NodeCore, PeerBook, SharedNode, SharedPeerBook, now_ms}, - domain::{Amount, ChainSnapshot, Ledger, MICRO_LUUN, MINE_REWARD, run_vdf}, + domain::{Amount, BLOCK_REWARD, ChainSnapshot, GenesisBurn, Ledger, MICRO_LUUN, run_vdf}, }; use tokio::sync::Mutex; -const GENESIS_INITIAL_BURN_PER_BLOCK: Amount = MINE_REWARD; -const GENESIS_INITIAL_BURN_FEE: Amount = 0; +const GENESIS_BOOTSTRAP_BURN_AMOUNT: Amount = MICRO_LUUN; +const GENESIS_INITIAL_BURN_PER_BLOCK: Amount = BLOCK_REWARD; const VDF_MEASUREMENT_INITIAL_ROUNDS: u32 = 1_000_000; const VDF_MEASUREMENT_MAX_ROUNDS: u32 = 100_000_000; const VDF_MEASUREMENT_MIN_ELAPSED: Duration = Duration::from_millis(150); @@ -47,7 +47,7 @@ async fn main() -> Result<()> { let ledger = initialize_ledger(&opts, wallet.address(), &chain_store).await?; let has_chain = opts.has_chain() || persisted_chain_exists; let initial_burn_per_block = initial_burn_per_block(&opts, &ui_config); - let initial_burn_fee = initial_burn_fee(&opts, &ui_config); + let initial_burn_fee = ui_config.burn_fee; let node: SharedNode = Arc::new(Mutex::new(NodeCore::from_ledger_with_burn_fee( wallet, @@ -299,13 +299,6 @@ fn initial_burn_per_block(opts: &CliOptions, ui_config: &config_store::UiConfig) } } -fn initial_burn_fee(opts: &CliOptions, ui_config: &config_store::UiConfig) -> Amount { - match opts.chain_mode { - ChainMode::Genesis => GENESIS_INITIAL_BURN_FEE, - ChainMode::Setup | ChainMode::Join => ui_config.burn_fee, - } -} - fn print_help() { println!("{}", help_text()); } @@ -342,7 +335,16 @@ fn setup_ledger() -> Ledger { fn start_genesis_ledger(wallet_address: &str) -> Result<Ledger> { let vdf_rounds = measure_initial_vdf_rounds(); - Ledger::new_with_genesis_mine(wallet_address, vdf_rounds) + let mut genesis = BTreeMap::new(); + genesis.insert(wallet_address.to_string(), GENESIS_BOOTSTRAP_BURN_AMOUNT); + Ledger::new_with_genesis_burns( + genesis, + vec![GenesisBurn::new( + wallet_address, + GENESIS_BOOTSTRAP_BURN_AMOUNT, + )], + vdf_rounds, + ) } fn measure_initial_vdf_rounds() -> u32 { @@ -545,16 +547,16 @@ mod tests { use luun::{ adapters::{chain_store::SqliteChainStore, config_store::UiConfig}, app::{DEFAULT_BURN_PER_BLOCK, NodeCore}, - domain::{GenesisBurn, Ledger, MINE_REWARD, Transaction, Wallet}, + domain::{BLOCK_REWARD, GenesisBurn, Ledger, Wallet}, }; use rusqlite::Connection; use tempfile::tempdir; use tokio::sync::Mutex; use super::{ - ChainMode, CliOptions, extrapolate_vdf_rounds, help_text, initial_burn_fee, - initial_burn_per_block, initialize_ledger, measure_vdf_rounds, persist_chain_snapshot, - run_chain_persistence_with_interval, start_genesis_ledger, validate_wallet_for_mode, + ChainMode, CliOptions, extrapolate_vdf_rounds, help_text, initial_burn_per_block, + initialize_ledger, measure_vdf_rounds, persist_chain_snapshot, + run_chain_persistence_with_interval, validate_wallet_for_mode, }; fn parse(args: &[&str]) -> anyhow::Result<Option<CliOptions>> { @@ -629,31 +631,14 @@ mod tests { } #[test] - fn genesis_mode_starts_with_mine_reward_burn_rate_and_zero_fee() { + fn genesis_mode_starts_with_full_reward_burn_rate() { let genesis = parse(&["--genesis"]).unwrap().unwrap(); let configured = UiConfig { burn_per_block: 50, burn_fee: 3, ..UiConfig::default() }; - assert_eq!(initial_burn_per_block(&genesis, &configured), MINE_REWARD); - assert_eq!(initial_burn_fee(&genesis, &configured), 0); - } - - #[test] - fn genesis_ledger_starts_with_single_mine_action() { - let wallet = Wallet::from_seed("genesis-mine-wallet"); - let ledger = start_genesis_ledger(wallet.address()).unwrap(); - let genesis = &ledger.chain()[0]; - - assert_eq!(genesis.height, 0); - assert_eq!(genesis.miner, "genesis"); - assert_eq!(genesis.reward, 0); - assert_eq!(genesis.transactions.len(), 1); - assert!(matches!(genesis.transactions[0], Transaction::Mine { .. })); - assert_eq!(genesis.transactions[0].amount(), MINE_REWARD); - assert_eq!(ledger.balance_of(wallet.address()), MINE_REWARD); - assert_eq!(ledger.expected_leader_for_next_block(), None); + assert_eq!(initial_burn_per_block(&genesis, &configured), BLOCK_REWARD); } #[test] @@ -666,11 +651,9 @@ mod tests { let setup = parse(&[]).unwrap().unwrap(); assert_eq!(initial_burn_per_block(&setup, &configured), 50); - assert_eq!(initial_burn_fee(&setup, &configured), 3); let join = parse(&["--join", "127.0.0.1:9444"]).unwrap().unwrap(); assert_eq!(initial_burn_per_block(&join, &configured), 50); - assert_eq!(initial_burn_fee(&join, &configured), 3); assert_eq!( initial_burn_per_block(&setup, &UiConfig::default()),