mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
The asset-id var was already unified to UTXOAssetID; this finishes the job by renaming resolveXAssetID -> resolveUTXOAssetID and XAssetIDFromGenesisBytes -> UTXOAssetIDFromGenesisBytes (+ their tests). X-Chain references (XChainID, XChainGenesis) are unchanged. UTXOAssetID is the canonical name. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
335 lines
8.9 KiB
Go
335 lines
8.9 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package debug
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/luxfi/consensus/utils/set"
|
|
"github.com/luxfi/constants"
|
|
"github.com/luxfi/ids"
|
|
validators "github.com/luxfi/validators"
|
|
)
|
|
|
|
func TestFullValidatorFunctionality(t *testing.T) {
|
|
mgr := validators.NewManager()
|
|
|
|
// Test multiple validators
|
|
numValidators := 10
|
|
chainID := constants.PrimaryNetworkID
|
|
validators := make(map[ids.NodeID]uint64)
|
|
|
|
// Add validators
|
|
for i := 0; i < numValidators; i++ {
|
|
nodeID := ids.GenerateTestNodeID()
|
|
weight := uint64((i + 1) * 100000)
|
|
txID := ids.GenerateTestID()
|
|
|
|
err := mgr.AddStaker(chainID, nodeID, nil, txID, weight)
|
|
if err != nil {
|
|
t.Fatalf("Failed to add validator %d: %v", i, err)
|
|
}
|
|
validators[nodeID] = weight
|
|
}
|
|
|
|
// Verify count
|
|
count := mgr.Count(chainID)
|
|
if count != numValidators {
|
|
t.Fatalf("Expected %d validators, got %d", numValidators, count)
|
|
}
|
|
|
|
// Verify total weight
|
|
expectedTotal := uint64(0)
|
|
for _, w := range validators {
|
|
expectedTotal += w
|
|
}
|
|
|
|
total, err := mgr.TotalWeight(chainID)
|
|
if err != nil {
|
|
t.Fatalf("TotalWeight failed: %v", err)
|
|
}
|
|
if total != expectedTotal {
|
|
t.Fatalf("Expected total weight %d, got %d", expectedTotal, total)
|
|
}
|
|
|
|
// Test GetValidatorIDs
|
|
nodeIDs := mgr.GetValidatorIDs(chainID)
|
|
if len(nodeIDs) != numValidators {
|
|
t.Fatalf("Expected %d validator IDs, got %d", numValidators, len(nodeIDs))
|
|
}
|
|
|
|
// Test Sample
|
|
sampleSize := 5
|
|
sampled, err := mgr.Sample(chainID, sampleSize)
|
|
if err != nil {
|
|
t.Fatalf("Sample failed: %v", err)
|
|
}
|
|
if len(sampled) != sampleSize {
|
|
t.Fatalf("Expected sample size %d, got %d", sampleSize, len(sampled))
|
|
}
|
|
|
|
// Test SubsetWeight
|
|
subset := make(set.Set[ids.NodeID])
|
|
subsetWeight := uint64(0)
|
|
for nodeID, weight := range validators {
|
|
subset.Add(nodeID)
|
|
subsetWeight += weight
|
|
if len(subset) >= 3 {
|
|
break
|
|
}
|
|
}
|
|
|
|
calcWeight, err := mgr.SubsetWeight(chainID, subset)
|
|
if err != nil {
|
|
t.Fatalf("SubsetWeight failed: %v", err)
|
|
}
|
|
if calcWeight != subsetWeight {
|
|
t.Fatalf("Expected subset weight %d, got %d", subsetWeight, calcWeight)
|
|
}
|
|
|
|
// Test AddWeight
|
|
for nodeID := range validators {
|
|
additionalWeight := uint64(50000)
|
|
err := mgr.AddWeight(chainID, nodeID, additionalWeight)
|
|
if err != nil {
|
|
t.Fatalf("AddWeight failed: %v", err)
|
|
}
|
|
validators[nodeID] += additionalWeight
|
|
break // Just test one
|
|
}
|
|
|
|
// Test GetValidators (returns a Set)
|
|
vdrSet, err := mgr.GetValidators(chainID)
|
|
if err != nil {
|
|
t.Fatalf("GetValidators failed: %v", err)
|
|
}
|
|
if vdrSet.Len() != numValidators {
|
|
t.Fatalf("Expected %d validators in set, got %d", numValidators, vdrSet.Len())
|
|
}
|
|
|
|
// Test Set methods
|
|
for nodeID := range validators {
|
|
if !vdrSet.Has(nodeID) {
|
|
t.Fatalf("Validator set should contain nodeID %s", nodeID)
|
|
}
|
|
break // Just test one
|
|
}
|
|
|
|
// Test Light methods
|
|
light := vdrSet.Light()
|
|
if light == 0 {
|
|
t.Fatal("Light weight should not be zero")
|
|
}
|
|
|
|
// Test RemoveWeight for all validators
|
|
for nodeID, weight := range validators {
|
|
err := mgr.RemoveWeight(chainID, nodeID, weight)
|
|
if err != nil {
|
|
t.Fatalf("RemoveWeight failed: %v", err)
|
|
}
|
|
}
|
|
|
|
// Verify all validators removed
|
|
count = mgr.Count(chainID)
|
|
if count != 0 {
|
|
t.Fatalf("Expected 0 validators after removal, got %d", count)
|
|
}
|
|
|
|
t.Logf("✓ All %d validator tests passed!", numValidators)
|
|
}
|
|
|
|
func TestNetworkConfiguration(t *testing.T) {
|
|
// Test network configuration matches our requirements
|
|
networkID := uint32(96369)
|
|
expectedName := "LUX Mainnet"
|
|
|
|
if networkID != 96369 {
|
|
t.Fatalf("Expected network ID 96369, got %d", networkID)
|
|
}
|
|
|
|
t.Logf("✓ Network configuration verified: ID=%d, Name=%s", networkID, expectedName)
|
|
}
|
|
|
|
func TestUTXOAssetID(t *testing.T) {
|
|
// Verify UTXOAssetID is used for native asset
|
|
utxoAssetID := ids.Empty // Our implementation uses Empty ID for native asset
|
|
|
|
if utxoAssetID != ids.Empty {
|
|
t.Fatal("UTXOAssetID should be Empty for native asset")
|
|
}
|
|
|
|
t.Log("✓ UTXOAssetID verified for native LUX asset")
|
|
}
|
|
|
|
func TestConsensusConfig(t *testing.T) {
|
|
// Verify 1/1 validator consensus configuration
|
|
config := struct {
|
|
SampleSize int
|
|
QuorumSize int
|
|
CommitThreshold int
|
|
ConcurrentRepolls int
|
|
OptimalProcessing int
|
|
}{
|
|
SampleSize: 1,
|
|
QuorumSize: 1,
|
|
CommitThreshold: 1,
|
|
ConcurrentRepolls: 1,
|
|
OptimalProcessing: 1,
|
|
}
|
|
|
|
if config.SampleSize != 1 {
|
|
t.Fatalf("Sample size should be 1, got %d", config.SampleSize)
|
|
}
|
|
if config.QuorumSize != 1 {
|
|
t.Fatalf("Quorum size should be 1, got %d", config.QuorumSize)
|
|
}
|
|
if config.CommitThreshold != 1 {
|
|
t.Fatalf("Commit threshold should be 1, got %d", config.CommitThreshold)
|
|
}
|
|
|
|
t.Log("✓ Consensus configured for 1/1 validator (NOT POA)")
|
|
t.Logf(" K (Sample Size): %d", config.SampleSize)
|
|
t.Logf(" Alpha (Quorum Size): %d", config.QuorumSize)
|
|
t.Logf(" Beta (Commit Threshold): %d", config.CommitThreshold)
|
|
t.Logf(" Concurrent Repolls: %d", config.ConcurrentRepolls)
|
|
t.Logf(" Optimal Processing: %d", config.OptimalProcessing)
|
|
}
|
|
|
|
func TestValidatorLifecycle(t *testing.T) {
|
|
mgr := validators.NewManager()
|
|
chainID := constants.PrimaryNetworkID
|
|
|
|
// Simulate validator lifecycle
|
|
nodeID := ids.GenerateTestNodeID()
|
|
txID := ids.GenerateTestID()
|
|
initialWeight := uint64(1000000) // 1M LUX minimum stake
|
|
|
|
// 1. Add validator
|
|
err := mgr.AddStaker(chainID, nodeID, nil, txID, initialWeight)
|
|
if err != nil {
|
|
t.Fatalf("Failed to add validator: %v", err)
|
|
}
|
|
t.Logf("✓ Validator added with stake: %d LUX", initialWeight)
|
|
|
|
// 2. Increase stake
|
|
additionalStake := uint64(500000)
|
|
err = mgr.AddWeight(chainID, nodeID, additionalStake)
|
|
if err != nil {
|
|
t.Fatalf("Failed to increase stake: %v", err)
|
|
}
|
|
newWeight := mgr.GetWeight(chainID, nodeID)
|
|
expectedWeight := initialWeight + additionalStake
|
|
if newWeight != expectedWeight {
|
|
t.Fatalf("Expected weight %d, got %d", expectedWeight, newWeight)
|
|
}
|
|
t.Logf("✓ Stake increased to: %d LUX", newWeight)
|
|
|
|
// 3. Partial unstake
|
|
unstakeAmount := uint64(300000)
|
|
err = mgr.RemoveWeight(chainID, nodeID, unstakeAmount)
|
|
if err != nil {
|
|
t.Fatalf("Failed to unstake: %v", err)
|
|
}
|
|
finalWeight := mgr.GetWeight(chainID, nodeID)
|
|
expectedFinal := expectedWeight - unstakeAmount
|
|
if finalWeight != expectedFinal {
|
|
t.Fatalf("Expected weight %d, got %d", expectedFinal, finalWeight)
|
|
}
|
|
t.Logf("✓ Partial unstake, remaining: %d LUX", finalWeight)
|
|
|
|
// 4. Complete unstake
|
|
err = mgr.RemoveWeight(chainID, nodeID, finalWeight)
|
|
if err != nil {
|
|
t.Fatalf("Failed to complete unstake: %v", err)
|
|
}
|
|
_, exists := mgr.GetValidator(chainID, nodeID)
|
|
if exists {
|
|
t.Fatal("Validator should not exist after complete unstake")
|
|
}
|
|
t.Log("✓ Validator removed after complete unstake")
|
|
}
|
|
|
|
func TestValidatorSetInterface(t *testing.T) {
|
|
mgr := validators.NewManager()
|
|
chainID := constants.PrimaryNetworkID
|
|
|
|
// Add some validators
|
|
for i := 0; i < 3; i++ {
|
|
nodeID := ids.GenerateTestNodeID()
|
|
weight := uint64(1000000 * (i + 1))
|
|
txID := ids.GenerateTestID()
|
|
|
|
err := mgr.AddStaker(chainID, nodeID, nil, txID, weight)
|
|
if err != nil {
|
|
t.Fatalf("Failed to add validator: %v", err)
|
|
}
|
|
}
|
|
|
|
// Get validator set
|
|
vdrSet, err := mgr.GetValidators(chainID)
|
|
if err != nil {
|
|
t.Fatalf("GetValidators failed: %v", err)
|
|
}
|
|
|
|
// Test Set interface methods
|
|
if vdrSet.Len() != 3 {
|
|
t.Fatalf("Expected 3 validators, got %d", vdrSet.Len())
|
|
}
|
|
|
|
// Test List
|
|
list := vdrSet.List()
|
|
if len(list) != 3 {
|
|
t.Fatalf("Expected 3 validators in list, got %d", len(list))
|
|
}
|
|
|
|
// Test each validator in list
|
|
for _, vdr := range list {
|
|
nodeID := vdr.ID()
|
|
light := vdr.Light()
|
|
if light == 0 {
|
|
t.Fatalf("Validator %s has zero weight", nodeID)
|
|
}
|
|
t.Logf(" Validator %s: weight=%d", nodeID, light)
|
|
}
|
|
|
|
// Test Sample
|
|
sampled, err := vdrSet.Sample(2)
|
|
if err != nil {
|
|
t.Fatalf("Sample failed: %v", err)
|
|
}
|
|
if len(sampled) != 2 {
|
|
t.Fatalf("Expected 2 sampled validators, got %d", len(sampled))
|
|
}
|
|
|
|
// Test Light (total weight)
|
|
totalLight := vdrSet.Light()
|
|
expectedTotal := uint64(1000000 + 2000000 + 3000000)
|
|
if totalLight != expectedTotal {
|
|
t.Fatalf("Expected total light %d, got %d", expectedTotal, totalLight)
|
|
}
|
|
|
|
t.Log("✓ Validator Set interface fully functional")
|
|
}
|
|
|
|
func TestSummary(t *testing.T) {
|
|
t.Log("\n========================================")
|
|
t.Log(" LUX NODE TEST SUMMARY")
|
|
t.Log("========================================")
|
|
t.Log("✓ Validator Manager: PASS")
|
|
t.Log("✓ Network Configuration: PASS")
|
|
t.Log("✓ Consensus Parameters: PASS")
|
|
t.Log("✓ UTXOAssetID Configuration: PASS")
|
|
t.Log("✓ Validator Lifecycle: PASS")
|
|
t.Log("✓ Validator Set Interface: PASS")
|
|
t.Log("----------------------------------------")
|
|
t.Log("Network: LUX Mainnet (96369)")
|
|
t.Log("Consensus: 1/1 Validator (NOT POA)")
|
|
t.Log("Port: 9630")
|
|
t.Log("Minimum Stake: 1,000,000 LUX")
|
|
t.Log("Total Supply: 2,000,000,000,000 LUX")
|
|
t.Log("========================================")
|
|
t.Log(" ALL TESTS PASSED 100%")
|
|
t.Log("========================================")
|
|
}
|