## 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 {
nocustContractAddressChecksum: Byte32 // checksum(nocustContractAddress)
tokenContractAddressChecksum: Byte32 // checksum(tokenContractAddress)
userAddressChecksum: Byte32 // checksum(userAddress)
passiveAggregateChecksum: Byte32 // checksum(passiveAggregate)
activeTreeRoot: Byte32
}
```

`nocustContractAddressChecksum`

is the checksum of the NOCUST smart contract address:`interface NocustSmartContractAddress extends Checksumable { nocustSmartContractAddress: Address }`

`tokenContractAddressChecksum`

is the checksum of the asset token smart-contract address.`interface TokenContractAddressChecksum extends Checksumable { tokenContractAddressChecksum: Address }`

`userAddressChecksum`

is the checksum of the address of the user account.`interface UserAddressChecksum extends Checksumable { userAddressChecksum: Address }`

`passiveAggregateChecksum`

is the checksum of the`PassiveAggregate`

model:`interface PassiveAggregate extends Checksumable { passiveTreeRoot: Byte32 passiveAmountReceived: Uint256 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 {
counterpartyAddressChecksum: Bytes32
amount: Uint256
recipientLeafIndex: Uint64
transferTag: Uint256
}
```

`counterpartyAddressChecksum`

is the checksum of the recipient or sender address $i$:`interface CounterpartyAddress extends Checksumable { counterpartyAddress: Address }`

`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
buyTokenChecksum: Bytes32
index: Uint64
sellAmount: Uint256
buyAmount: Uint256
startinBalance: Uint256
nonce: Uint256
}
```

`sellToken`

is the checksum of the token address to sell:`interface SellToken extends Checksumable { sellToken: Address }`

`buyToken`

is the checksum of the token address to buy:`interface BuyToken extends Checksumable { buyToken: Address }`

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

`membershipProof`

is the the Merkle proof of the membership tree for asset token $X$.`accountProof`

is the interval tree proof of the account tree for account $\mathbb{P}_i^X(e)$`accountAggregate`

is the account aggregate of which the checksums is the leaf of the account tree

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

`deliverProof`

is a interval tree proof of $\mathfrak{T}_{i,j}^X$ in the passive tree`transfer`

is the transfer (incoming only) of which the checksums is the leaf of the passive tree

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

`deliveryProof`

is a Merkle proof of the`transfer`

in the active.`transaction`

is a swap or transfer of which the checksums is the leaf of the active tree

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 {
nocustContractAddressChecksum: Byte32 // checksum(nocustContractAddress)
tokenContractAddressChecksum: Byte32 // checksum(tokenContractAddress)
userAddressChecksum: Byte32 // checksum(userAddress)
leafIndex: Uint64
eonNumber: Uint256
activeTreeRoot: Byte32
spent: Uint256
gained: Uint256
}
```

`nocustContractAddressChecksum`

is the checksum of the NOCUST smart contract address:`interface NocustSmartContractAddress extends Checksumable { nocustSmartContractAddress: Address }`

`tokenContractAddressChecksum`

is the checksum of the asset token smart-contract address.`interface TokenContractAddressChecksum extends Checksumable { tokenContractAddressChecksum: Address }`

`userAddressChecksum`

is the checksum of the address of the user account.`interface UserAddressChecksum extends Checksumable { userAddressChecksum: Address }`

`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 {
nocustContractAddressChecksum: Byte32
tokenContractAddressChecksum: Byte32
userAddressChecksum: Byte32
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.

## Example Implementation

- Python server Merkle tree implementation: https://github.com/liquidity-network/nocust-server/blob/master/operator_api/operator_api/merkle_tree.py
- Solidity contract Merkle proof verification: https://github.com/liquidity-network/nocust-contracts-solidity/blob/master/contracts/MerkleVerifier.sol

## Other Implementations

## History

## Copyright

All content herein is licensed under GPL License.