Skip to main content

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​

NameTypeDescription
ptr*const u8Pointer to check for 8-byte alignment.

Returns​

TypeDescription
booltrue 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​

NameTypeDescription
bytes&[u8; 32]Big-endian 32-byte integer.

Returns​

TypeDescription
[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​

NameTypeDescription
x&[u64]Left operand, little-endian limbs.
y&[u64]Right operand, same length as x.

Returns​

TypeDescription
booltrue 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.

Returns true when every limb is zero.

pub fn is_zero(x: &[u64]) -> bool

Parameters​

NameTypeDescription
x&[u64]Slice of little-endian limbs.

Returns​

TypeDescription
booltrue if x == 0, false otherwise.

Example​

if zisklib::is_zero(&x) { return; }