Files
zeekay 3183dab89c Make the whole module build and test again after the port
go list ./... returned nothing, so no package here could be built or tested and
the failure was invisible: one directory held a Go test beside fifteen .cpp
files, which makes it a Go package the toolchain then refuses. The generator
moves to the golden/ subdirectory the other two C++ chains already use.

That silence was hiding a package that does not compile. host/ calls
EnsureIdentity and identity.go defines LoadIdentity — a rename that happened on
one side — and it has no importers, because the Go host is cmd/luxd now. Deleted
rather than repaired: the thing it was a stand-in for arrived.

The operator tools came across too (backup, blscheck, ceremony, config,
genesishash, keytoaddr, pqkeygen, repair-proposervm, wire) plus benchmarks and
examples, so the package set now differs from the retired repo by exactly one
name: main/ is cmd/luxd.

Two tests were right and are now satisfied rather than silenced. The purity test
looked for ./main; it looks where the daemon lives. The chain-address test found
conformance/dex spelling /v1/chain by hand — but that is its own module on
purpose, since it links an EVM ABI and a signer the node must not carry, so it
cannot call Chain. The rule is about this module, and the walk now says so.
2026-09-07 17:16:26 -07:00

261 lines
6.6 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Multi-Network Validation Proof of Concept
// This demonstrates how a single Lux Node could validate multiple networks
package main
import (
"fmt"
"log"
"net/http"
"sync"
"time"
"github.com/luxfi/constants"
)
// NetworkValidator represents a validator for a specific network
type NetworkValidator struct {
NetworkID uint32
NetworkName string
RPCPort int
Validators int
ChainID string
Active bool
mu sync.RWMutex
}
// MultiNetworkNode represents a node validating multiple networks
type MultiNetworkNode struct {
Networks map[uint32]*NetworkValidator
mu sync.RWMutex
}
// NewMultiNetworkNode creates a new multi-network node
// Network IDs: 1 (mainnet), 2 (testnet), 3 (devnet) - P-Chain identifiers
// Chain IDs: 96369, 96368, 96370 - C-Chain EVM identifiers (can be used as aliases)
func NewMultiNetworkNode() *MultiNetworkNode {
return &MultiNetworkNode{
Networks: map[uint32]*NetworkValidator{
constants.MainnetID: { // 1
NetworkID: constants.MainnetID,
NetworkName: "Lux Mainnet",
RPCPort: 9630,
Validators: 5,
ChainID: "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM",
Active: true,
},
constants.TestnetID: { // 2
NetworkID: constants.TestnetID,
NetworkName: "Lux Testnet",
RPCPort: 9620,
Validators: 5,
ChainID: "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm",
Active: true,
},
200200: { // Zoo chain Chain ID
NetworkID: 200200,
NetworkName: "Zoo Network",
RPCPort: 2000,
Validators: 5,
ChainID: "2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt",
Active: true,
},
// Q-Chain is part of the primary network (mainnet ID 1)
// and no longer has a separate network ID — see the
// MainnetID entry above. The Q-Chain blockchain ID lives
// in luxfi/constants.QChainID; consumers can read it from
// the primary-network entry's chain registry rather than
// from a duplicate top-level map entry here.
},
}
}
// StartRPCServer starts the unified RPC server
func (n *MultiNetworkNode) StartRPCServer(port int) {
http.HandleFunc("/v1/crossnet/status", n.handleCrossNetStatus)
http.HandleFunc("/v1/crossnet/validators", n.handleCrossNetValidators)
http.HandleFunc("/v1/network/", n.handleNetworkSpecific)
fmt.Printf("🌐 Multi-Network RPC Server starting on port %d\n", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}
// handleCrossNetStatus returns status of all networks
func (n *MultiNetworkNode) handleCrossNetStatus(w http.ResponseWriter, r *http.Request) {
n.mu.RLock()
defer n.mu.RUnlock()
response := `{
"networks": [`
first := true
for _, network := range n.Networks {
if !first {
response += ","
}
response += fmt.Sprintf(`
{
"networkID": %d,
"networkName": "%s",
"active": %t,
"validators": %d,
"chainID": "%s",
"rpcEndpoint": "http://localhost:%d"
}`,
network.NetworkID,
network.NetworkName,
network.Active,
network.Validators,
network.ChainID,
network.RPCPort,
)
first = false
}
response += `
]
}`
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(response))
}
// handleCrossNetValidators returns validators across all networks
func (n *MultiNetworkNode) handleCrossNetValidators(w http.ResponseWriter, r *http.Request) {
n.mu.RLock()
defer n.mu.RUnlock()
totalValidators := 0
for _, network := range n.Networks {
if network.Active {
totalValidators += network.Validators
}
}
response := fmt.Sprintf(`{
"totalNetworks": %d,
"totalValidators": %d,
"networks": {`,
len(n.Networks),
totalValidators,
)
first := true
for id, network := range n.Networks {
if !first {
response += ","
}
response += fmt.Sprintf(`
"%d": {
"name": "%s",
"validators": %d,
"active": %t
}`,
id,
network.NetworkName,
network.Validators,
network.Active,
)
first = false
}
response += `
}
}`
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(response))
}
// handleNetworkSpecific routes to network-specific handlers
func (n *MultiNetworkNode) handleNetworkSpecific(w http.ResponseWriter, r *http.Request) {
// Parse network ID from path: /v1/network/{networkID}/...
// This would route to the appropriate network's chain manager
response := fmt.Sprintf(`{
"message": "Network-specific routing would happen here",
"path": "%s",
"method": "%s"
}`, r.URL.Path, r.Method)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(response))
}
// ValidateNetwork simulates validation for a specific network
func (n *MultiNetworkNode) ValidateNetwork(networkID uint32) {
network, exists := n.Networks[networkID]
if !exists {
log.Printf("Network %d not found", networkID)
return
}
log.Printf("šŸ”· Starting validation for %s (Network ID: %d)", network.NetworkName, networkID)
// In real implementation, this would:
// 1. Connect to network-specific bootstrappers
// 2. Sync network-specific blockchain data
// 3. Participate in network-specific consensus
// 4. Store data in network-specific database
for {
network.mu.RLock()
if !network.Active {
network.mu.RUnlock()
break
}
network.mu.RUnlock()
// Simulate validation work
time.Sleep(10 * time.Second)
log.Printf("āœ… Validated block on %s", network.NetworkName)
}
}
// StartAllValidators starts validation for all networks
func (n *MultiNetworkNode) StartAllValidators() {
var wg sync.WaitGroup
for networkID := range n.Networks {
wg.Add(1)
go func(id uint32) {
defer wg.Done()
n.ValidateNetwork(id)
}(networkID)
}
// Don't wait - let validators run in background
go func() {
wg.Wait()
log.Println("All validators stopped")
}()
}
func main() {
fmt.Println("šŸš€ Lux Multi-Network Validator POC")
fmt.Println("=====================================")
node := NewMultiNetworkNode()
// Start validation for all networks
node.StartAllValidators()
// Start unified RPC server
fmt.Println("\nšŸ“Š Network Status:")
for id, network := range node.Networks {
fmt.Printf(" • %s (ID: %d) - %d validators\n",
network.NetworkName, id, network.Validators)
}
fmt.Println("\n🌐 Starting Multi-Network RPC Server...")
fmt.Println(" • Cross-network status: http://localhost:9650/v1/crossnet/status")
fmt.Println(" • Cross-network validators: http://localhost:9650/v1/crossnet/validators")
fmt.Println(" • Network-specific: http://localhost:9650/v1/network/{networkID}/...")
// This would be replaced with actual RPC server
node.StartRPCServer(9650)
}