mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
221 lines
5.6 KiB
Go
221 lines
5.6 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package state
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/math"
|
|
"github.com/luxfi/node/vms/platformvm/warp"
|
|
)
|
|
|
|
var (
|
|
errWrongNonce = errors.New("wrong nonce")
|
|
errInsufficientBalance = errors.New("insufficient balance")
|
|
)
|
|
|
|
/*
|
|
* VMDB
|
|
* |-- initializedKey -> nil
|
|
* |-. blocks
|
|
* | |-- lastAcceptedKey -> blockID
|
|
* | |-- height -> blockID
|
|
* | '-- blockID -> block bytes
|
|
* |-. addresses
|
|
* | '-- addressID -> nonce
|
|
* | '-- addressID + chainID -> balance
|
|
* |-. chains
|
|
* | |-- chainID -> balance
|
|
* | '-- chainID + loanID -> nil
|
|
* '-. message
|
|
* '-- txID -> message bytes
|
|
*/
|
|
|
|
// Chain state
|
|
|
|
func IsInitialized(db database.KeyValueReader) (bool, error) {
|
|
return db.Has(initializedKey)
|
|
}
|
|
|
|
func SetInitialized(db database.KeyValueWriter) error {
|
|
return db.Put(initializedKey, nil)
|
|
}
|
|
|
|
// Block state
|
|
|
|
func GetLastAccepted(db database.KeyValueReader) (ids.ID, error) {
|
|
luxID, err := database.GetID(db, blockPrefix)
|
|
if err != nil {
|
|
return ids.Empty, err
|
|
}
|
|
return ids.ID(luxID), nil
|
|
}
|
|
|
|
func SetLastAccepted(db database.KeyValueWriter, blkID ids.ID) error {
|
|
luxID := ([32]byte)(blkID)
|
|
return database.PutID(db, blockPrefix, luxID)
|
|
}
|
|
|
|
func GetBlockIDByHeight(db database.KeyValueReader, height uint64) (ids.ID, error) {
|
|
key := Flatten(blockPrefix, database.PackUInt64(height))
|
|
luxID, err := database.GetID(db, key)
|
|
if err != nil {
|
|
return ids.Empty, err
|
|
}
|
|
return ids.ID(luxID), nil
|
|
}
|
|
|
|
func GetBlock(db database.KeyValueReader, blkID ids.ID) ([]byte, error) {
|
|
key := Flatten(blockPrefix, blkID[:])
|
|
return db.Get(key)
|
|
}
|
|
|
|
func AddBlock(db database.KeyValueWriter, height uint64, blkID ids.ID, blk []byte) error {
|
|
heightToIDKey := Flatten(blockPrefix, database.PackUInt64(height))
|
|
luxID := ([32]byte)(blkID)
|
|
if err := database.PutID(db, heightToIDKey, luxID); err != nil {
|
|
return err
|
|
}
|
|
idToBlockKey := Flatten(blockPrefix, blkID[:])
|
|
return db.Put(idToBlockKey, blk)
|
|
}
|
|
|
|
// Address state
|
|
|
|
func GetNonce(db database.KeyValueReader, address ids.ShortID) (uint64, error) {
|
|
key := Flatten(addressPrefix, address[:])
|
|
value, err := database.GetUInt64(db, key)
|
|
if err == database.ErrNotFound {
|
|
return 0, nil
|
|
}
|
|
return value, err
|
|
}
|
|
|
|
func SetNonce(db database.KeyValueWriter, address ids.ShortID, nonce uint64) error {
|
|
key := Flatten(addressPrefix, address[:])
|
|
return database.PutUInt64(db, key, nonce)
|
|
}
|
|
|
|
func IncrementNonce(db database.KeyValueReaderWriter, address ids.ShortID, nonce uint64) error {
|
|
expectedNonce, err := GetNonce(db, address)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if nonce != expectedNonce {
|
|
return errWrongNonce
|
|
}
|
|
return SetNonce(db, address, nonce+1)
|
|
}
|
|
|
|
func GetBalance(db database.KeyValueReader, address ids.ShortID, chainID ids.ID) (uint64, error) {
|
|
key := Flatten(addressPrefix, address[:], chainID[:])
|
|
value, err := database.GetUInt64(db, key)
|
|
if err == database.ErrNotFound {
|
|
return 0, nil
|
|
}
|
|
return value, err
|
|
}
|
|
|
|
func SetBalance(db database.KeyValueWriterDeleter, address ids.ShortID, chainID ids.ID, balance uint64) error {
|
|
key := Flatten(addressPrefix, address[:], chainID[:])
|
|
if balance == 0 {
|
|
return db.Delete(key)
|
|
}
|
|
return database.PutUInt64(db, key, balance)
|
|
}
|
|
|
|
func DecreaseBalance(db database.KeyValueReaderWriterDeleter, address ids.ShortID, chainID ids.ID, amount uint64) error {
|
|
balance, err := GetBalance(db, address, chainID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if balance < amount {
|
|
return errInsufficientBalance
|
|
}
|
|
return SetBalance(db, address, chainID, balance-amount)
|
|
}
|
|
|
|
func IncreaseBalance(db database.KeyValueReaderWriterDeleter, address ids.ShortID, chainID ids.ID, amount uint64) error {
|
|
balance, err := GetBalance(db, address, chainID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
balance, err = math.Add(balance, amount)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return SetBalance(db, address, chainID, balance)
|
|
}
|
|
|
|
// Chain state
|
|
|
|
func HasLoanID(db database.KeyValueReader, chainID ids.ID, loanID ids.ID) (bool, error) {
|
|
key := Flatten(chainPrefix, chainID[:], loanID[:])
|
|
return db.Has(key)
|
|
}
|
|
|
|
func AddLoanID(db database.KeyValueWriter, chainID ids.ID, loanID ids.ID) error {
|
|
key := Flatten(chainPrefix, chainID[:], loanID[:])
|
|
return db.Put(key, nil)
|
|
}
|
|
|
|
func GetLoan(db database.KeyValueReader, chainID ids.ID) (uint64, error) {
|
|
key := Flatten(chainPrefix, chainID[:])
|
|
value, err := database.GetUInt64(db, key)
|
|
if err == database.ErrNotFound {
|
|
return 0, nil
|
|
}
|
|
return value, err
|
|
}
|
|
|
|
func SetLoan(db database.KeyValueWriterDeleter, chainID ids.ID, balance uint64) error {
|
|
key := Flatten(chainPrefix, chainID[:])
|
|
if balance == 0 {
|
|
return db.Delete(key)
|
|
}
|
|
return database.PutUInt64(db, key, balance)
|
|
}
|
|
|
|
func DecreaseLoan(db database.KeyValueReaderWriterDeleter, chainID ids.ID, amount uint64) error {
|
|
balance, err := GetLoan(db, chainID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if balance < amount {
|
|
return errInsufficientBalance
|
|
}
|
|
return SetLoan(db, chainID, balance-amount)
|
|
}
|
|
|
|
func IncreaseLoan(db database.KeyValueReaderWriterDeleter, chainID ids.ID, amount uint64) error {
|
|
balance, err := GetLoan(db, chainID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
balance, err = math.Add(balance, amount)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return SetLoan(db, chainID, balance)
|
|
}
|
|
|
|
// Message state
|
|
|
|
func GetMessage(db database.KeyValueReader, txID ids.ID) (*warp.UnsignedMessage, error) {
|
|
key := Flatten(messagePrefix, txID[:])
|
|
bytes, err := db.Get(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return warp.ParseUnsignedMessage(bytes)
|
|
}
|
|
|
|
func SetMessage(db database.KeyValueWriter, txID ids.ID, message *warp.UnsignedMessage) error {
|
|
key := Flatten(messagePrefix, txID[:])
|
|
bytes := message.Bytes()
|
|
return db.Put(key, bytes)
|
|
}
|