-
Some indices are specified using badgerhold tags on struct fields. Others by implementing the
Indexes()
method ofbh.Storer
interface. -
Watch out when using indices on fields of pointer types. By default, badgerhold adds IDs of all structs that have the indexed field set to
nil
to a single index entry, for instance:_bhIndex:Batch:Hash:nil -> bh.KeyList{ batchID1, batchID2, ... }
Such index entry can quickly grow in size. For structs that have indices on fields of pointer type we can implement
Indexes()
method and specify our ownIndexFunc
. Returningnil
from suchIndexFunc
fornil
field values prevents creation of thenil
index entry. In case you go down this path, make sure to initialise the index usinginitializeIndex
function (seestorage/initialize_index.go
for more info). -
All transaction details were previously held in a single Transaction structure. We had to split transaction details between Stored Transaction and Stored Transaction Receipt because of conflict between API
hubble_sendTransaction
method and Rollup loop iterations. If we kept all data in the same structure the API method would be adding new keys updating the indices. At the same time Rollup loop would be modifying the stored transactions updating the same indices. As a result some DB transactions would error withbh.ErrConflict
.
- Holds
UserState
data
Key: state ID uint32
Value: stored.StateLeaf
type StateLeaf struct {
StateID uint32
DataHash common.Hash
PubKeyID uint32
TokenID Uint256
Balance Uint256
Nonce Uint256
}
Key: pub key ID uint32
Value: list of state IDs bh.KeyList
- Holds state tree nodes (hashes). The leaf level nodes are hashes of
UserState
structs.
Key: node path models.NamespacedMerklePath
Prefix: bh_MerkleTreeNode:state
Value: node common.Hash
(through clever encoding of models.MerkleTreeNode
)
- Holds state tree updates including leaves data that were previously in the tree
Key: auto-incremented ID uint64
Value: models.StateUpdate
type StateUpdate struct {
ID uint64 `badgerhold:"key"`
CurrentRoot common.Hash
PrevRoot common.Hash
PrevStateLeaf StateLeaf
}
type StateLeaf struct {
StateID uint32
DataHash common.Hash
UserState
}
type UserState struct {
PubKeyID uint32
TokenID Uint256
Balance Uint256
Nonce Uint256
}
- Holds pubKeyID - publicKey mapping
Key: pubKeyID uint32
Value: {pubKeyID, publicKey} models.AccountLeaf
Key: publicKey models.PublicKey
Prefix: _bhIndex:AccountLeaf:PublicKey:
Value: list of pubKeyIDs bh.KeyList
- Holds account tree nodes (hashes). The leaf level nodes are hashes of public keys.
Key: node path models.NamespacedMerklePath
Prefix: bh_MerkleTreeNode:account
Value: node common.Hash
(through clever encoding of models.MerkleTreeNode
)
Key: tx hash common.Hash
Value: stored.PendingTx
type PendingTx struct {
Hash common.Hash
TxType txtype.TransactionType
FromStateID uint32
Amount models.Uint256
Fee models.Uint256
Nonce models.Uint256
Signature models.Signature
ReceiveTime *models.Timestamp
Body TxBody // interface
}
Body: stored.TxTransferBody
type TxTransferBody struct {
ToStateID uint32
}
Body: stored.TxCreate2TransferBody
type TxCreate2TransferBody struct {
ToPublicKey models.PublicKey
ToStateID *uint32
}
Body: stored.TxMassMigrationBody
type TxMassMigrationBody struct {
SpokeID uint32
}
- Stores transactions which have been added to a batch and submitted to the chain
Key: (BatchID, IndexInBatch, IndexInCommitment) models.CommitmentSlot
Value: stored.BatchedTx
type BatchedTx struct {
PendingTx
ID stored.CommitmentSlot
}
- Stores transactions which the rollup loop attempted to add to a batch, but failed
Key: tx hash common.Hash
Value: stored.FailedTx
type FailedTx struct {
PendingTx
ErrorMessage *string
}
Key: Hash common.Hash
Prefix: _bhIndex:BatchedTx:Hash:
Value: list bh.KeyList
with single element, the tx
- Holds individual pending deposits until they are moved into Pending Deposit Subtrees. Individual deposits correspond to
DepositQueued
events emitted by the SCs.
Key: <subtreeID, depositIndex> models.DepositID
Value: models.PendingDeposit
type DepositID struct {
SubtreeID Uint256 // the subtree which contains this deposit
DepositIndex Uint256 // deposit number in the subtree
}
type PendingDeposit struct {
ID DepositID
ToPubKeyID uint32
TokenID Uint256
L2Amount Uint256
}
- FIFO queue for ready Deposit Subtrees that can be submitted in a new Batch
Key: SubtreeID models.Uint256
Value: models.PendingDepositSubtree
type PendingDepositSubtree struct {
ID models.Uint256 // assigned in SC
Root common.Hash // subtree root that will be inserted into the state tree
Deposits []models.PendingDeposit // deposits included in the subtree
}
- Hold commitment details for both transaction and deposit commitmetns
Key: {BatchID, IndexInBatch} models.CommitmentID
Value: stored.Commitment
type Commitment struct {
models.CommitmentBase
Body CommitmentBody // interface
}
type CommitmentBase struct {
ID CommitmentID
Type batchtype.BatchType
PostStateRoot common.Hash
}
type CommitmentID struct {
BatchID Uint256
IndexInBatch uint8
}
Body: stored.TxCommitmentBody
type TxCommitmentBody struct {
FeeReceiver uint32
CombinedSignature models.Signature
BodyHash *common.Hash
}
Body: stored.MMCommitmentBody
type MMCommitmentBody struct {
CombinedSignature models.Signature
BodyHash *common.Hash
Meta models.MassMigrationMeta
WithdrawRoot common.Hash
}
type MassMigrationMeta struct {
SpokeID uint32
TokenID Uint256
Amount Uint256
FeeReceiver uint32
}
- When Deposit batch is created data is moved from Pending Deposit Subtree to Stored Commitment
Body: stored.DepositCommitmentBody
type DepositCommitmentBody struct {
SubtreeID Uint256
SubtreeRoot common.Hash
Deposits []models.PendingDeposit
}
- Hold details of both mined and pending batches. Pending batches have some fields left
nil
.
Key: batch ID models.Uint256
Value: stored.Batch
type Batch struct {
ID Uint256
BType batchtype.BatchType // not named `Type` to avoid collision with Type() method needed to implement bh.Storer interface
TransactionHash common.Hash
Hash *common.Hash // root of merkle tree of all commitments included in this batch
FinalisationBlock *uint32
AccountTreeRoot *common.Hash
PrevStateRoot *common.Hash
MinedTime *models.Timestamp
}
Key: batch hash *common.Hash
Prefix: _bhIndex:Batch:Hash:
Value: list of batch IDs bh.KeyList
- Holds a single value: the current chain state
Key: "ChainState" string
Value: models.ChainState
type ChainState struct {
ChainID Uint256
AccountRegistry common.Address
AccountRegistryDeploymentBlock uint64
TokenRegistry common.Address
DepositManager common.Address
Rollup common.Address
GenesisAccounts []PopulatedGenesisAccount
}
type PopulatedGenesisAccount struct {
PublicKey [128]byte
PubKeyID uint32
StateID uint32
Balance Uint256
}
- Holds tokenID - token contract address mapping
Key: token ID models.Uint256
Value: token contract address common.Address
(through clever encoding of models.RegisteredToken
)
type RegisteredToken struct {
ID models.Uint256
Contract common.Address
}
- Holds spokeID - spoke contract address mapping
Key: spoke ID models.Uint256
Value: spoke contract address common.Address
(through clever encoding of models.RegisteredSpoke
)
type RegisteredSpoke struct {
ID models.Uint256
Contract common.Address
}
- Holds batchID - finalisation block mapping
Key: batchID models.Uint256
Value: finalisation block uint32
type PendingStakeWithdrawal struct {
BatchID Uint256
FinalisationBlock uint32
}