Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **mina-node-account**: move tests into `node/account/tests`, document the
library and run the tests in CI
([#1540](https://github.com/o1-labs/mina-rust/pull/1540)).
- **Ledger**: add tests to verify some properties transaction application
should have on the ledger. Also, document the different types of transactions
that can be used to modify the ledger
([#1541](https://github.com/o1-labs/mina-rust/pull/1541))

### Changed

Expand Down
41 changes: 41 additions & 0 deletions ledger/src/scan_state/transaction_logic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,10 +1051,51 @@ impl GenericTransaction for Transaction {
}
}

/// Top-level transaction type representing all possible transactions in the
/// Mina protocol.
///
/// Transactions in Mina fall into two categories:
///
/// ## User-initiated transactions
///
/// - [`Command`](Transaction::Command): User-initiated transactions that can be
/// either signed commands (payments and stake delegations) or zkApp commands
/// (complex multi-account zero-knowledge operations). These transactions are
/// submitted by users, require signatures, and pay fees to block producers.
///
/// ## Protocol transactions
///
/// - [`FeeTransfer`](Transaction::FeeTransfer): System-generated transaction
/// that distributes collected transaction fees to block producers. Created
/// automatically during block production and does not require user signatures.
/// - [`Coinbase`](Transaction::Coinbase): System-generated transaction that
/// rewards block producers for successfully producing a block. May include an
/// optional fee transfer component to split rewards.
///
/// # Transaction processing
///
/// All transactions are processed through the two-phase application model
/// ([`apply_transaction_first_pass`] and [`apply_transaction_second_pass`]) to
/// enable efficient proof generation. Protocol transactions (fee transfers and
/// coinbase) complete entirely in the first pass, while user commands may
/// require both passes.
///
/// # Serialization
///
/// The type uses [`derive_more::From`] for automatic conversion from variant
/// types and implements conversion to/from the p2p wire format
/// [`MinaTransactionTransactionStableV2`].
///
/// OCaml reference: src/lib/transaction/transaction.ml L:8-11
/// Commit: 5da42ccd72e791f164d4d200cf1ce300262873b3
/// Last verified: 2025-10-10
#[derive(Clone, Debug, derive_more::From)]
pub enum Transaction {
/// User-initiated transaction: signed command or zkApp command
Command(UserCommand),
/// System-generated fee distribution to block producers
FeeTransfer(FeeTransfer),
/// System-generated block reward for block producer
Coinbase(Coinbase),
}

Expand Down
12 changes: 6 additions & 6 deletions ledger/src/scan_state/transaction_logic/transaction_applied.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use mina_core::constants::ConstraintConstants;
use mina_curves::pasta::Fp;

use crate::{Account, AccountId};

use super::{
signed_command, zkapp_command, Coinbase, FeeTransfer, Transaction, TransactionStatus,
UserCommand, WithStatus,
};
use crate::scan_state::currency::{Amount, Magnitude, Signed};
use crate::{
scan_state::currency::{Amount, Magnitude, Signed},
Account, AccountId,
};
use mina_core::constants::ConstraintConstants;
use mina_curves::pasta::Fp;

pub mod signed_command_applied {
use mina_signer::CompressedPubKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,33 +678,6 @@ fn update_timing_when_no_deduction(
validate_timing(account, Amount::zero(), txn_global_slot)
}

// /// TODO: Move this to the ledger
// /// <https://github.com/MinaProtocol/mina/blob/2ee6e004ba8c6a0541056076aab22ea162f7eb3a/src/lib/mina_ledger/ledger.ml#L311>
// fn get_or_create<L>(
// ledger: &mut L,
// account_id: &AccountId,
// ) -> Result<(AccountState, Account, Address), String>
// where
// L: LedgerIntf,
// {
// let location = ledger
// .get_or_create_account(account_id.clone(), Account::initialize(account_id))
// .map_err(|e| format!("{:?}", e))?;

// let action = match location {
// GetOrCreated::Added(_) => AccountState::Added,
// GetOrCreated::Existed(_) => AccountState::Existed,
// };

// let addr = location.addr();

// let account = ledger
// .get(addr.clone())
// .expect("get_or_create: Account was not found in the ledger after creation");

// Ok((action, account, addr))
// }

fn get_new_accounts<T>(action: AccountState, data: T) -> Option<T> {
match action {
AccountState::Added => Some(data),
Expand Down
10 changes: 5 additions & 5 deletions ledger/src/scan_state/transaction_logic/transaction_witness.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use mina_p2p_messages::v2::MinaStateProtocolStateBodyValueStableV2;

use crate::{scan_state::pending_coinbase::Stack, sparse_ledger::SparseLedger};

use super::{Transaction, TransactionStatus};
use crate::scan_state::currency::Slot;
use crate::{
scan_state::{currency::Slot, pending_coinbase::Stack},
sparse_ledger::SparseLedger,
};
use mina_p2p_messages::v2::MinaStateProtocolStateBodyValueStableV2;

/// <https://github.com/MinaProtocol/mina/blob/436023ba41c43a50458a551b7ef7a9ae61670b25/src/lib/transaction_witness/transaction_witness.ml#L55>
#[derive(Debug)]
Expand Down
32 changes: 10 additions & 22 deletions ledger/src/transaction_pool.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
use backtrace::Backtrace;
use serde::{Deserialize, Serialize};
use std::{
borrow::{Borrow, Cow},
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
};

use itertools::Itertools;
use mina_core::{bug_condition, consensus::ConsensusConstants};
use mina_curves::pasta::Fp;
use mina_p2p_messages::{bigint::BigInt, v2};

use crate::{
scan_state::{
currency::{Amount, Balance, BlockTime, Fee, Magnitude, Nonce, Slot},
Expand All @@ -27,6 +15,16 @@ use crate::{
verifier::{Verifier, VerifierError},
Account, AccountId, BaseLedger, Mask, TokenId, VerificationKey, VerificationKeyWire,
};
use backtrace::Backtrace;
use itertools::Itertools;
use mina_core::{bug_condition, consensus::ConsensusConstants};
use mina_curves::pasta::Fp;
use mina_p2p_messages::{bigint::BigInt, v2};
use serde::{Deserialize, Serialize};
use std::{
borrow::{Borrow, Cow},
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
};

#[derive(Debug, thiserror::Error)]
pub enum TransactionPoolErrors {
Expand Down Expand Up @@ -589,16 +587,6 @@ pub struct IndexedPoolConfig {
slot_tx_end: Option<Slot>,
}

// module Config = struct
// type t =
// { constraint_constants : Genesis_constants.Constraint_constants.t
// ; consensus_constants : Consensus.Constants.t
// ; time_controller : Block_time.Controller.t
// ; slot_tx_end : Mina_numbers.Global_slot_since_hard_fork.t option
// }
// [@@deriving sexp_of, equal, compare]
// end

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct IndexedPool {
/// Transactions valid against the current ledger, indexed by fee per
Expand Down
3 changes: 1 addition & 2 deletions ledger/src/tree.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::{collections::BTreeMap, fmt::Debug, sync::Mutex};

use crate::{
address::Address,
base::AccountIndex,
tree_version::{TreeVersion, V2},
};
use mina_curves::pasta::Fp;
use once_cell::sync::Lazy;
use std::{collections::BTreeMap, fmt::Debug, sync::Mutex};

#[derive(Clone, Debug)]
struct Leaf<T: TreeVersion> {
Expand Down
11 changes: 2 additions & 9 deletions ledger/src/tree_version.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::{fmt::Debug, hash::Hash};

use crate::account::{get_legacy_hash_of, Account, AccountLegacy, TokenId, TokenIdLegacy};
use mina_curves::pasta::Fp;
use poseidon::hash::params::get_merkle_param_for_height;

use crate::account::{get_legacy_hash_of, Account, AccountLegacy, TokenId, TokenIdLegacy};
use std::{fmt::Debug, hash::Hash};

pub trait TreeVersion {
type Account: Debug + Clone;
Expand Down Expand Up @@ -34,14 +32,9 @@ impl TreeVersion for V2 {
}

fn empty_hash_at_height(height: usize) -> Fp {
// let now = redux::Instant::now();

(0..height).fold(Account::empty().hash(), |prev_hash, height| {
Self::hash_node(height, prev_hash, prev_hash)
})
// elog!("empty_hash_at_height={:?} {:?}", height, now.elapsed());

// res
}
}

Expand Down
Loading
Loading