aztec-nr - protocol_types::traits

Trait Packable

pub trait Packable {
    let N: u32;

    // Required methods
    pub fn pack(self) -> [Field; N];
    pub fn unpack(packed: [Field; N]) -> Self;
}

Space-efficient value packing and unpacking.

Like Serialize and Deserialize, this trait is used to convert to a from Field array representations. Packable is used instead of those whenever the length of the resulting array needs to be minimized, for example in order to reduce the number of amount storage access operations, or the number of values that will be hashed together.

The associated constant N is the length of the Field array.

Automatic Derivation

The #[derive] macro can be used on any type that holds primitive values, or types that themselves also derive Packable. The resulting implementation does not attempt to tightly-pack values at all, and instead simply assigns a full Field to each value. This makes it suitable for types that are composed solely of Field-sized elements.

#[derive(Packable)]
struct FieldGrouping {
    a: Field,
    b: Field,
    c: Field,
}

#[derive(Packable)]
struct NestedStructs {
    fg: FieldGrouping,
    x: Field,
}

// Inefficient: there are gains to be had by manually implementing the trait instead of using `derive`
#[derive(Packable)]
struct SubFieldGrouping {
    a: bool,
    b: u32,
    c: u64,
}

Manual Implementation

If a type holds at least two elements smaller than a Field, then manually implementing Packable can result in reduced costs (assuming the sub-Field elements are small enough to be packed together).

The nature of cost reduction will depend on what the value is used for. For public storage, it will typically decrease both L2 gas (in the form of fewer SLOAD and SSTORE opcodes) and DA costs (due to there being fewer slots accessed). For notes, it will typically decrease proving times (due to fewer hash operations).

Note that packing and unpacking must also be runtime efficient for the previously mentioned gains to not be offset by this overhead. Bit-packing by multiplying and dividing by powers of 2 is often a good strategy, as this maps well to both AVM opcodes (for public contract functions) and proving backend primitives (for private contract functions).

struct TwoBooleans {
    a: bool,
    b: bool,
}

impl Packable for TwoBooleans {
    let N: u32 = 1;

    fn pack(self) -> [Field; Self::N] {
        // a in bit 1, b in bit 0
        [(self.a as Field) * 2.pow_32(1) + (self.b as Field)]
    }

    fn unpack(packed: [Field; Self::N]) -> Self {
        let b = (packed[0] as u1) != 0;
        let a = (((packed[0] - b as Field) / 2.pow_32(1)) as u1) != 0;

        Self { a, b }
    }
}

Required methods

pub fn pack(self) -> [Field; N]

Packs the value into a compact Field array.

The original value can be reconstructed by calling Packable::unpack.

pub fn unpack(packed: [Field; N]) -> Self

Unpacks the value from a compact Field array.

packed must be the value returned by Packable::pack.

Implementors

impl Packable for AddressNote

impl Packable for AztecAddress

impl<let M: u32, let N: u32> Packable for CompressedString<N, M>

impl Packable for ContractClassId

impl<let INITIAL_DELAY: u64, T> Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>
where T: Packable

impl Packable for EmbeddedCurvePoint

impl Packable for Empty

impl Packable for EthAddress

impl Packable for Field

impl Packable for FieldCompressedString

impl Packable for FieldNote

impl<let N: u32, T> Packable for HasArrayWithGenerics<T, N>
where T: Packable

impl<Note> Packable for HintedNote<Note>
where Note: Packable

impl Packable for MockStruct

impl Packable for MockStruct

impl Packable for NoteMetadata

impl Packable for PartialUintNote

impl Packable for Smol

impl Packable for TwoBooleans

impl Packable for UintNote

impl<let M: u32, T> Packable for WithHash<T, M>
where T: Packable<N = M>

impl<let M: u32, T> Packable for [T; M]
where T: Packable

impl Packable for bool

impl Packable for i16

impl Packable for i32

impl Packable for i64

impl Packable for i8

impl Packable for u128

impl Packable for u16

impl Packable for u32

impl Packable for u64

impl Packable for u8