Encodings
Details about encodings used to represent core data structures using both field elements and bits.
Last updated
Details about encodings used to represent core data structures using both field elements and bits.
Last updated
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 , the compressed encoding is the pair , where is a single bit representing the "sign" ( means negative) of , and a field element is considered "negative" if .
To decompress a pair , we do the following:
check that and are well-formed.
compute , where and 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 , assert that is also . Otherwise, the pair is an invalid encoding
otherwise, there will be two square roots - return the one whose "sign" matches :
compute one of them and call it .
compute the sign of by comparing with
if , return . Otherwise, return .
We encode pairs into a 255-bit value as the sign bit followed by the binary representation of , which is 254-bits. In code:
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.
We define an Asset
by the following struct:
encodedAssetId
is the number represented by the 253 least-significant bits of assetId
.
encodedAssetAddr
is 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 0
bits
the 3 most-significant bits of assetId
88 bits that are left unspecified (currently they are ignored)
2 bits representing assetType
- 00
for ERC20
, 01
for ERC721
, 10
for ERC1155
.
160 bits representing assetAddr
.
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 encoding process for a Note
is:
encode the asset
decompress the stealthAddress
field
pull out the encodedAssetAddr
and encodedAssetId
fields.
To represent the asset using only valid elements of , we transform it into the following form:
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 , h1X
, h1Y
, h2X
, and h2Y
are the and coordinates of and respectively.
The CompressedStealthAddress
struct is the "compressed" form of a stealth address, where the two components are represented using compressed point encoding (see above).