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; }