Skip to content

Conversation

@dannywillems
Copy link
Member

Summary

  • Adds new mina-tx-type crate with standalone transaction types for external use
  • Extracts coinbase types (Coinbase, CoinbaseFeeTransfer) with supporting currency types
  • Includes Magnitude trait, Signed<T> wrapper, and impl_number! macro

Details

This PR creates a new crate that provides Mina Protocol transaction types without requiring the full ledger crate dependencies. This allows external projects to work with Mina transactions in a lightweight manner.

Extracted components

Traits:

  • Magnitude - Core numeric operations (simplified, without proof-related methods)
  • MinMax - Min/max value bounds

Types:

  • Sgn - Sign enum (Pos/Neg)
  • Signed<T> - Signed magnitude wrapper
  • Amount - Currency amount type
  • Fee - Transaction fee type
  • Coinbase - Coinbase transaction
  • CoinbaseFeeTransfer - Fee transfer to SNARK worker

Macro:

  • impl_number! - Generates currency types with trait implementations

What was NOT extracted (intentionally)

Proof-related code stays in the ledger crate:

  • to_field() / of_field() methods
  • ToFieldElements, Check, ToInputs trait implementations
  • to_bits() method
  • P2P message conversions

Documentation

Added mina-tx-type/EXTRACTION_ANALYSIS.md with detailed analysis of:

  • All types and traits required for extraction
  • Dependencies and their locations
  • Extraction strategy and rationale

Test plan

  • All 16 unit tests pass (cargo test -p mina-tx-type)
  • Ledger crate compiles unchanged (cargo check -p mina-tree)
  • Formatting passes (make format)

Closes #1824

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

OCaml Reference Validation Results

Repository: https://github.com/MinaProtocol/mina.git
Branch: compatible
Status: ❌ Validation failed

Click to see full validation output
Checking OCaml references against https://github.com/MinaProtocol/mina.git (branch: compatible)
Fetching current commit from compatible...
Current OCaml commit: 75437cafea702d36865da779d43509c02d876f26

Validating references...
========================
✓ VALID: ledger/src/account/account.rs -> src/lib/mina_base/account.ml L:201-224
  ⚠ STALE COMMIT: fc6be4c58091c761f827c858229c2edf9519e941 (current: 75437cafea702d36865da779d43509c02d876f26)
❌ INVALID: ledger/src/scan_state/transaction_logic/for_tests.rs
   Code at L:2285-2285 differs between commit 5da42ccd72e791f164d4d200cf1ce300262873b3 and current branch
   Referenced: https://github.com/MinaProtocol/mina/blob/5da42ccd72e791f164d4d200cf1ce300262873b3/src/lib/transaction_logic/mina_transaction_logic.ml#L2285-L2285
   Current:    https://github.com/MinaProtocol/mina/blob/compatible/src/lib/transaction_logic/mina_transaction_logic.ml#L2285-L2285
❌ INVALID: ledger/src/scan_state/transaction_logic/for_tests.rs
   Code at L:2351-2356 differs between commit 5da42ccd72e791f164d4d200cf1ce300262873b3 and current branch
   Referenced: https://github.com/MinaProtocol/mina/blob/5da42ccd72e791f164d4d200cf1ce300262873b3/src/lib/transaction_logic/mina_transaction_logic.ml#L2351-L2356
   Current:    https://github.com/MinaProtocol/mina/blob/compatible/src/lib/transaction_logic/mina_transaction_logic.ml#L2351-L2356
❌ INVALID: ledger/src/scan_state/transaction_logic/for_tests.rs
   Code at L:2407 differs between commit 5da42ccd72e791f164d4d200cf1ce300262873b3 and current branch
   Referenced: https://github.com/MinaProtocol/mina/blob/5da42ccd72e791f164d4d200cf1ce300262873b3/src/lib/transaction_logic/mina_transaction_logic.ml#L2407-L2407
   Current:    https://github.com/MinaProtocol/mina/blob/compatible/src/lib/transaction_logic/mina_transaction_logic.ml#L2407-L2407
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/transaction_status.ml L:9-51
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/transaction_status.ml L:452-454
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/with_status.ml L:6-10
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/fee_transfer.ml L:76-80
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/fee_transfer.ml L:68-69
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/mina_base/coinbase.ml L:17-21
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/mod.rs -> src/lib/transaction/transaction.ml L:8-11
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/signed_command.rs -> src/lib/mina_base/signed_command_payload.ml L:34-48
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/signed_command.rs -> src/lib/mina_base/stake_delegation.ml L:11-13
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/signed_command.rs -> src/lib/mina_base/signed_command_payload.ml L:179-181
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/signed_command.rs -> src/lib/mina_base/signed_command_payload.ml L:239-243
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: ledger/src/scan_state/transaction_logic/signed_command.rs -> src/lib/mina_base/signed_command_payload.ml L:352-362
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)
✓ VALID: mina-tx-type/src/coinbase.rs -> src/lib/mina_base/coinbase.ml L:17-21
  ⚠ STALE COMMIT: 5da42ccd72e791f164d4d200cf1ce300262873b3 (current: 75437cafea702d36865da779d43509c02d876f26)

Summary
=======
Total references found: 17
Valid references: 14
Invalid references: 3
Stale commits: 14

❌ Validation failed: 3 invalid reference(s) found

This adds a new standalone crate that provides Mina Protocol transaction
types for external use without requiring the full ledger crate.

Extracted types and traits:
- Sgn enum (sign type)
- Magnitude trait (numeric operations)
- MinMax trait (bounds)
- Signed<T> struct (signed magnitude wrapper)
- Amount and Fee types (via impl_number! macro)
- Coinbase and CoinbaseFeeTransfer structs

The extraction excludes proof-related code (to_field, of_field, etc.)
to keep the crate lightweight. The ledger crate continues to use its
own implementations.
@dannywillems dannywillems force-pushed the dw/mina-tx-type-coinbase branch from 60e4851 to 5937ba6 Compare December 9, 2025 22:07
@github-actions
Copy link

github-actions bot commented Dec 9, 2025

✓ Code Reference Verification Passed

All code references in the documentation have been verified successfully!

Total references checked: 1
Valid references: 1

The documentation is in sync with the codebase on the develop branch.

This commit adds the proof-related types needed for the Magnitude
trait's field conversion methods:

- proofs/field.rs: FieldWitness trait, Boolean, CircuitVar, ShiftedValue,
  ShiftingValue, and related types
- proofs/to_field_elements.rs: ToFieldElements trait
- proofs/witness.rs: Check trait and Witness struct

The Magnitude trait now includes to_field() and of_field() methods that
match the ledger crate's implementation.

Dependencies added: ark-ec, ark-ff, kimchi, mina-curves, mina-p2p-messages,
mina-poseidon, poseidon
@dannywillems
Copy link
Member Author

dannywillems commented Dec 9, 2025

Next Steps: Trait Replacement Order

The next step is to replace the traits in the ledger crate with imports from mina-tx-type. Based on the dependency analysis, here's the recommended order:

  1. ToFieldElements ← start here (simplest, no dependencies on other moved traits)
  2. Check (depends on FieldWitness and Witness)
  3. ShiftingValue / ShiftedValue (used by FieldWitness)
  4. Witness (depends on Check, ToFieldElements, FieldWitness)
  5. FieldWitness (depends on all the above - do last)
  6. Boolean / CircuitVar (depend on FieldWitness, Check, Witness)

Why start with ToFieldElements?

  • Minimal dependencies - It only depends on ark_ff::Field, no circular dependencies
  • Simple trait - Just one required method (to_field_elements) and one provided method
  • Widely used - It's a foundational trait that other types implement, so replacing it early validates the approach
  • No dependency on other moved traits - Unlike FieldWitness which depends on Check, ToFieldElements, ShiftingValue, etc.

Important

When replacing traits, we must ensure that the code in mina-tx-type is exactly the same as the code being replaced in the ledger crate. This guarantees that the replacement is a pure refactoring with no behavioral changes.

@dannywillems
Copy link
Member Author

ToFieldElements Migration Status

I attempted to replace the ToFieldElements trait in the ledger crate with an import from mina-tx-type, but encountered Rust's orphan rule limitations.

What was accomplished

In mina-tx-type:

  • Added comprehensive ToFieldElements implementations for generic types ((), Vec<T>, Box<[T]>, Fp, Fq, Cow<'_, T>, [T; N], ByteString, GroupAffine<F>, &[u8], &[bool], bool, u64, u32, PointEvaluations<T>, ProofEvaluations<T>, (A, B), &T, Boolean, CircuitVar<Boolean>)
  • Added implementations for mina_signer::CompressedPubKey, mina_signer::Signature, mina_signer::PubKey, v2::MinaBaseProtocolConstantsCheckedValueStableV1
  • Added helper functions field_to_bits and field_of_bits

In ledger:

  • Added documentation explaining the migration plan and orphan rule limitations

Why full replacement wasn't possible

Rust's orphan rules prevent implementing a foreign trait for combinations involving foreign types. Since both ToFieldElements (from mina-tx-type) and types like Fp, Fq, Option<T>, tuples etc. would be "foreign" to the ledger crate, the compiler rejects these implementations.

Steps needed to complete the migration

  1. Replace local type definitions with imports from mina-tx-type:

    • FieldWitness trait and impls
    • CircuitVar<T> enum
    • Boolean enum
    • GroupAffine<F> type alias

    These are defined in ledger/src/proofs/field.rs and need to be imported from mina_tx_type::proofs::field instead.

  2. Move remaining implementations to mina-tx-type:
    Once the types are shared, the following implementations can be moved:

    • impl ToFieldElements for OpeningProof<Vesta> (requires poly-commitment dep)
    • impl ToFieldElements for ProverCommitments<Vesta> (requires kimchi dep)
    • Various tuple implementations like (&SetOrKeep<T>, F)
  3. Replace trait import:
    Finally, replace pub trait ToFieldElements with:
    pub use mina_tx_type::ToFieldElements;

See the documentation comments in ledger/src/proofs/to_field_elements.rs and ledger/src/proofs/field.rs for more details.

- Add comprehensive ToFieldElements implementations to mina-tx-type for
  generic types (Vec, Box, arrays, tuples, primitives) and external types
  (mina_signer, mina_p2p_messages)
- Add field_to_bits and field_of_bits helper functions
- Add migration documentation to ledger/src/proofs explaining orphan rule
  limitations and steps needed to complete trait replacement
- Document future migration to snarky-rs and pickles-rs crates (issues
  #1762, #1763)
Extend the impl_number macro in mina-tx-type to generate ToFieldElements
and Check trait implementations for currency types (Amount, Fee). This
matches the implementations in the ledger crate.

Note: The Check implementation is simplified as it doesn't include the
full range checking (to_field_checked_prime) which depends on the
transaction module. This will be properly implemented when snarky-rs is
available.
@dannywillems
Copy link
Member Author

Migration Plan: Using mina-tx-type Types in Ledger

Coinbase Types Migration Analysis

I analyzed whether the Coinbase and CoinbaseFeeTransfer types from mina-tx-type can replace the ones in ledger/src/scan_state/transaction_logic/mod.rs.

Current Status: Blocked

The ledger versions have additional methods that depend on ledger-specific types:

CoinbaseFeeTransfer ledger-specific methods:

  • receiver() -> returns AccountId (ledger type)

Coinbase ledger-specific methods:

  • expected_supply_increase() -> returns Result<Amount, String> (uses ledger's Amount)
  • fee_excess() -> returns FeeExcess (ledger type)
  • receiver() -> returns AccountId (ledger type)
  • account_access_statuses() -> uses TransactionStatus, zkapp_command::AccessedOrNot (ledger types)

Blocking Dependencies

To replace Coinbase types in ledger, the following types need to be extracted to mina-tx-type first:

  1. AccountId - Used for receiver identification
  2. FeeExcess - Used for fee calculations
  3. TransactionStatus - Used for transaction state tracking
  4. zkapp_command::AccessedOrNot - Used for account access tracking

Recommended Migration Steps

  1. Phase 1: Extract AccountId to mina-tx-type (likely depends on TokenId extraction)
  2. Phase 2: Extract FeeExcess and related fee calculation types
  3. Phase 3: Extract TransactionStatus and related enums
  4. Phase 4: Replace ledger's Coinbase types with imports from mina-tx-type

Alternative Approach

If full extraction is not desired, we could:

  1. Keep core struct definitions in mina-tx-type (as done now)
  2. Use extension traits in ledger to add ledger-specific methods
  3. This would require re-exporting the types or using newtype wrappers

This PR establishes the foundation by defining the core Coinbase and CoinbaseFeeTransfer structs in mina-tx-type. The ledger crate can adopt these types incrementally as dependencies are extracted.

@dannywillems
Copy link
Member Author

Update: Coinbase Type Migration Blocked by Currency Types

After attempting to use mina-tx-type::Coinbase in the ledger crate, I identified a fundamental blocker:

The Problem

The Coinbase and CoinbaseFeeTransfer types in mina-tx-type use:

// mina-tx-type/src/coinbase.rs
use crate::currency::{Amount, Fee};  // mina_tx_type::currency types

While the ledger crate uses:

// ledger/src/scan_state/currency.rs
pub struct Amount(pub u64);  // Different type
pub struct Fee(pub u64);     // Different type

These are incompatible types. Even though they have the same structure, Rust treats them as completely different types.

Why This Matters

All existing code in ledger that works with Coinbase expects:

  • Coinbase.amount to be ledger::Amount
  • CoinbaseFeeTransfer.fee to be ledger::Fee

Simply importing mina-tx-type::Coinbase would break compilation across ~20+ files.

Required Migration Path

To properly migrate Coinbase types, we must first:

  1. Extract Currency Types: Move Amount, Fee, Signed<T>, Magnitude, MinMax, Sgn from ledger/src/scan_state/currency.rs to mina-tx-type

  2. Update Ledger Currency Imports: Replace ledger's currency module with re-exports from mina-tx-type:

    // ledger/src/scan_state/currency.rs
    pub use mina_tx_type::currency::*;
    // Keep ledger-specific extensions
  3. Migrate Coinbase: Once currency types are shared, the Coinbase types can be imported from mina-tx-type

  4. Add Ledger Extensions: Create extension traits in ledger for methods requiring ledger-specific types (AccountId, FeeExcess, etc.)

Complexity Assessment

The currency types are used extensively throughout the ledger crate. This migration would affect:

  • scan_state/currency.rs (core definitions)
  • scan_state/transaction_logic/ (multiple files)
  • staged_ledger/ (multiple files)
  • proofs/ (field conversions)
  • External conversions (conv.rs)
  • Test files

Recommendation

This PR establishes mina-tx-type with independent type definitions. The migration to shared types should be done in a follow-up PR with dedicated review, as it will be a large change affecting many files.

The current PR can be merged as-is - it provides a clean foundation for future migration.

@dannywillems
Copy link
Member Author

Decision: Keep Currency Types Separate for Now

After further analysis, migrating Amount and Fee from ledger to mina-tx-type would require:

  1. Moving the impl_number! macro (or a subset of it)
  2. Moving the Magnitude, MinMax, Sgn, Signed<T> types
  3. Handling ledger-specific dependencies:
    • crate::proofs::transaction::Check
    • crate::proofs::to_field_elements::ToFieldElements
    • crate::proofs::transaction::scalar_challenge::to_field_checked_prime
    • crate::ToInputs

This is a significant refactoring effort that would affect many files across the ledger crate.

Current State

This PR establishes mina-tx-type with:

  • Independent Amount and Fee types (same structure as ledger's)
  • Coinbase and CoinbaseFeeTransfer types
  • Basic proof-related traits (ToFieldElements, Check, Witness, FieldWitness)

Future Migration Path

The types in mina-tx-type serve as the target canonical definitions. Migration will happen incrementally:

  1. Phase 1 (this PR): Define core types in mina-tx-type
  2. Phase 2: Migrate currency types (requires moving ToInputs, adapting proof traits)
  3. Phase 3: Replace ledger's Coinbase types with imports from mina-tx-type
  4. Phase 4: Add extension traits in ledger for ledger-specific methods

Recommendation

Merge this PR to establish the foundation. The actual migration should be done in dedicated follow-up PRs with proper testing and review due to the scope of changes required.

Add mina-tx-type workspace dependency to the ledger crate to prepare
for future migration of shared types. The actual migration of Coinbase
and currency types will be done in follow-up PRs due to the extensive
changes required.
Migrate Amount and Fee types from ledger's scan_state/currency.rs to
use the types defined in mina-tx-type crate. This involves:

- Re-exporting Amount, Fee, Magnitude, MagnitudeFieldExt, MinMax, Sgn,
  and Signed from mina-tx-type in ledger's currency module
- Creating extension traits to work around Rust's orphan rules:
  - AmountFeeFieldExt<F> for field conversion methods
  - ToCheckedExt<F> and SignedToCheckedExt<F,T> for checked conversions
  - SignedExt<T> for random generation
  - SgnExt for sign field conversion
- Splitting impl_nat! macro into impl_nat_32! and impl_nat_64! variants
  to handle different bit widths properly
- Adding inner_to_field and inner_of_field methods to CheckedCurrency
  and CheckedNat traits for field conversions
- Updating ForZkappCheck trait to use zkapp_to_field method
- Adding necessary imports across affected files

This is part of the effort to extract common transaction types into the
mina-tx-type crate for reuse across the codebase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Extract coinbase transaction types into mina-tx-type crate

2 participants