mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
vms/platformvm/... build + vet PASS with pcodecs/txs.Codec gone from the VM. Executor semantics (standard_tx_executor): - registerOwnSet(): shared primitive — per-validator state.L1Validator with native owner blobs (txs.MarshalOwner/UnmarshalOwner, no codec), active-set capacity check, EndAccumulatedFee=balance+accruedFees, SetNetToL1Conversion manager-authority recording (byte-for-byte legacy tail). - ConvertNetworkTx: promote endomorphism (owner-authorized, folds old ConvertNetworkToL1Tx), gated by security.Mode.Manager. - CreateNetworkTx: base (AddNet/SetNetOwner) + sovereign path registers own set. - Deleted CreateSovereignL1Tx + ConvertNetworkToL1Tx. - txs.UnmarshalOwner added: canonical owner marshal/unmarshal pair, no codec. All ~13 txs.Visitor impls carry ConvertNetworkTx; gossip/block Parse(b) codec-free; wallet/network/primary off txs.Codec. KNOWN GAP (pending design decision, NOT silently green): CreateNetworkTx reads tx.Chains() only to derive managerChainID — it does NOT create the genesis chains (no AddChain). Atomic-spawn-with-chains vs decomplect-to-CreateChainTx is the open call. 17 codec-era _test.go parked as .bak for follow-up rewrite. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
144 lines
3.5 KiB
Go
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"
|
|
lux "github.com/luxfi/utxo"
|
|
"github.com/luxfi/node/vms/platformvm/status"
|
|
"github.com/luxfi/node/vms/platformvm/txs"
|
|
)
|
|
|
|
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
|
|
}
|