mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
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>
261 lines
6.6 KiB
Go
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)
|
|
}
|