mirror of
https://github.com/luxfi/proto.git
synced 2026-10-30 15:21:09 +00:00
proto required luxfi/node and luxfi/node required proto, with no replace directive on either side. The cycle was not load-bearing: most of it was proto reaching into the node for packages proto already owns — p/warp, p/txs, p/signer, p/stakeable, p/security, x/txs — which now name themselves. Two were real. The UTXO components moved here, where the chains that use them already live, and the node is the only other caller, so that dependency now runs one way. And p/config held the node's chain manager to queue a chain the P-Chain had accepted a CreateChainTx for; it calls one method, so it declares one method. A P-Chain that imports the node to describe QueueChainCreation is what made two modules require each other. Dropping the requirement dropped a registration with it: lux.ParseUTXO is a registry filled by an init, which the node used to link in on proto's behalf. The packages that call it now say so themselves. Co-authored-by: Hanzo Dev <[email protected]>
111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package lux
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/math/set"
|
|
"github.com/luxfi/util"
|
|
|
|
safemath "github.com/luxfi/math"
|
|
)
|
|
|
|
// GetBalance returns the current balance of [addrs]
|
|
func GetBalance(db UTXOReader, addrs set.Set[ids.ShortID]) (uint64, error) {
|
|
utxos, err := GetAllUTXOs(db, addrs)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("couldn't get UTXOs: %w", err)
|
|
}
|
|
balance := uint64(0)
|
|
for _, utxo := range utxos {
|
|
if out, ok := utxo.Out.(Amounter); ok {
|
|
balance, err = safemath.Add64(out.Amount(), balance)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
}
|
|
return balance, nil
|
|
}
|
|
|
|
func GetAllUTXOs(db UTXOReader, addrs set.Set[ids.ShortID]) ([]*UTXO, error) {
|
|
utxos, _, _, err := GetPaginatedUTXOs(
|
|
db,
|
|
addrs,
|
|
ids.ShortEmpty,
|
|
ids.Empty,
|
|
math.MaxInt,
|
|
)
|
|
return utxos, err
|
|
}
|
|
|
|
// GetPaginatedUTXOs returns UTXOs such that at least one of the addresses in
|
|
// [addrs] is referenced.
|
|
//
|
|
// Returns at most [limit] UTXOs.
|
|
//
|
|
// Only returns UTXOs associated with addresses >= [startAddr].
|
|
//
|
|
// For address [startAddr], only returns UTXOs whose IDs are greater than
|
|
// [startUTXOID].
|
|
//
|
|
// Returns:
|
|
// * The fetched UTXOs
|
|
// * The address associated with the last UTXO fetched
|
|
// * The ID of the last UTXO fetched
|
|
func GetPaginatedUTXOs(
|
|
db UTXOReader,
|
|
addrs set.Set[ids.ShortID],
|
|
lastAddr ids.ShortID,
|
|
lastUTXOID ids.ID,
|
|
limit int,
|
|
) ([]*UTXO, ids.ShortID, ids.ID, error) {
|
|
var (
|
|
utxos []*UTXO
|
|
seen = set.NewSet[ids.ID](limit) // IDs of UTXOs already in the list
|
|
searchSize = limit // the limit diminishes which can impact the expected return
|
|
addrsList = addrs.List()
|
|
)
|
|
utils.Sort(addrsList) // enforces the same ordering for pagination
|
|
for _, addr := range addrsList {
|
|
start := ids.Empty
|
|
if comp := bytes.Compare(addr.Bytes(), lastAddr.Bytes()); comp == -1 { // Skip addresses before [startAddr]
|
|
continue
|
|
} else if comp == 0 {
|
|
start = lastUTXOID
|
|
}
|
|
|
|
lastAddr = addr // The last address searched
|
|
|
|
utxoIDs, err := db.UTXOIDs(addr.Bytes(), start, searchSize) // Get UTXOs associated with [addr]
|
|
if err != nil {
|
|
return nil, ids.ShortID{}, ids.Empty, fmt.Errorf("couldn't get UTXOs for address %s: %w", addr, err)
|
|
}
|
|
for _, utxoID := range utxoIDs {
|
|
lastUTXOID = utxoID // The last searched UTXO - not the last found
|
|
|
|
if seen.Contains(utxoID) { // Already have this UTXO in the list
|
|
continue
|
|
}
|
|
|
|
utxo, err := db.GetUTXO(utxoID)
|
|
if err != nil {
|
|
return nil, ids.ShortID{}, ids.Empty, fmt.Errorf("couldn't get UTXO %s: %w", utxoID, err)
|
|
}
|
|
|
|
utxos = append(utxos, utxo)
|
|
seen.Add(utxoID)
|
|
limit--
|
|
if limit <= 0 {
|
|
return utxos, lastAddr, lastUTXOID, nil // Found [limit] utxos; stop.
|
|
}
|
|
}
|
|
}
|
|
return utxos, lastAddr, lastUTXOID, nil // Didn't reach the [limit] utxos; no more were found
|
|
}
|