add conversion to/from bytes

This commit is contained in:
Balazs Komuves 2026-01-23 19:37:04 +01:00
parent 012ab9f5cc
commit 453eb12deb
No known key found for this signature in database
GPG Key ID: F63B7AEF18435562
5 changed files with 133 additions and 1 deletions

View File

@ -21,6 +21,6 @@ Currently, only Poseidon2 with `t=3` is implemented.
- [ ] benchmark RISC-V cycles
- [ ] add more Poseidon2 state widths (not just `t=3`)
- [ ] implement `circomlib`-compatible Poseidon
- [ ] add a test-suite; in particular, more complete testing of the field operations
- [ ] add a 64 bit version
- [ ] more complete testing of the field operations
- [ ] further optimizations

View File

@ -163,6 +163,26 @@ fn main() {
BigInt::is_lt_prime(&c) );
*/
{
println!("");
println!("conversion to/from bytes");
let a = FELT1;
let xs = Felt::to_le_bytes(&a);
let b = Felt::unsafe_from_le_bytes(&xs);
println!("a = {}",a);
println!("b = {}",b);
println!("le = {:?}",xs);
}
{
let a = FELT2;
let ys = Felt::to_be_bytes(&a);
let b = Felt::unsafe_from_be_bytes(&ys);
println!("a = {}",a);
println!("b = {}",b);
println!("be = {:?}",ys);
}
//----------------------------------------------------------------------------
}

View File

@ -61,6 +61,59 @@ impl<const N: usize> BigInt<N> {
BigInt(ls)
}
//------------------------------------
// conversion to/from bytes
pub fn to_le_bytes(big: &BigInt<N>) -> [u8; 4*N] {
let mut buf : [u8; 4*N] = [0; 4*N];
for i in 0..N {
let xs: [u8; 4] = big.0[i].to_le_bytes();
let k = 4*i;
for j in 0..4 {
buf[k + j] = xs[j];
}
}
buf
}
pub fn from_le_bytes(buf : &[u8; 4*N]) -> BigInt<N> {
let mut ws: [u32; N] = [0; N];
for i in 0..N {
let k = 4*i;
let mut xs: [u8; 4] = [0; 4];
for j in 0..4 { xs[j] = buf[k+j]; } // stupid rust...
let w: u32 = u32::from_le_bytes(xs);
ws[i] = w;
}
BigInt(ws)
}
pub fn to_be_bytes(big: &BigInt<N>) -> [u8; 4*N] {
let mut buf : [u8; 4*N] = [0; 4*N];
for i in 0..N {
let xs: [u8; 4] = big.0[N-1-i].to_be_bytes();
let k = 4*i;
for j in 0..4 {
buf[k + j] = xs[j];
}
}
buf
}
pub fn from_be_bytes(buf : &[u8; 4*N]) -> BigInt<N> {
let mut ws: [u32; N] = [0; N];
for i in 0..N {
let k = 4*i;
let mut xs: [u8; 4] = [0; 4];
for j in 0..4 { xs[j] = buf[k+j]; } // stupid rust...
let w: u32 = u32::from_be_bytes(xs);
ws[N-1-i] = w;
}
BigInt(ws)
}
//------------------------------------
pub fn truncate1(big : &BigInt<{N+1}>) -> BigInt<N> {
// let small: [u32; N] = &big.limbs[0..N];
let mut small: [u32; N] = [0; N];
@ -78,6 +131,9 @@ impl<const N: usize> BigInt<N> {
BigInt(xs)
}
//------------------------------------
// comparison
pub fn is_zero(big: &BigInt<N>) -> bool {
let mut ok : bool = true;
for i in 0..N {
@ -132,6 +188,7 @@ impl<const N: usize> BigInt<N> {
}
//------------------------------------
// addition and subtraction
#[inline(always)]
#[unroll_for_loops]
@ -235,6 +292,7 @@ impl<const N: usize> BigInt<N> {
}
//------------------------------------
// multiplication
pub fn scale(scalar: u32, big2: &BigInt<N>) -> (BigInt<N>, u32) {
let mut c : u32 = 0;

View File

@ -49,6 +49,10 @@ impl Felt {
Felt(BigInt::make(xs))
}
pub fn is_valid(felt: &Felt) -> bool {
BigInt::is_lt_prime(&felt.0)
}
pub fn checked_make( xs: [u32; 8] ) -> Felt {
let big: Big = BigInt::make(xs);
if BigInt::is_lt_prime(&big) {
@ -59,6 +63,26 @@ impl Felt {
}
}
//------------------------------------
pub fn to_le_bytes(felt: &Felt) -> [u8; 32] {
BigInt::to_le_bytes(&felt.0)
}
pub fn unsafe_from_le_bytes(buf: &[u8; 32]) -> Felt {
let big = BigInt::from_le_bytes(buf);
Felt(big)
}
pub fn to_be_bytes(felt: &Felt) -> [u8; 32] {
BigInt::to_be_bytes(&felt.0)
}
pub fn unsafe_from_be_bytes(buf: &[u8; 32]) -> Felt {
let big = BigInt::from_be_bytes(buf);
Felt(big)
}
// convert to Montgomery representation
pub fn to_mont(fld: &Felt) -> Mont {
Mont::unsafe_convert_from_big( &fld.0 )
@ -69,6 +93,8 @@ impl Felt {
Felt(Mont::convert_to_big(&mont))
}
//------------------------------------
pub fn zero() -> Felt {
Felt(BigInt::zero())
}

View File

@ -39,6 +39,34 @@ impl Mont {
Mont(BigInt::make(xs))
}
pub fn is_valid(mont: &Mont) -> bool {
BigInt::is_lt_prime(&mont.0)
}
// note: this exports the Montgomery representation!
pub fn to_le_bytes(mont: &Mont) -> [u8; 32] {
BigInt::to_le_bytes(&mont.0)
}
// note: this assumes the input is already in Montgomery representation!
pub fn unsafe_from_le_bytes(buf: &[u8; 32]) -> Mont {
let big = BigInt::from_le_bytes(buf);
Mont(big)
}
// note: this exports the Montgomery representation!
pub fn to_be_bytes(mont: &Mont) -> [u8; 32] {
BigInt::to_be_bytes(&mont.0)
}
// note: this assumes the input is already in Montgomery representation!
pub fn unsafe_from_be_bytes(buf: &[u8; 32]) -> Mont {
let big = BigInt::from_be_bytes(buf);
Mont(big)
}
//------------------------------------
#[inline(always)]
pub fn zero() -> Mont {
Mont(BigInt::zero())