# 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 \in \mathbb{F}_p$ is considered "negative" if $x \gt \frac{p - 1}{2}$.

To decompress a pair $(s, Y)$, we do the following:

check that $s$ and $Y$ are well-formed.

compute $X^2 = \frac{1 - Y^2}{A - DY^2}$, 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 $\frac{p-1}{2}$

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:

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 $\mathbb{F}_p$, we transform it into the following form:

`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`

bitsthe 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`

.

### 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 $(H_1, H_2) \in \mathbb{G}^2$, `h1X`

, `h1Y`

, `h2X`

, and `h2Y`

are the $X$ and $Y$ coordinates of $H_1$ and $H_2$ respectively.
The `CompressedStealthAddress`

struct is the "compressed" form of a stealth address, where the two components $H_1, H_2$ are represented using compressed point encoding (see above).

The encoding process for a `Note`

is:

encode the

`asset`

decompress the

`stealthAddress`

fieldpull out the

`encodedAssetAddr`

and`encodedAssetId`

fields.

Last updated