## Synopsis

The Bimodal ledger is the core data-structure holding account information. The checksum aggregates all the ledger and makes it straightforward to audit and verify its content.

### Motivation

The user accounts need to be structured and aggregated in a deterministic manner for the NOCUST periodic commitment.

### Definitions

• $\mathfrak{T}_{i,j}^X(e)$: Transfer from $\mathbb{P}_i^X(e)$ to $\mathbb{P}_j^X(e)$ of asset token $X$ during eon $e$
• $\mathfrak{X}_i^{X,Y}(e)$: Swap made by $\mathbb{P}_i(e)$ selling asset token $X$ from $\mathbb{P}_i^X(e)$ buying asset token $Y$ with $\mathbb{P}_i^Y(e)$ during eon $e$
• $\mathfrak{A}_i^X(e)$: Proof of exclusive balance allotment for $\mathbb{P}_i^X(e)$
• $\lambda_P(\mathfrak{T}_{i,j}^X \in\mathbb{P}_j^X)$ : Proof of transfer delivery for $\mathfrak{T}_{i,j}^X$ in $\mathbb{P}_i^X$
• $\lambda_A(\mathfrak{X}_i^{X,Y} \in\mathbb{P}_i^X )$ : Proof of active swap delivery for $\mathfrak{X}_i^{X,Y}$ in $\mathbb{P}_i^X$
• $\mathfrak{S}_i^K(e)$: Represent the latest active state of the account $\mathbb{P}_i^X(e)$
• $\mathfrak{M}_i^K(e)$: Represent the latest Balance Marker of the account $\mathbb{P}_i^X(e)$
• $SIG_{op}(N)$ Signature by to operator over an object $N$
• $SIG_{i}(N)$ Signature by $\mathbb{P}_i$ over an object $N$
• $R^p_i(e)$: The amount received from transfers during the round
• $R^a_i(e)$: The amount received from swaps during the round
• $S_i(e)$: The amount spent by doing swap or transfer during the round

We will refer to an element/variable of an object with the notation .variableName. For example, $\mathfrak{S}_i^K(e).\texttt{eonNumber}​$ refers to the eonNumber element of the active state

### Desired Properties

The bimodal ledger allows for light client verifications of exclusive allotments. Merkle proofs should be compact and grow logarithmically with the number of users and transactions.

## Technical Specification

Below is an overview of the complete NOCUST bimodal ledger.

At the very top is the checkpoint that is periodically committed onto the parent chain. At the top level is the membership tree or token tree. Each leaf consist of 1 token/asset supported by the commit-chain (typically ERC-20 or Ether in Ethereum). The second level from the top is the account tree. Each leaf is a user account for a specific token. This tree has the specificity to be an Interval tree of account balance. Each user account is composed of several fields including the account address (public key) and Active and Passive transaction trees.

### Trees

#### Checkpoint

The checkpoint is the 32 byte root checksum of the membership tree. The checkpoint needs to be periodically submitted to the access restricted function submitCheckpoint. Exactly one checkpoint per eon MUST be submitted by operator. All the data within the bimodal ledger depends on a specific eon number.

interface checkpoint {
checkpoint: Byte32
}


#### Membership tree

The membership tree MUST be a standard Merkle tree as described in NSPEC004. The NOCUST commit-chain MAY support compliant asset tokens (ERC-20 on Ethereum). Each asset supported by the commit chain is reflected by a leaf in the membership tree. The leaf at index 0 MUST represents the native asset of the parent-chain (Ether for Ethereum). The operator MAY add support for additional asset token. To add an asset token it MUST call the access restricted contract function registerERC20. Each leaf simply consists of the root checksum of the account tree for the given asset.

#### Account tree

The membership tree is an Interval tree as described in NSPEC004. Each leaf in the tree represent a user account $\mathbb{P}_i$ that includes all of its transactions and additional meta-data. The leafChecksum from NSPEC004 MUST be set to the checksum of the Account aggregate. The allotment $A_i$ of each account is set to the account balance. The left and right values from NSPEC004 MUST be set according to the interval equation.

#### Active tree

The active tree of $\mathbb{P}_i^X$ MUST contain all outgoing transactions $\mathfrak{T}_{i,j}^X(e)$ made during the eon, and all swaps $\mathfrak{X}_i^{X,Y}(e)$ buy or sell made by the user account during the eon of the checkpoint. The active tree MUST be a standard Merkle tree as described in NSPEC004. The leafs are the checksums of the transactions. The sum of the amount of all the outgoing transfer and swap in the active tree is equal to $S_i(e)$. The sum of the amount of all the swaps is equal to $R_i^a(e)$

#### Passive tree

The passive tree MUST contain all of the incoming transactions made during the eon of the checkpoint. The passive tree MUST not contain any swaps. The passive tree MUST be an interval tree as described in NSPEC004. The allotment of each transaction element is set to the amount of the transaction. The right and left values are set according to the interval formula from NSPEC004. The leafChecksum is set to the checksum of the transaction model. The sum of the amounts of all transfers in the passive tree is equal to $R_i^p(e)$

### Models

#### Account aggregate

They MUST be exactly one Account aggregate per $\mathbb{P}_i^X$. The checksum of this data structure is to be used as a leaf element of the Account tree.

interface AccountAggregate extends Checksumable {
passiveAggregateChecksum: Byte32      // checksum(passiveAggregate)
activeTreeRoot: Byte32
}

• nocustContractAddressChecksum is the checksum of the NOCUST smart contract address:

interface NocustSmartContractAddress extends Checksumable {
}

• tokenContractAddressChecksum is the checksum of the asset token smart-contract address.

interface TokenContractAddressChecksum extends Checksumable {
}

• userAddressChecksum is the checksum of the address of the user account.

interface UserAddressChecksum extends Checksumable {
}

• passiveAggregateChecksum is the checksum of the PassiveAggregate model:

interface PassiveAggregate extends Checksumable {
passiveTreeRoot: Byte32
lastOugoingTransferpassiveMarker: Uint256
}

• passiveTreeRoot is the Merkle root of the passive tree.
• passiveAmountReceived is $R^p_i(e)$ the total sum of the funds received by transfer for the particular asset or the sum of the transactions in the passive tree.
• lastOugoingTransferpassiveMarker Is the Passive Marker of the last outgoing transfer.
• activeTreeRoot is the Merkle root of the active tree.

#### Transaction Model

NOCUST supports 2 types of transaction. Transfers, sending money from Alice to Bob, and token swaps between 2 asset tokens. The commit-chain MAY support only payment but no swaps. However, the commit-chain MUST always support transfer.

##### Transaction model for payment

$\mathfrak{T}_{i,j}^X(e)$, transfer from $\mathbb{P}_i^X(e)$ to $\mathbb{P}_j^X(e)$ of asset token $X$ during eon $e$

interface Transfer extends Checksumable {
amount: Uint256
recipientLeafIndex: Uint64
transferTag: Uint256
}

• counterpartyAddressChecksum is the checksum of the recipient or sender address $i$:

interface CounterpartyAddress extends Checksumable {
}

• amount is the amount sent.

• recipientLeafIndex is the index of the leaf in the account tree of the recipient $\mathbb{P}_j$.

• transferTag is a unique number resulting from the Uint256 interpretation of the checksum of the Tag model

interface TransferTag extends Checksumable {
passiveMarker: Uint256
nonce: Uint256
}

• passiveMarker If the transfer is finalized. We set its value to the Passive Marker (left value of the transfer in the passive interval tree of the recipient). If the transfer is not finalized, we set its value to $2^{256} - 1$.
• nonce is a unique random number to be chosen by the sender.

We call a transfer finalized, if it is not the last element in the active set.

A valid $\mathfrak{T}_{i,j}^X(e)$ MUST be included in the passive tree of $\mathbb{P}^X_j(e)$ and in the active tree of $\mathbb{P}_i^X(e)$.

##### Transaction model for swap

For a new swap $\mathfrak{X}_i^{X,Y}(e)$. We call $\mathbb{P}_i^X$ debited account and $\mathbb{P}_i^Y$ the credited account

interface Swap extends Checksumable {
sellTokenChecksum: Bytes32
index: Uint64
sellAmount: Uint256
startinBalance: Uint256
nonce: Uint256
}

• sellToken is the checksum of the token address to sell:

interface SellToken extends Checksumable {
}

• buyToken is the checksum of the token address to buy:

interface BuyToken extends Checksumable {
}

• index is the leaf index of the credited account.

• sellAmount amount of the sellToken to sell.

• buyAmount amount of the buyToken to buy.

• startingBalance is the balance $balance(\mathbb{P}_i)$ at the start of the swap.

• nonce is a unique random number to be chosen by the sender.

A valid $\mathfrak{X}_i^{X,Y}(e)$ MUST be included in the active tree of $\mathbb{P}_i^X(e)$ and $\mathbb{P}_i^Y(e)$.

#### Proof of exclusive balance allotment

$\mathfrak{A}_i^X(e)$ A proof of exclusive balance allotment is specific to an account $\mathbb{P}_i^X(e)$. It allows to fully verify $A_i^X(e)$ from the checkpoint on the parent-chain.

interface ProofOfExclusiveBalanceAllotement {
membershipProof: MerkleProof
accountProof: ProofOfExclusiveAllotement
accountAggregate: AccountAggregate
}


A proof of exclusive balance allotment is considered valid if the root of the membership tree reconstructed match the checkpoint.

#### Proof of passive delivery

$\lambda_P(\mathfrak{T}_{i,j}^{X} \in\mathbb{P}_j^X )$ is the Proof of transfer delivery for $\mathfrak{T}_{i,j}^X$ in $\mathbb{P}_j^X$. It allows to verify the delivery of transfer in the recipient account.

interface ProofOfPassiveDelivery {
deliveryProof: ProofOfExclusiveAllotement
transfer: Transfer
}


A proof of passive delivery is considered valid if the if the root of the membership tree reconstructed match the checkpoint.

#### Proof of active delivery

$\lambda_A(\mathfrak{T}_{i,j}^{X} \in\mathbb{P}_i^X )​$ is the Proof of active delivery of transfer $\mathfrak{T}_{i,j}^X​$ in $\mathbb{P}_i^X​$. It allows proving the inclusion of a transfer in the sender account.

$\lambda_A(\mathfrak{X}_i^{X,Y} \in\mathbb{P}_i^X )$ is the proof of active delivery of swap $\mathfrak{X}_i^{X,Y}$ in $\mathbb{P}_i^X$. It allows proving the inclusion of the swap in sell account.

$\lambda_A(\mathfrak{X}_i^{X,Y} \in\mathbb{P}_i^Y )$ is the proof of active delivery of swap $\mathfrak{X}_i^{X,Y}$ in $\mathbb{P}_i^Y$. It allows proving the inclusion of swap in buy account.

interface ProofOfActiveDelivery {
deliveryProof: MerkleProof
transaction: Transfer | Swap
}


A proof of active delivery is considered valid if the root of the membership tree reconstructed match the checkpoint.

#### Active state

The active state is essentially a subset of the account aggregate. The missing fields are the passiveAggregateChecksum and the passiveAggregate. While its checksum is not directly part of the bimodal ledger, the active state is central in the NOCUST architecture. It is the data-structure that is used to authorize off-chain transactions. We denote $\mathfrak{S}_i^K(e)$ the latest active-state of account $\mathbb{P}_i^K(e)$.

The active state is checksumed and signed by the user and the operator to authorize a transaction. Users make transactions by creating a new updated active state. We denote $SIG_{i}(\mathfrak{S}_i^K)$ the signature of the active state $\mathfrak{S}_i^K$ by the user $\mathbb{P}_i$ and $SIG_{op}(\mathfrak{S}_i^K)$ the signature of the active state $\mathfrak{S}_i^K$ by the operator.

For an active state $\mathfrak{S}_i^K$ to be considered valid, it MUST be signed by the operator and the account owner.

interface ActiveState extends Checksumable {
leafIndex: Uint64
eonNumber: Uint256
activeTreeRoot: Byte32
spent: Uint256
gained: Uint256
}

• nocustContractAddressChecksum is the checksum of the NOCUST smart contract address:

interface NocustSmartContractAddress extends Checksumable {
}

• tokenContractAddressChecksum is the checksum of the asset token smart-contract address.

interface TokenContractAddressChecksum extends Checksumable {
}

• userAddressChecksum is the checksum of the address of the user account.

interface UserAddressChecksum extends Checksumable {
}

• leafIndex of the account in the Account tree. The account index is provided by the operator after account registration and can't be changed

• eonNumber MUST equals $e$.

• activeTreeRoot root of the Active Tree. The active tree MUST include all the the outgoing transactions and swaps made during the eon eonNumber or all the outgoing transaction and swaps made in the current ongoing eon.

• spent the total amount spent. We add to the spent value after making an outgoing transfer or swap. Withdrawals request do not count toward spent.

• gained the total amount received by swap during the eon. We add to the gained value only after finalizing a swap. Deposits do not count toward gained

#### Balance Marker

The balance marker is used to communicate user account balance to the operator. It is not directly part of the bimodal ledger. We denote the Balance Marker $\mathfrak{M}_i^K(e)$ of account $\mathbb{P}_i^K$.

interface BalanceMarker extends Checksumable {
eonNumber: Uint256
balance: Uint256
}


The first 3 fields are the same as in the active state of the account. eonNumber is set to $e$. balance is set to a balance value.