Skip to content

Commit 8b34cb8

Browse files
authored
Merge pull request #1541 from o1-labs/dw/continue-doc-zkapps
Transaction logic: continue adding docs + tests for invariants
2 parents fc58bc1 + f0cf40e commit 8b34cb8

12 files changed

+1685
-71
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4646
- **mina-node-account**: move tests into `node/account/tests`, document the
4747
library and run the tests in CI
4848
([#1540](https://github.com/o1-labs/mina-rust/pull/1540)).
49+
- **Ledger**: add tests to verify some properties transaction application
50+
should have on the ledger. Also, document the different types of transactions
51+
that can be used to modify the ledger
52+
([#1541](https://github.com/o1-labs/mina-rust/pull/1541))
4953

5054
### Changed
5155

ledger/src/scan_state/transaction_logic/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,10 +1051,51 @@ impl GenericTransaction for Transaction {
10511051
}
10521052
}
10531053

1054+
/// Top-level transaction type representing all possible transactions in the
1055+
/// Mina protocol.
1056+
///
1057+
/// Transactions in Mina fall into two categories:
1058+
///
1059+
/// ## User-initiated transactions
1060+
///
1061+
/// - [`Command`](Transaction::Command): User-initiated transactions that can be
1062+
/// either signed commands (payments and stake delegations) or zkApp commands
1063+
/// (complex multi-account zero-knowledge operations). These transactions are
1064+
/// submitted by users, require signatures, and pay fees to block producers.
1065+
///
1066+
/// ## Protocol transactions
1067+
///
1068+
/// - [`FeeTransfer`](Transaction::FeeTransfer): System-generated transaction
1069+
/// that distributes collected transaction fees to block producers. Created
1070+
/// automatically during block production and does not require user signatures.
1071+
/// - [`Coinbase`](Transaction::Coinbase): System-generated transaction that
1072+
/// rewards block producers for successfully producing a block. May include an
1073+
/// optional fee transfer component to split rewards.
1074+
///
1075+
/// # Transaction processing
1076+
///
1077+
/// All transactions are processed through the two-phase application model
1078+
/// ([`apply_transaction_first_pass`] and [`apply_transaction_second_pass`]) to
1079+
/// enable efficient proof generation. Protocol transactions (fee transfers and
1080+
/// coinbase) complete entirely in the first pass, while user commands may
1081+
/// require both passes.
1082+
///
1083+
/// # Serialization
1084+
///
1085+
/// The type uses [`derive_more::From`] for automatic conversion from variant
1086+
/// types and implements conversion to/from the p2p wire format
1087+
/// [`MinaTransactionTransactionStableV2`].
1088+
///
1089+
/// OCaml reference: src/lib/transaction/transaction.ml L:8-11
1090+
/// Commit: 5da42ccd72e791f164d4d200cf1ce300262873b3
1091+
/// Last verified: 2025-10-10
10541092
#[derive(Clone, Debug, derive_more::From)]
10551093
pub enum Transaction {
1094+
/// User-initiated transaction: signed command or zkApp command
10561095
Command(UserCommand),
1096+
/// System-generated fee distribution to block producers
10571097
FeeTransfer(FeeTransfer),
1098+
/// System-generated block reward for block producer
10581099
Coinbase(Coinbase),
10591100
}
10601101

ledger/src/scan_state/transaction_logic/transaction_applied.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use mina_core::constants::ConstraintConstants;
2-
use mina_curves::pasta::Fp;
3-
4-
use crate::{Account, AccountId};
5-
61
use super::{
72
signed_command, zkapp_command, Coinbase, FeeTransfer, Transaction, TransactionStatus,
83
UserCommand, WithStatus,
94
};
10-
use crate::scan_state::currency::{Amount, Magnitude, Signed};
5+
use crate::{
6+
scan_state::currency::{Amount, Magnitude, Signed},
7+
Account, AccountId,
8+
};
9+
use mina_core::constants::ConstraintConstants;
10+
use mina_curves::pasta::Fp;
1111

1212
pub mod signed_command_applied {
1313
use mina_signer::CompressedPubKey;

ledger/src/scan_state/transaction_logic/transaction_partially_applied.rs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -678,33 +678,6 @@ fn update_timing_when_no_deduction(
678678
validate_timing(account, Amount::zero(), txn_global_slot)
679679
}
680680

681-
// /// TODO: Move this to the ledger
682-
// /// <https://github.com/MinaProtocol/mina/blob/2ee6e004ba8c6a0541056076aab22ea162f7eb3a/src/lib/mina_ledger/ledger.ml#L311>
683-
// fn get_or_create<L>(
684-
// ledger: &mut L,
685-
// account_id: &AccountId,
686-
// ) -> Result<(AccountState, Account, Address), String>
687-
// where
688-
// L: LedgerIntf,
689-
// {
690-
// let location = ledger
691-
// .get_or_create_account(account_id.clone(), Account::initialize(account_id))
692-
// .map_err(|e| format!("{:?}", e))?;
693-
694-
// let action = match location {
695-
// GetOrCreated::Added(_) => AccountState::Added,
696-
// GetOrCreated::Existed(_) => AccountState::Existed,
697-
// };
698-
699-
// let addr = location.addr();
700-
701-
// let account = ledger
702-
// .get(addr.clone())
703-
// .expect("get_or_create: Account was not found in the ledger after creation");
704-
705-
// Ok((action, account, addr))
706-
// }
707-
708681
fn get_new_accounts<T>(action: AccountState, data: T) -> Option<T> {
709682
match action {
710683
AccountState::Added => Some(data),

ledger/src/scan_state/transaction_logic/transaction_witness.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use mina_p2p_messages::v2::MinaStateProtocolStateBodyValueStableV2;
2-
3-
use crate::{scan_state::pending_coinbase::Stack, sparse_ledger::SparseLedger};
4-
51
use super::{Transaction, TransactionStatus};
6-
use crate::scan_state::currency::Slot;
2+
use crate::{
3+
scan_state::{currency::Slot, pending_coinbase::Stack},
4+
sparse_ledger::SparseLedger,
5+
};
6+
use mina_p2p_messages::v2::MinaStateProtocolStateBodyValueStableV2;
77

88
/// <https://github.com/MinaProtocol/mina/blob/436023ba41c43a50458a551b7ef7a9ae61670b25/src/lib/transaction_witness/transaction_witness.ml#L55>
99
#[derive(Debug)]

ledger/src/transaction_pool.rs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
use backtrace::Backtrace;
2-
use serde::{Deserialize, Serialize};
3-
use std::{
4-
borrow::{Borrow, Cow},
5-
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
6-
};
7-
8-
use itertools::Itertools;
9-
use mina_core::{bug_condition, consensus::ConsensusConstants};
10-
use mina_curves::pasta::Fp;
11-
use mina_p2p_messages::{bigint::BigInt, v2};
12-
131
use crate::{
142
scan_state::{
153
currency::{Amount, Balance, BlockTime, Fee, Magnitude, Nonce, Slot},
@@ -27,6 +15,16 @@ use crate::{
2715
verifier::{Verifier, VerifierError},
2816
Account, AccountId, BaseLedger, Mask, TokenId, VerificationKey, VerificationKeyWire,
2917
};
18+
use backtrace::Backtrace;
19+
use itertools::Itertools;
20+
use mina_core::{bug_condition, consensus::ConsensusConstants};
21+
use mina_curves::pasta::Fp;
22+
use mina_p2p_messages::{bigint::BigInt, v2};
23+
use serde::{Deserialize, Serialize};
24+
use std::{
25+
borrow::{Borrow, Cow},
26+
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
27+
};
3028

3129
#[derive(Debug, thiserror::Error)]
3230
pub enum TransactionPoolErrors {
@@ -589,16 +587,6 @@ pub struct IndexedPoolConfig {
589587
slot_tx_end: Option<Slot>,
590588
}
591589

592-
// module Config = struct
593-
// type t =
594-
// { constraint_constants : Genesis_constants.Constraint_constants.t
595-
// ; consensus_constants : Consensus.Constants.t
596-
// ; time_controller : Block_time.Controller.t
597-
// ; slot_tx_end : Mina_numbers.Global_slot_since_hard_fork.t option
598-
// }
599-
// [@@deriving sexp_of, equal, compare]
600-
// end
601-
602590
#[derive(Clone, Debug, Serialize, Deserialize)]
603591
pub struct IndexedPool {
604592
/// Transactions valid against the current ledger, indexed by fee per

ledger/src/tree.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use std::{collections::BTreeMap, fmt::Debug, sync::Mutex};
2-
31
use crate::{
42
address::Address,
53
base::AccountIndex,
64
tree_version::{TreeVersion, V2},
75
};
86
use mina_curves::pasta::Fp;
97
use once_cell::sync::Lazy;
8+
use std::{collections::BTreeMap, fmt::Debug, sync::Mutex};
109

1110
#[derive(Clone, Debug)]
1211
struct Leaf<T: TreeVersion> {

ledger/src/tree_version.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
use std::{fmt::Debug, hash::Hash};
2-
1+
use crate::account::{get_legacy_hash_of, Account, AccountLegacy, TokenId, TokenIdLegacy};
32
use mina_curves::pasta::Fp;
43
use poseidon::hash::params::get_merkle_param_for_height;
5-
6-
use crate::account::{get_legacy_hash_of, Account, AccountLegacy, TokenId, TokenIdLegacy};
4+
use std::{fmt::Debug, hash::Hash};
75

86
pub trait TreeVersion {
97
type Account: Debug + Clone;
@@ -34,14 +32,9 @@ impl TreeVersion for V2 {
3432
}
3533

3634
fn empty_hash_at_height(height: usize) -> Fp {
37-
// let now = redux::Instant::now();
38-
3935
(0..height).fold(Account::empty().hash(), |prev_hash, height| {
4036
Self::hash_node(height, prev_hash, prev_hash)
4137
})
42-
// elog!("empty_hash_at_height={:?} {:?}", height, now.elapsed());
43-
44-
// res
4538
}
4639
}
4740

0 commit comments

Comments
 (0)