Files
node/examples/multi-network/multi-network-poc.go
T
zeekayandHanzo Dev 0ba5d05bd8 Retire /ext/ endpoint prefix: /v1/ is THE endpoint
Route registration, client URL builders, and log lines all move to /v1/
(wallet primary api, chains/rpc handler_manager+chain_integration, xvm
client+wallet_client, xsvm api client, multi-network example, manager logs).
Zero /ext/ literals remain. One endpoint namespace, no transition alias.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 19:14:51 -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)
}