Utilities
zisklib utility helpers: pointer alignment, big-endian byte to
little-endian limb conversions, and lexicographic
comparison / equality / predicate checks over multi-limb [u64]
slices.
Overview
Low-level helpers used across zisklib for shuffling 256-bit values
between byte buffers and limb arrays and for fast-path predicates
(zero, one, power of two, single-limb) that appear throughout modular
arithmetic and curve scalar handling. Two representations dominate:
big-endian &[u8] (as used by external interfaces and the
hash-functions module) and little-endian &[u64] (limb 0 = LSB). The
byte-order conversions bridge the two for the canonical 256-bit size;
the comparison and predicate helpers work on slices of any matching
length. Everything in uint256 and bigint
ultimately leans on these.
Alignment
Pointer alignment checks needed when calling into zkVM precompiles
that require their input/output buffers to sit on an 8-byte boundary.
Pointers are passed as raw *const u8 so callers can verify any
slice, struct, or limb array regardless of element type before
handing it off to a syscall.
Returns true when the given pointer is 8-byte aligned (the low 3
bits of the address are zero).
pub fn is_aligned_8(ptr: *const u8) -> bool
Parameters
| Name | Type | Description |
|---|---|---|
ptr | *const u8 | Pointer to check for 8-byte alignment. |
Returns
| Type | Description |
|---|---|
bool | true if ptr as usize & 0x7 == 0, false otherwise. |
Example
let buf = [0u64; 4];
assert!(zisklib::is_aligned_8(buf.as_ptr() as *const u8));
Byte-order conversion
Lossless translation between big-endian 32-byte buffers and the
canonical 4-limb little-endian [u64; 4] representation that
zisklib uses for 256-bit integers. The two functions are inverses
of each other and bridge the byte-oriented hash-functions outputs
and external 32-byte encodings with the limb-oriented uint256 and
bigint modules.
Decodes a big-endian 32-byte buffer into four 64-bit little-endian
limbs. Limb 0 holds the least significant 8 bytes (bytes[24..32]).
pub fn be_bytes_to_u64_4(bytes: &[u8; 32]) -> [u64; 4]
Parameters
| Name | Type | Description |
|---|---|---|
bytes | &[u8; 32] | Big-endian 32-byte integer. |
Returns
| Type | Description |
|---|---|
[u64; 4] | The same value as 4 little-endian u64 limbs. |
Example
let limbs = zisklib::be_bytes_to_u64_4(&be_bytes);
Comparison
Lexicographic ordering and equality over arbitrary-length
little-endian limb slices, comparing from the most significant limb
down. Both operands must have the same number of limbs (debug-asserted),
so values are expected to already be normalised to a fixed width.
These routines underpin range checks and modular-reduction guards in
the uint256 and bigint modules.
Lexicographic greater-than over two equal-length little-endian limb slices. Compares from the most significant limb downward.
pub fn gt(x: &[u64], y: &[u64]) -> bool
Parameters
| Name | Type | Description |
|---|---|---|
x | &[u64] | Left operand, little-endian limbs. |
y | &[u64] | Right operand, same length as x. |
Returns
| Type | Description |
|---|---|
bool | true if x > y, false otherwise. |
Example
if zisklib::gt(&a, &b) { /* ... */ }
Predicates
Single-operand shape checks on a multi-limb integer: is it zero, is it
one, is it a power of two, does it fit in a single 64-bit word. Inputs
are little-endian &[u64] limb slices of any length. These predicates
are useful for early-exits and fast paths inside modular exponentiation,
scalar handling, and the modular routines in bigint and uint256.