Storage and Operations
The Ledger Engine should utilize a key-value based database with support for transactions like RocksDB to store balances and State Updates.
Balance Storage
BalanceStore: BalanceKey:Hash(Wallet,Asset,ChainId) -> Uint
Stores amount of an asset available for a trader. Defaults to 0.
LastBalanceUpdateStore: LastBalanceUpdateKey:Hash(Wallet,Asset,ChainId) -> Uint
Stores the sequence number of the last state update that affected the trader's balance of an asset. Defaults to 0.
State Update Storage
SequenceIdStore: SequenceKey -> Uint
Stores next sequence number
StateUpdateStore: StateUpdateKey:Uint -> Serialize(StateUpdate)
Stores raw State Update by its sequence number
ChainSequenceIdStore: Uint -> Uint
Maps chain ID to latest chain sequence ID
Merkle Storage
LeafStore: Uint -> LeafHash
Append-only
Index of leaf in tree
Operations
Generating State Updates
processDeposit(Deposit deposit)
MUST be atomic
using
chainId
ofdeposit
, query for latest id fromChainSequenceIdStore.
Assert that thechainSequenceId
of the deposit is one after the latest id. Update the latest id.hash
deposit
to obtain UTXO hashdepositHash
Can be done in parallel:
using
depositHash
, store the deposit inUTXOStore
get wallet and asset from
deposit
, hash to get key forWalletStore.
append
BalanceKey
to last key, get value fromBalanceStore
. Add amount from deposit, update value inBalanceStore
using
SequenceKey
, get next sequence number fromSequenceStore
using sequence number and the
deposit
, create aStateUpdate
serialize
DepositParams
and store using sequence number as key inStateUpdateStore
processTrade(TradeParams trade)
using
size
andprice
of trade, calculate amount of each asset that needs to be paidBased on the parameters of the trade, determine the address of the maker and taker, as well as the address and chain ID of the base asset and counter asset, and query for the following:
maker's balance of base asset from
BalanceStore
and the last update from theLastUpdateBalanceStore
maker's balance of counter asset from
BalanceStore
and the last update from theLastUpdateBalanceStore
taker's balance of base asset from
BalanceStore
and the last update from theLastUpdateBalanceStore
taker's balance of counter asset from
BalanceStore
and the last update from theLastUpdateBalanceStore
If maker's order is a BUY and taker's order is a SELL, generate new balances for each side by doing the following:
decrement maker's balance of counter asset by
size * price
increment taker's balance of counter asset by
size * price
increment maker's balance of base asset by
size
decrement taker's balance of base asset by
size
If maker's order is a SELL and taker's order is a BUY, do same as above but switch maker and taker
Using the new balances from above, update the following:
maker's balance of base asset in
BalanceStore
maker's balance of counter asset in
BalanceStore
taker's balance of base asset in
BalanceStore
taker's balance of counter asset in
BalanceStore
using
SequenceKey
, get next sequence number fromSequenceStore
use sequence number to update the following:
maker's last update for balance of base asset in
LastBalanceUpdateStore
maker's last update for balance of counter asset in
LastBalanceUpdateStore
taker's last update for balance of base asset in
LastBalanceUpdateStore
taker's last update for balance of counter asset in
LastBalanceUpdateStore
using sequence number, previous balances, sequence IDs of previous balances, and new balances:
serialize
Trade
and store using sequence number as key inStateUpdateStore
processSettlementRequest(SettlementRequest settlementRequest)
using
chainId
ofsettlementRequest
, query for latest id fromChainSequenceIdStore.
Assert that thechainSequenceId
of the settlement request is one after the latest id. Update the latest Id.using
trader,
asset
, andchainId
ofsettlementRequest
, construct key forBalanceStore
andLastBalanceUpdateStore
, and query for eachusing
trader
andasset
ofsettlementRequest
, construct key forBalanceStore
and set the value to0
using
SequenceKey
, get next sequence number fromSequenceStore
using the
settlementRequest
, last balance update ID, old balance, new balance (zero), and sequence ID, createSettlementAcknowledgement
use sequence ID to update last balance update ID for trader and asset
serialize
SettlementAcknowledgement
and store using sequence number as key inStateUpdateStore
Validating State Updates
validateStateUpdate(SignedStateUpdate proposedStateUpdate, ChainEventStore eventStore)
validate that the address recovered from the signature of the
proposedStateUpdate
matches the address of theparticipatingInterface
set in the state updatevalidate that the
sequenceId
of theproposedStateUpdate
is the next id in the sequence after the storedlastProcessedStateUpdate
Deserialize the
structData
based on thetypeIdentifier
and call the corresponding function to validate the state updateif the validate function specific to the state update returns true, then commit the changes and return true
if invalid, forward the signed state update to the fraud engine
validateDeposit(DepositAcknowledgement proposedDeposit, ChainEventStore eventStore)
using
chainId
andchainSequenceId
of theproposedDeposit.deposit
, query for the corresponding event in theeventStore
if event is missing, wait and try again
assert that the event from the
eventStore
matches the depositget
Deposit
fromproposedDeposit
and use as input toprocessDeposit
validate that the output generated by
processDeposit
matches the output inproposedDeposit
validateTrade(Trade proposedTrade)
get
TradeParams
fromproposedTrade
and use as input inprocessTrade
validate that the balances and last update IDs generated by
processTrade
match the ones in theproposedTrade
. Returntrue
if so, otherwise returnfalse
validateSettlement(SettlementAcknowledgement proposedSettlement, ChainEventStore eventStore)
using
chainId
andchainSequenceId
of theproposedSettlement.settlementRequest
, query for the corresponding event in theeventStore
if event is missing, wait and try again
assert that the event from the
eventStore
matches the settlement requestget
SettlementRequest
fromproposedSettlement
and use as input inprocessSettlementRequest
validate that the balances and last update IDs generated by
processSettlementRequest
match the ones in theproposedSettlement
. Returntrue
if so, otherwise returnfalse
Last updated