Files
zeekayandHanzo Dev b1cc108c9f gofmt
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 01:51:51 -07:00

144 lines
3.5 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"fmt"
"github.com/luxfi/database"
"github.com/luxfi/database/linkeddb"
"github.com/luxfi/database/prefixdb"
"github.com/luxfi/ids"
"github.com/luxfi/node/vms/platformvm/status"
"github.com/luxfi/node/vms/platformvm/txs"
lux "github.com/luxfi/utxo"
)
func (s *state) GetTx(txID ids.ID) (*txs.Tx, status.Status, error) {
if tx, exists := s.addedTxs[txID]; exists {
return tx.tx, tx.status, nil
}
if tx, cached := s.txCache.Get(txID); cached {
if tx == nil {
return nil, status.Unknown, database.ErrNotFound
}
return tx.tx, tx.status, nil
}
txBytes, err := s.txDB.Get(txID[:])
if err == database.ErrNotFound {
s.txCache.Put(txID, nil)
return nil, status.Unknown, database.ErrNotFound
}
if err != nil {
return nil, status.Unknown, err
}
stx, err := parseTxStatus(txBytes)
if err != nil {
return nil, status.Unknown, err
}
tx, err := txs.Parse(stx.Tx)
if err != nil {
return nil, status.Unknown, err
}
ptx := &txAndStatus{
tx: tx,
status: stx.Status,
}
s.txCache.Put(txID, ptx)
return ptx.tx, ptx.status, nil
}
func (s *state) AddTx(tx *txs.Tx, status status.Status) {
s.addedTxs[tx.ID()] = &txAndStatus{
tx: tx,
status: status,
}
}
func (s *state) GetRewardUTXOs(txID ids.ID) ([]*lux.UTXO, error) {
if utxos, exists := s.addedRewardUTXOs[txID]; exists {
return utxos, nil
}
if utxos, cached := s.rewardUTXOsCache.Get(txID); cached {
return utxos, nil
}
rawTxDB := prefixdb.New(txID[:], s.rewardUTXODB)
txDB := linkeddb.NewDefault(rawTxDB)
it := txDB.NewIterator()
defer it.Release()
utxos := []*lux.UTXO(nil)
for it.Next() {
utxo, err := lux.ParseUTXO(it.Value())
if err != nil {
return nil, err
}
utxos = append(utxos, utxo)
}
if err := it.Error(); err != nil {
return nil, err
}
s.rewardUTXOsCache.Put(txID, utxos)
return utxos, nil
}
func (s *state) AddRewardUTXO(txID ids.ID, utxo *lux.UTXO) {
s.addedRewardUTXOs[txID] = append(s.addedRewardUTXOs[txID], utxo)
}
func (s *state) writeTXs() error {
for txID, txStatus := range s.addedTxs {
stx := txBytesAndStatus{
Tx: txStatus.tx.Bytes(),
Status: txStatus.status,
}
// We serialize the [txBytesAndStatus] envelope natively (see
// statewire.go). The embedded tx keeps its own self-delimiting
// signed bytes so its TxID is preserved on re-parse.
txBytes, err := marshalTxStatus(stx)
if err != nil {
return fmt.Errorf("failed to serialize tx: %w", err)
}
delete(s.addedTxs, txID)
// Note: Evict is used rather than Put here because stx may end up
// referencing additional data (because of shared byte slices) that
// would not be properly accounted for in the cache sizing.
s.txCache.Evict(txID)
if err := s.txDB.Put(txID[:], txBytes); err != nil {
return fmt.Errorf("failed to add tx: %w", err)
}
}
return nil
}
func (s *state) writeRewardUTXOs() error {
for txID, utxos := range s.addedRewardUTXOs {
delete(s.addedRewardUTXOs, txID)
s.rewardUTXOsCache.Put(txID, utxos)
rawTxDB := prefixdb.New(txID[:], s.rewardUTXODB)
txDB := linkeddb.NewDefault(rawTxDB)
for _, utxo := range utxos {
utxoBytes, err := utxo.WireBytes()
if err != nil {
return fmt.Errorf("failed to serialize reward UTXO: %w", err)
}
utxoID := utxo.InputID()
if err := txDB.Put(utxoID[:], utxoBytes); err != nil {
return fmt.Errorf("failed to add reward UTXO: %w", err)
}
}
}
return nil
}