Skip to content

Commit 9952ccd

Browse files
committed
mina-tx-type: add N type, ToChecked, SignedRandExt, SlotRandExt
Moves additional types and traits from ledger to mina-tx-type: - N type: Generic 64-bit number for proof computations - ToChecked trait: Convert currency types to checked circuit forms - SignedRandExt trait: Random signed value generation - SlotRandExt trait: Random slot generation for tests Also consolidates ToInputs implementations in ledger/src/hash.rs using the impl_to_inputs macro for currency types. Note: ToInputs trait cannot be moved to mina-tx-type due to Rust's orphan rule - ledger needs to implement ToInputs for foreign types. Issue: #1665
1 parent 3d2edae commit 9952ccd

File tree

4 files changed

+250
-221
lines changed

4 files changed

+250
-221
lines changed

ledger/src/hash.rs

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
1+
//! Hash computation types and traits for the ledger.
2+
//!
3+
//! This module provides the [`ToInputs`] trait for converting types to hash
4+
//! inputs, enabling Poseidon hash computation for transactions and other
5+
//! protocol data structures.
6+
17
use mina_curves::pasta::Fp;
28
use mina_signer::CompressedPubKey;
39

410
use crate::{proofs::witness::Witness, scan_state::currency};
511
use poseidon::hash::{hash_with_kimchi, Inputs, LazyParam};
612

13+
/// Trait for types that can be converted to hash inputs.
14+
///
15+
/// This trait is the foundation for computing Poseidon hashes of protocol
16+
/// data structures. Types implementing this trait can be hashed using
17+
/// the Mina-compatible Kimchi hash function.
718
pub trait ToInputs {
19+
/// Appends the hash inputs for this value to the given input buffer.
820
fn to_inputs(&self, inputs: &mut Inputs);
921

22+
/// Creates a new input buffer containing this value's hash inputs.
1023
fn to_inputs_owned(&self) -> Inputs {
1124
let mut inputs = Inputs::new();
1225
self.to_inputs(&mut inputs);
1326
inputs
1427
}
1528

29+
/// Computes the Poseidon hash of this value with the given parameter.
1630
fn hash_with_param(&self, param: &LazyParam) -> Fp {
1731
let mut inputs = Inputs::new();
1832
self.to_inputs(&mut inputs);
1933
hash_with_kimchi(param, &inputs.to_fields())
2034
}
2135

36+
/// Computes the Poseidon hash with circuit witness generation.
2237
fn checked_hash_with_param(&self, param: &LazyParam, w: &mut Witness<Fp>) -> Fp {
2338
use crate::proofs::transaction::transaction_snark::checked_hash;
2439

@@ -73,7 +88,9 @@ where
7388
}
7489
}
7590

91+
/// Extension trait for appending [`ToInputs`] values to an input buffer.
7692
pub trait AppendToInputs {
93+
/// Appends a value implementing [`ToInputs`] to this input buffer.
7794
fn append<T>(&mut self, value: &T)
7895
where
7996
T: ToInputs;
@@ -88,36 +105,37 @@ impl AppendToInputs for Inputs {
88105
}
89106
}
90107

91-
#[cfg(test)]
92-
mod tests {
93-
use o1_utils::FieldHelpers;
94-
95-
use poseidon::hash::param_to_field;
96-
#[cfg(target_family = "wasm")]
97-
use wasm_bindgen_test::wasm_bindgen_test as test;
108+
// ============================================================================
109+
// ToInputs implementations for currency types
110+
// ============================================================================
111+
112+
macro_rules! impl_to_inputs {
113+
(32: { $($name32:ident,)* }, 64: { $($name64:ident,)* },) => {
114+
$(
115+
impl ToInputs for currency::$name32 {
116+
fn to_inputs(&self, inputs: &mut Inputs) {
117+
inputs.append_u32(self.as_u32());
118+
}
119+
}
120+
)*
121+
$(
122+
impl ToInputs for currency::$name64 {
123+
fn to_inputs(&self, inputs: &mut Inputs) {
124+
inputs.append_u64(self.as_u64());
125+
}
126+
}
127+
)*
128+
};
129+
}
98130

99-
use super::*;
131+
impl_to_inputs!(
132+
32: { Length, Slot, Nonce, Index, SlotSpan, TxnVersion, Epoch, },
133+
64: { Amount, Balance, Fee, BlockTime, BlockTimeSpan, N, },
134+
);
100135

101-
#[test]
102-
fn test_param() {
103-
for (s, hex) in [
104-
(
105-
"",
106-
"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a000000000000000000000000",
107-
),
108-
(
109-
"hello",
110-
"68656c6c6f2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a000000000000000000000000",
111-
),
112-
(
113-
"aaaaaaaaaaaaaaaaaaaa",
114-
"6161616161616161616161616161616161616161000000000000000000000000",
115-
),
116-
] {
117-
let field = param_to_field(s);
118-
assert_eq!(field.to_hex(), hex);
119-
}
120-
}
136+
#[cfg(test)]
137+
mod tests {
138+
use poseidon::hash::Inputs;
121139

122140
#[test]
123141
fn test_inputs() {
@@ -132,31 +150,5 @@ mod tests {
132150

133151
elog!("INPUTS={:?}", inputs);
134152
elog!("FIELDS={:?}", inputs.to_fields());
135-
136-
// // Self::timing
137-
// match self.timing {
138-
// Timing::Untimed => {
139-
// roi.append_bool(false);
140-
// roi.append_u64(0); // initial_minimum_balance
141-
// roi.append_u32(0); // cliff_time
142-
// roi.append_u64(0); // cliff_amount
143-
// roi.append_u32(1); // vesting_period
144-
// roi.append_u64(0); // vesting_increment
145-
// }
146-
// Timing::Timed {
147-
// initial_minimum_balance,
148-
// cliff_time,
149-
// cliff_amount,
150-
// vesting_period,
151-
// vesting_increment,
152-
// } => {
153-
// roi.append_bool(true);
154-
// roi.append_u64(initial_minimum_balance);
155-
// roi.append_u32(cliff_time);
156-
// roi.append_u64(cliff_amount);
157-
// roi.append_u32(vesting_period);
158-
// roi.append_u64(vesting_increment);
159-
// }
160-
// }
161153
}
162154
}

ledger/src/scan_state/currency.rs

Lines changed: 12 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Currency types with ledger-specific implementations.
22
//!
33
//! Re-exports types from [`mina_tx_type::currency`] and adds implementations
4-
//! for ledger-specific traits like [`ToFieldElements`], [`Check`], and [`ToInputs`].
5-
6-
use rand::Rng;
4+
//! for ledger-specific traits like [`ToFieldElements`] and [`Check`].
5+
//!
6+
//! Note: [`ToInputs`] implementations are provided by mina-tx-type.
77
88
use crate::proofs::{
99
field::FieldWitness, to_field_elements::ToFieldElements, transaction::Check, witness::Witness,
@@ -12,163 +12,14 @@ use crate::proofs::{
1212
// Re-export all types from mina-tx-type
1313
pub use mina_tx_type::currency::{
1414
Amount, Balance, BlockTime, BlockTimeSpan, Epoch, Fee, FieldLike, Index, Length, Magnitude,
15-
MinMax, Nonce, Sgn, Signed, Slot, SlotSpan, TxnVersion,
15+
MinMax, Nonce, Sgn, Signed, SignedRandExt, Slot, SlotRandExt, SlotSpan, ToChecked, TxnVersion,
16+
N,
1617
};
1718

1819
// ============================================================================
19-
// Extension traits for ledger-specific functionality
20-
// ============================================================================
21-
22-
/// Extension trait for random generation of Signed values.
23-
pub trait SignedRandExt<T: Magnitude> {
24-
fn gen() -> Signed<T>;
25-
}
26-
27-
impl<T> SignedRandExt<T> for Signed<T>
28-
where
29-
T: Magnitude + PartialOrd + Ord + Clone,
30-
rand::distributions::Standard: rand::distributions::Distribution<T>,
31-
{
32-
fn gen() -> Signed<T> {
33-
let mut rng = rand::thread_rng();
34-
35-
let magnitude: T = rng.gen();
36-
let sgn = if rng.gen::<bool>() {
37-
Sgn::Pos
38-
} else {
39-
Sgn::Neg
40-
};
41-
42-
Signed::create(magnitude, sgn)
43-
}
44-
}
45-
46-
/// Extension trait for Slot random generation.
47-
pub trait SlotRandExt {
48-
fn gen_small() -> Slot;
49-
}
50-
51-
impl SlotRandExt for Slot {
52-
fn gen_small() -> Slot {
53-
let mut rng = rand::thread_rng();
54-
Slot::from_u32(rng.gen::<u32>() % 10_000)
55-
}
56-
}
57-
58-
// ============================================================================
59-
// Ledger-specific type: N (generic number)
20+
// Ledger-specific trait implementations for N
6021
// ============================================================================
6122

62-
/// A generic 64-bit number type for proof computations.
63-
#[derive(
64-
Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize,
65-
)]
66-
pub struct N(pub(super) u64);
67-
68-
impl std::fmt::Debug for N {
69-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70-
f.write_fmt(format_args!("N({:?})", self.0))
71-
}
72-
}
73-
74-
impl Magnitude for N {
75-
const NBITS: usize = 64;
76-
77-
fn zero() -> Self {
78-
Self(0)
79-
}
80-
81-
fn is_zero(&self) -> bool {
82-
self.0 == 0
83-
}
84-
85-
fn wrapping_add(&self, rhs: &Self) -> Self {
86-
Self(self.0.wrapping_add(rhs.0))
87-
}
88-
89-
fn wrapping_mul(&self, rhs: &Self) -> Self {
90-
Self(self.0.wrapping_mul(rhs.0))
91-
}
92-
93-
fn wrapping_sub(&self, rhs: &Self) -> Self {
94-
Self(self.0.wrapping_sub(rhs.0))
95-
}
96-
97-
fn checked_add(&self, rhs: &Self) -> Option<Self> {
98-
self.0.checked_add(rhs.0).map(Self)
99-
}
100-
101-
fn checked_mul(&self, rhs: &Self) -> Option<Self> {
102-
self.0.checked_mul(rhs.0).map(Self)
103-
}
104-
105-
fn checked_sub(&self, rhs: &Self) -> Option<Self> {
106-
self.0.checked_sub(rhs.0).map(Self)
107-
}
108-
109-
fn checked_div(&self, rhs: &Self) -> Option<Self> {
110-
self.0.checked_div(rhs.0).map(Self)
111-
}
112-
113-
fn checked_rem(&self, rhs: &Self) -> Option<Self> {
114-
self.0.checked_rem(rhs.0).map(Self)
115-
}
116-
117-
fn abs_diff(&self, rhs: &Self) -> Self {
118-
Self(self.0.abs_diff(rhs.0))
119-
}
120-
121-
fn to_field<F: FieldLike>(&self) -> F {
122-
F::from(self.0)
123-
}
124-
125-
fn of_field<F: FieldLike>(field: F) -> Self {
126-
use ark_ff::BigInteger256;
127-
let bigint: BigInteger256 = field.into();
128-
Self(bigint.0[0])
129-
}
130-
}
131-
132-
impl MinMax for N {
133-
fn min() -> Self {
134-
Self(0)
135-
}
136-
fn max() -> Self {
137-
Self(u64::MAX)
138-
}
139-
}
140-
141-
impl N {
142-
pub const NBITS: usize = 64;
143-
144-
pub fn as_u64(&self) -> u64 {
145-
self.0
146-
}
147-
148-
pub const fn from_u64(value: u64) -> Self {
149-
Self(value)
150-
}
151-
152-
pub const fn scale(&self, n: u64) -> Option<Self> {
153-
match self.0.checked_mul(n) {
154-
Some(n) => Some(Self(n)),
155-
None => None,
156-
}
157-
}
158-
}
159-
160-
impl rand::distributions::Distribution<N> for rand::distributions::Standard {
161-
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> N {
162-
N(rng.next_u64())
163-
}
164-
}
165-
166-
impl crate::ToInputs for N {
167-
fn to_inputs(&self, inputs: &mut poseidon::hash::Inputs) {
168-
inputs.append_u64(self.0);
169-
}
170-
}
171-
17223
impl<F: FieldWitness> ToFieldElements<F> for N {
17324
fn to_field_elements(&self, fields: &mut Vec<F>) {
17425
fields.push(self.to_field());
@@ -186,21 +37,17 @@ impl<F: FieldWitness> Check<F> for N {
18637
}
18738

18839
// ============================================================================
189-
// Macro for implementing ledger traits on currency types
40+
// Macro for implementing ledger-specific traits on currency types
19041
// ============================================================================
19142

43+
/// Macro to implement ToFieldElements and Check for currency types.
44+
/// ToInputs implementations are provided by mina-tx-type.
19245
macro_rules! impl_ledger_traits {
19346
(32: { $($name32:ident,)* }, 64: { $($name64:ident,)* },) => {
194-
$(impl_ledger_traits!({$name32, u32, as_u32, append_u32},);)*
195-
$(impl_ledger_traits!({$name64, u64, as_u64, append_u64},);)*
47+
$(impl_ledger_traits!({$name32, u32, as_u32},);)*
48+
$(impl_ledger_traits!({$name64, u64, as_u64},);)*
19649
};
197-
($({ $name:ident, $inner:ty, $as_name:ident, $append_name:ident },)*) => ($(
198-
impl crate::ToInputs for $name {
199-
fn to_inputs(&self, inputs: &mut poseidon::hash::Inputs) {
200-
inputs.$append_name(self.$as_name());
201-
}
202-
}
203-
50+
($({ $name:ident, $inner:ty, $as_name:ident },)*) => ($(
20451
impl<F: FieldWitness> ToFieldElements<F> for $name {
20552
fn to_field_elements(&self, fields: &mut Vec<F>) {
20653
fields.push(self.to_field());

mina-tx-type/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,3 @@ mina-p2p-messages = { workspace = true }
1616
mina-signer = { workspace = true }
1717
rand = { workspace = true }
1818
serde = { workspace = true }
19-
20-
[dev-dependencies]

0 commit comments

Comments
 (0)