Encodings
Details about encodings used to represent core data structures using both field elements and bits.
Compressed Point Encoding
We often represent Baby Jubjub curve points in a "compressed" 255-bit encoding to save on hashing, bandwidth, and calldata. Our encoding scheme is identical to the scheme used in circomlib's PointBits templates and circomlibjs's packPoint and unpackPoint methods.
For a given point P=(X,Y), the compressed encoding is the pair (s,Y), where s is a single bit representing the "sign" (1 means negative) of X, and a field element x∈Fp is considered "negative" if x>2p−1.
To decompress a pair (s,Y), we do the following:
check that s and Y are well-formed.
compute X2=A−DY21−Y2, where A and D are Baby Jubjub's curve parameters
check that the square root exists. If it doesn't, the pair does not represent a valid curve point.
if the square root is 0, assert that s is also 0. Otherwise, the pair is an invalid encoding
otherwise, there will be two square roots - return the one whose "sign" matches s:
compute one of them and call it X.
compute the sign s′ of X by comparing with 2p−1
if s′=s, return X. Otherwise, return p−X.
We encode (s,Y) pairs into a 255-bit value as the sign bit followed by the binary representation of Y, which is 254-bits. In code:
function encodePair(signBit: bool, y: uint256) returns (uint256) {
return uint256(signBit) << 254 | y
}Note that the compressed encoding does not fit in a field element, even though it does fit in a uint256. Therefore it is (for the most part) not used in-circuit.
Asset Encoding
We define an Asset by the following struct:
To represent the asset using only valid elements of Fp, we transform it into the following form:
encodedAssetIdis the number represented by the 253 least-significant bits ofassetId.encodedAssetAddris defined as the number represented by the following bits concatenated together, read from most-significant to least-significant (i.e. in big-endian order):3
0bitsthe 3 most-significant bits of
assetId88 bits that are left unspecified (currently they are ignored)
2 bits representing
assetType-00forERC20,01forERC721,10forERC1155.160 bits representing
assetAddr.
Note Encoding
We define the Note and EncodedNote structs as follows:
Within Nocturne, all amounts and balances are forced by the contracts and circuits to be 252-bit integers. This ensures it's impossible to overflow the field.
The StealthAddress struct is a "flattened" form of a stealth address. If we recall that a stealth address is pair of Baby Jubjub curve elements (H1,H2)∈G2, h1X, h1Y, h2X, and h2Y are the X and Y coordinates of H1 and H2 respectively.
The CompressedStealthAddress struct is the "compressed" form of a stealth address, where the two components H1,H2 are represented using compressed point encoding (see above).
The encoding process for a Note is:
encode the
assetdecompress the
stealthAddressfieldpull out the
encodedAssetAddrandencodedAssetIdfields.
Last updated