mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-10-06 15:29:07 +00:00
Refactor node and bootstrap configurations for improved clarity and consistency; unify RQLite and Raft ports across nodes, update environment setup, and enhance logging for node operations.
This commit is contained in:
parent
0a0756d4da
commit
cd74a2df68
23
.env.example
23
.env.example
@ -1,17 +1,14 @@
|
|||||||
# Bootstrap Node Configuration
|
# Example Environment Configuration for Development
|
||||||
# Add multiple bootstrap peers separated by commas for redundancy
|
# Copy this to .env and modify as needed
|
||||||
|
|
||||||
# Primary bootstrap peer (currently running)
|
# Bootstrap peers for development (localhost)
|
||||||
BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j
|
BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j
|
||||||
|
|
||||||
# Example with multiple bootstrap peers:
|
# Environment setting (development or production)
|
||||||
# BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j,/ip4/127.0.0.1/tcp/4002/p2p/12D3KooWSecondBootstrapPeer,/ip4/192.168.1.100/tcp/4001/p2p/12D3KooWRemoteBootstrapPeer
|
|
||||||
|
|
||||||
# For production, you would add external IPs:
|
|
||||||
# BOOTSTRAP_PEERS=/ip4/bootstrap1.example.com/tcp/4001/p2p/12D3KooWPeer1,/ip4/bootstrap2.example.com/tcp/4001/p2p/12D3KooWPeer2
|
|
||||||
|
|
||||||
# Default bootstrap port
|
|
||||||
BOOTSTRAP_PORT=4001
|
|
||||||
|
|
||||||
# Environment (development, staging, production)
|
|
||||||
ENVIRONMENT=development
|
ENVIRONMENT=development
|
||||||
|
|
||||||
|
# Note: In production, set ENVIRONMENT=production and the bootstrap.go will automatically
|
||||||
|
# use the production bootstrap peers defined in constants/bootstrap.go
|
||||||
|
|
||||||
|
# For multiple bootstrap peers, separate with commas:
|
||||||
|
# BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/peer1,/ip4/127.0.0.1/tcp/4005/p2p/peer2
|
||||||
|
48
Makefile
48
Makefile
@ -1,13 +1,12 @@
|
|||||||
# Network - Distributed P2P Database System
|
# Network - Distributed P2P Database System
|
||||||
# Makefile for development and build tasks
|
# Makefile for development and build tasks
|
||||||
|
|
||||||
.PHONY: build clean test run-bootstrap run-node run-example deps tidy fmt vet
|
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet
|
||||||
|
|
||||||
# Build targets
|
# Build targets
|
||||||
build: deps
|
build: deps
|
||||||
@echo "Building network executables..."
|
@echo "Building network executables..."
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
go build -o bin/bootstrap cmd/bootstrap/main.go
|
|
||||||
go build -o bin/node cmd/node/main.go
|
go build -o bin/node cmd/node/main.go
|
||||||
go build -o bin/network-cli cmd/cli/main.go
|
go build -o bin/network-cli cmd/cli/main.go
|
||||||
@echo "Build complete!"
|
@echo "Build complete!"
|
||||||
@ -24,16 +23,21 @@ test:
|
|||||||
@echo "Running tests..."
|
@echo "Running tests..."
|
||||||
go test -v ./...
|
go test -v ./...
|
||||||
|
|
||||||
# Run bootstrap node
|
# Run node (auto-detects if bootstrap or regular based on configuration)
|
||||||
run-bootstrap:
|
|
||||||
@echo "Starting bootstrap node..."
|
|
||||||
go run cmd/bootstrap/main.go -port 4001 -data ./data/bootstrap
|
|
||||||
|
|
||||||
# Run regular node
|
|
||||||
run-node:
|
run-node:
|
||||||
@echo "Starting regular node..."
|
@echo "Starting network node..."
|
||||||
go run cmd/node/main.go -data ./data/node
|
go run cmd/node/main.go -data ./data/node
|
||||||
|
|
||||||
|
# Run second node with different identity
|
||||||
|
run-node2:
|
||||||
|
@echo "Starting second network node..."
|
||||||
|
go run cmd/node/main.go -id node2
|
||||||
|
|
||||||
|
# Run third node with different identity
|
||||||
|
run-node3:
|
||||||
|
@echo "Starting third network node..."
|
||||||
|
go run cmd/node/main.go -id node3
|
||||||
|
|
||||||
# Show current bootstrap configuration
|
# Show current bootstrap configuration
|
||||||
show-bootstrap:
|
show-bootstrap:
|
||||||
@echo "Current bootstrap configuration from .env:"
|
@echo "Current bootstrap configuration from .env:"
|
||||||
@ -106,7 +110,7 @@ vet:
|
|||||||
# Development setup
|
# Development setup
|
||||||
dev-setup: deps
|
dev-setup: deps
|
||||||
@echo "Setting up development environment..."
|
@echo "Setting up development environment..."
|
||||||
@mkdir -p data/bootstrap data/node1 data/node2
|
@mkdir -p data/bootstrap data/node data/node-node2 data/node-node3
|
||||||
@mkdir -p data/test-bootstrap data/test-node1 data/test-node2
|
@mkdir -p data/test-bootstrap data/test-node1 data/test-node2
|
||||||
@mkdir -p anchat/bin
|
@mkdir -p anchat/bin
|
||||||
@echo "Development setup complete!"
|
@echo "Development setup complete!"
|
||||||
@ -138,15 +142,16 @@ test-consensus: build
|
|||||||
# Start development cluster (requires multiple terminals)
|
# Start development cluster (requires multiple terminals)
|
||||||
dev-cluster:
|
dev-cluster:
|
||||||
@echo "To start a development cluster, run these commands in separate terminals:"
|
@echo "To start a development cluster, run these commands in separate terminals:"
|
||||||
@echo "1. make run-bootstrap # Start bootstrap node"
|
@echo "1. make run-node # Start first node (auto-detects as bootstrap in dev)"
|
||||||
@echo "2. make run-node # Start regular node (auto-loads bootstrap from .env)"
|
@echo "2. make run-node2 # Start second node with different identity"
|
||||||
@echo "3. make run-example # Test basic functionality"
|
@echo "3. make run-node3 # Start third node with different identity"
|
||||||
@echo "4. make run-anchat # Start messaging app"
|
@echo "4. make run-example # Test basic functionality"
|
||||||
@echo "5. make show-bootstrap # Check bootstrap configuration"
|
@echo "5. make run-anchat # Start messaging app"
|
||||||
@echo "6. make cli-health # Check network health"
|
@echo "6. make show-bootstrap # Check bootstrap configuration"
|
||||||
@echo "7. make cli-peers # List peers"
|
@echo "7. make cli-health # Check network health"
|
||||||
@echo "8. make cli-storage-test # Test storage"
|
@echo "8. make cli-peers # List peers"
|
||||||
@echo "9. make cli-pubsub-test # Test messaging"
|
@echo "9. make cli-storage-test # Test storage"
|
||||||
|
@echo "10. make cli-pubsub-test # Test messaging"
|
||||||
|
|
||||||
# Full development workflow
|
# Full development workflow
|
||||||
dev: clean build build-anchat test
|
dev: clean build build-anchat test
|
||||||
@ -159,8 +164,9 @@ help:
|
|||||||
@echo " build-anchat - Build Anchat application"
|
@echo " build-anchat - Build Anchat application"
|
||||||
@echo " clean - Clean build artifacts"
|
@echo " clean - Clean build artifacts"
|
||||||
@echo " test - Run tests"
|
@echo " test - Run tests"
|
||||||
@echo " run-bootstrap - Start bootstrap node"
|
@echo " run-node - Start network node (auto-detects bootstrap vs regular)"
|
||||||
@echo " run-node - Start regular node (auto-loads bootstrap from .env)"
|
@echo " run-node2 - Start second node with different identity"
|
||||||
|
@echo " run-node3 - Start third node with different identity"
|
||||||
@echo " run-example - Run usage example"
|
@echo " run-example - Run usage example"
|
||||||
@echo " run-anchat - Run Anchat demo"
|
@echo " run-anchat - Run Anchat demo"
|
||||||
@echo " run-cli - Run network CLI help"
|
@echo " run-cli - Run network CLI help"
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
|
||||||
"git.debros.io/DeBros/network/pkg/logging"
|
|
||||||
"git.debros.io/DeBros/network/pkg/node"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var (
|
|
||||||
dataDir = flag.String("data", "./data/bootstrap", "Data directory")
|
|
||||||
port = flag.Int("port", 4001, "Listen port")
|
|
||||||
help = flag.Bool("help", false, "Show help")
|
|
||||||
)
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *help {
|
|
||||||
flag.Usage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create colored logger for bootstrap
|
|
||||||
logger, err := logging.NewStandardLogger(logging.ComponentBootstrap)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to create logger: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load configuration
|
|
||||||
cfg := config.BootstrapConfig()
|
|
||||||
cfg.Node.DataDir = *dataDir
|
|
||||||
cfg.Node.ListenAddresses = []string{
|
|
||||||
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *port),
|
|
||||||
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", *port),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure RQLite ports for bootstrap node
|
|
||||||
cfg.Database.RQLitePort = *port + 1000 // e.g., 5001 for bootstrap port 4001
|
|
||||||
cfg.Database.RQLiteRaftPort = *port + 3000 // e.g., 7001 for bootstrap port 4001 (changed to avoid conflicts)
|
|
||||||
cfg.Database.RQLiteJoinAddress = "" // Bootstrap node doesn't join anyone
|
|
||||||
|
|
||||||
logger.Printf("Starting bootstrap node...")
|
|
||||||
logger.Printf("Data directory: %s", cfg.Node.DataDir)
|
|
||||||
logger.Printf("Listen addresses: %v", cfg.Node.ListenAddresses)
|
|
||||||
logger.Printf("RQLite HTTP port: %d", cfg.Database.RQLitePort)
|
|
||||||
logger.Printf("RQLite Raft port: %d", cfg.Database.RQLiteRaftPort)
|
|
||||||
|
|
||||||
// Create context for graceful shutdown
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// Start bootstrap node in a goroutine
|
|
||||||
errChan := make(chan error, 1)
|
|
||||||
go func() {
|
|
||||||
if err := startBootstrapNode(ctx, cfg, *port, logger); err != nil {
|
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Wait for interrupt signal or error
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case err := <-errChan:
|
|
||||||
logger.Printf("Failed to start bootstrap node: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
case <-c:
|
|
||||||
logger.Printf("Shutting down bootstrap node...")
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startBootstrapNode(ctx context.Context, cfg *config.Config, port int, logger *logging.StandardLogger) error {
|
|
||||||
// Create and start bootstrap node using the new node implementation
|
|
||||||
n, err := node.NewNode(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create bootstrap node: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := n.Start(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to start bootstrap node: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the peer ID to a file for CLI access
|
|
||||||
peerID := n.GetPeerID()
|
|
||||||
peerInfoFile := filepath.Join(cfg.Node.DataDir, "peer.info")
|
|
||||||
peerMultiaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/%s", port, peerID)
|
|
||||||
|
|
||||||
if err := os.WriteFile(peerInfoFile, []byte(peerMultiaddr), 0644); err != nil {
|
|
||||||
logger.Printf("Warning: Failed to save peer info: %v", err)
|
|
||||||
} else {
|
|
||||||
logger.Printf("Peer info saved to: %s", peerInfoFile)
|
|
||||||
logger.Printf("Bootstrap multiaddr: %s", peerMultiaddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Printf("Bootstrap node started successfully")
|
|
||||||
|
|
||||||
// Wait for context cancellation
|
|
||||||
<-ctx.Done()
|
|
||||||
|
|
||||||
// Stop node
|
|
||||||
return n.Stop()
|
|
||||||
}
|
|
170
cmd/node/main.go
170
cmd/node/main.go
@ -7,18 +7,21 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/config"
|
"git.debros.io/DeBros/network/pkg/config"
|
||||||
"git.debros.io/DeBros/network/pkg/constants"
|
"git.debros.io/DeBros/network/pkg/constants"
|
||||||
|
"git.debros.io/DeBros/network/pkg/logging"
|
||||||
"git.debros.io/DeBros/network/pkg/node"
|
"git.debros.io/DeBros/network/pkg/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
dataDir = flag.String("data", "./data/node", "Data directory")
|
dataDir = flag.String("data", "", "Data directory (auto-detected if not provided)")
|
||||||
port = flag.Int("port", 4002, "Listen port")
|
nodeID = flag.String("id", "", "Node identifier (for running multiple local nodes)")
|
||||||
bootstrap = flag.String("bootstrap", "", "Bootstrap peer address")
|
bootstrap = flag.String("bootstrap", "", "Bootstrap peer address (for manual override)")
|
||||||
help = flag.Bool("help", false, "Show help")
|
help = flag.Bool("help", false, "Show help")
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -28,48 +31,88 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load configuration
|
// Auto-detect if this is a bootstrap node based on configuration
|
||||||
cfg := config.DefaultConfig()
|
isBootstrap := isBootstrapNode()
|
||||||
|
|
||||||
|
// Set default data directory if not provided
|
||||||
|
if *dataDir == "" {
|
||||||
|
if isBootstrap {
|
||||||
|
*dataDir = "./data/bootstrap"
|
||||||
|
} else {
|
||||||
|
if *nodeID != "" {
|
||||||
|
*dataDir = fmt.Sprintf("./data/node-%s", *nodeID)
|
||||||
|
} else {
|
||||||
|
*dataDir = "./data/node"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All nodes use port 4001 for consistency
|
||||||
|
port := 4001
|
||||||
|
|
||||||
|
// Create logger with appropriate component type
|
||||||
|
var logger *logging.StandardLogger
|
||||||
|
var err error
|
||||||
|
if isBootstrap {
|
||||||
|
logger, err = logging.NewStandardLogger(logging.ComponentBootstrap)
|
||||||
|
} else {
|
||||||
|
logger, err = logging.NewStandardLogger(logging.ComponentNode)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create logger: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load configuration based on node type
|
||||||
|
var cfg *config.Config
|
||||||
|
if isBootstrap {
|
||||||
|
cfg = config.BootstrapConfig()
|
||||||
|
logger.Printf("Starting bootstrap node...")
|
||||||
|
} else {
|
||||||
|
cfg = config.DefaultConfig()
|
||||||
|
logger.Printf("Starting regular node...")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set basic configuration
|
||||||
cfg.Node.DataDir = *dataDir
|
cfg.Node.DataDir = *dataDir
|
||||||
cfg.Node.ListenAddresses = []string{
|
cfg.Node.ListenAddresses = []string{
|
||||||
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *port),
|
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", port),
|
||||||
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", *port),
|
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", port),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure RQLite ports based on node port (only if not already set in config)
|
// All nodes use the same RQLite port (4001) to join the same cluster
|
||||||
if cfg.Database.RQLitePort == 0 {
|
cfg.Database.RQLitePort = 4001
|
||||||
cfg.Database.RQLitePort = *port + 1000 // e.g., 5002 for node port 4002
|
cfg.Database.RQLiteRaftPort = 4002
|
||||||
}
|
|
||||||
if cfg.Database.RQLiteRaftPort == 0 {
|
|
||||||
cfg.Database.RQLiteRaftPort = *port + 3000 // e.g., 7002 for node port 4002 (changed to avoid conflicts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure bootstrap peers
|
if isBootstrap {
|
||||||
|
// Bootstrap node doesn't join anyone - it starts the cluster
|
||||||
|
cfg.Database.RQLiteJoinAddress = ""
|
||||||
|
logger.Printf("Bootstrap node - starting new RQLite cluster")
|
||||||
|
} else {
|
||||||
|
// Regular nodes join the bootstrap node's RQLite cluster
|
||||||
|
cfg.Database.RQLiteJoinAddress = "http://localhost:4001"
|
||||||
|
|
||||||
|
// Configure bootstrap peers for P2P discovery
|
||||||
if *bootstrap != "" {
|
if *bootstrap != "" {
|
||||||
// Use command line bootstrap if provided
|
// Use command line bootstrap if provided
|
||||||
cfg.Discovery.BootstrapPeers = []string{*bootstrap}
|
cfg.Discovery.BootstrapPeers = []string{*bootstrap}
|
||||||
log.Printf("Using command line bootstrap peer: %s", *bootstrap)
|
logger.Printf("Using command line bootstrap peer: %s", *bootstrap)
|
||||||
} else {
|
} else {
|
||||||
// Use environment-configured bootstrap peers
|
// Use environment-configured bootstrap peers
|
||||||
bootstrapPeers := constants.GetBootstrapPeers()
|
bootstrapPeers := constants.GetBootstrapPeers()
|
||||||
if len(bootstrapPeers) > 0 {
|
if len(bootstrapPeers) > 0 {
|
||||||
cfg.Discovery.BootstrapPeers = bootstrapPeers
|
cfg.Discovery.BootstrapPeers = bootstrapPeers
|
||||||
log.Printf("Using environment bootstrap peers: %v", bootstrapPeers)
|
logger.Printf("Using environment bootstrap peers: %v", bootstrapPeers)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Warning: No bootstrap peers configured")
|
logger.Printf("Warning: No bootstrap peers configured")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
logger.Printf("Regular node - joining RQLite cluster at: %s", cfg.Database.RQLiteJoinAddress)
|
||||||
|
}
|
||||||
|
|
||||||
// For LibP2P peer discovery testing, don't join RQLite cluster
|
logger.Printf("Data directory: %s", cfg.Node.DataDir)
|
||||||
// Each node will have its own independent RQLite instance
|
logger.Printf("Listen addresses: %v", cfg.Node.ListenAddresses)
|
||||||
cfg.Database.RQLiteJoinAddress = "" // Keep RQLite independent
|
logger.Printf("RQLite HTTP port: %d", cfg.Database.RQLitePort)
|
||||||
|
logger.Printf("RQLite Raft port: %d", cfg.Database.RQLiteRaftPort)
|
||||||
log.Printf("Starting network node...")
|
|
||||||
log.Printf("Data directory: %s", cfg.Node.DataDir)
|
|
||||||
log.Printf("Listen addresses: %v", cfg.Node.ListenAddresses)
|
|
||||||
log.Printf("Bootstrap peers: %v", cfg.Discovery.BootstrapPeers)
|
|
||||||
log.Printf("RQLite HTTP port: %d", cfg.Database.RQLitePort)
|
|
||||||
log.Printf("RQLite Raft port: %d", cfg.Database.RQLiteRaftPort)
|
|
||||||
|
|
||||||
// Create context for graceful shutdown
|
// Create context for graceful shutdown
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@ -78,7 +121,7 @@ func main() {
|
|||||||
// Start node in a goroutine
|
// Start node in a goroutine
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
if err := startNode(ctx, cfg); err != nil {
|
if err := startNode(ctx, cfg, port, isBootstrap, logger); err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -89,15 +132,60 @@ func main() {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
log.Fatalf("Failed to start node: %v", err)
|
logger.Printf("Failed to start node: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
case <-c:
|
case <-c:
|
||||||
log.Printf("Shutting down node...")
|
logger.Printf("Shutting down node...")
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNode(ctx context.Context, cfg *config.Config) error {
|
// isBootstrapNode determines if this should be a bootstrap node
|
||||||
// Create and start node
|
// by checking the local machine's configuration and bootstrap peer list
|
||||||
|
func isBootstrapNode() bool {
|
||||||
|
// Get the bootstrap peer addresses to check if this machine should be a bootstrap
|
||||||
|
bootstrapPeers := constants.GetBootstrapPeers()
|
||||||
|
|
||||||
|
// Check if any bootstrap peer is localhost/127.0.0.1 (development)
|
||||||
|
// or if we're running on a production bootstrap server
|
||||||
|
hostname, _ := os.Hostname()
|
||||||
|
|
||||||
|
for _, peerAddr := range bootstrapPeers {
|
||||||
|
// Parse the multiaddr to extract the host
|
||||||
|
host := parseHostFromMultiaddr(peerAddr)
|
||||||
|
|
||||||
|
// Check if this is a local bootstrap (development)
|
||||||
|
if host == "127.0.0.1" || host == "localhost" {
|
||||||
|
return true // In development, assume we're running the bootstrap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a production bootstrap server
|
||||||
|
// You could add more sophisticated host matching here
|
||||||
|
if hostname != "" && strings.Contains(peerAddr, hostname) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default: if no specific match, run as regular node
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseHostFromMultiaddr extracts the host from a multiaddr
|
||||||
|
func parseHostFromMultiaddr(multiaddr string) string {
|
||||||
|
// Simple parsing for /ip4/host/tcp/port/p2p/peerid format
|
||||||
|
parts := strings.Split(multiaddr, "/")
|
||||||
|
|
||||||
|
// Look for ip4/ip6/dns host in the multiaddr
|
||||||
|
for i, part := range parts {
|
||||||
|
if (part == "ip4" || part == "ip6" || part == "dns" || part == "dns4" || part == "dns6") && i+1 < len(parts) {
|
||||||
|
return parts[i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func startNode(ctx context.Context, cfg *config.Config, port int, isBootstrap bool, logger *logging.StandardLogger) error {
|
||||||
|
// Create and start node using the unified node implementation
|
||||||
n, err := node.NewNode(cfg)
|
n, err := node.NewNode(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create node: %w", err)
|
return fmt.Errorf("failed to create node: %w", err)
|
||||||
@ -107,6 +195,22 @@ func startNode(ctx context.Context, cfg *config.Config) error {
|
|||||||
return fmt.Errorf("failed to start node: %w", err)
|
return fmt.Errorf("failed to start node: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the peer ID to a file for CLI access (especially useful for bootstrap)
|
||||||
|
if isBootstrap {
|
||||||
|
peerID := n.GetPeerID()
|
||||||
|
peerInfoFile := filepath.Join(cfg.Node.DataDir, "peer.info")
|
||||||
|
peerMultiaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/%s", port, peerID)
|
||||||
|
|
||||||
|
if err := os.WriteFile(peerInfoFile, []byte(peerMultiaddr), 0644); err != nil {
|
||||||
|
logger.Printf("Warning: Failed to save peer info: %v", err)
|
||||||
|
} else {
|
||||||
|
logger.Printf("Peer info saved to: %s", peerInfoFile)
|
||||||
|
logger.Printf("Bootstrap multiaddr: %s", peerMultiaddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Printf("Node started successfully")
|
||||||
|
|
||||||
// Wait for context cancellation
|
// Wait for context cancellation
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|
||||||
|
@ -3,11 +3,12 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.debros.io/DeBros/network/pkg/constants"
|
||||||
|
|
||||||
"git.debros.io/DeBros/network/pkg/storage"
|
"git.debros.io/DeBros/network/pkg/storage"
|
||||||
|
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
@ -196,29 +197,35 @@ func (d *DatabaseClientImpl) connectToAvailableNode() (*gorqlite.Connection, err
|
|||||||
return nil, fmt.Errorf("failed to connect to any RQLite instance. Last error: %w", lastErr)
|
return nil, fmt.Errorf("failed to connect to any RQLite instance. Last error: %w", lastErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRQLiteNodes returns a list of RQLite node URLs from environment or defaults
|
// getRQLiteNodes returns a list of RQLite node URLs using the peer IPs/hostnames from bootstrap.go, always on port 4001
|
||||||
func (d *DatabaseClientImpl) getRQLiteNodes() []string {
|
func (d *DatabaseClientImpl) getRQLiteNodes() []string {
|
||||||
// Try to get RQLite nodes from environment variable
|
// Use bootstrap peer addresses from constants
|
||||||
if envNodes := os.Getenv("RQLITE_NODES"); envNodes != "" {
|
// Import the constants package
|
||||||
return strings.Split(envNodes, ",")
|
// We'll extract the IP/host from the multiaddr and build the HTTP URL
|
||||||
|
var nodes []string
|
||||||
|
for _, addr := range constants.GetBootstrapPeers() {
|
||||||
|
// Example multiaddr: /ip4/57.129.81.31/tcp/4001/p2p/12D3KooWQRK2duw5B5LXi8gA7HBBFiCsLvwyph2ZU9VBmvbE1Nei
|
||||||
|
parts := strings.Split(addr, "/")
|
||||||
|
var host string
|
||||||
|
var port string = "4001" // always use 4001
|
||||||
|
for i := 0; i < len(parts); i++ {
|
||||||
|
if parts[i] == "ip4" || parts[i] == "ip6" {
|
||||||
|
host = parts[i+1]
|
||||||
}
|
}
|
||||||
|
if parts[i] == "dns" || parts[i] == "dns4" || parts[i] == "dns6" {
|
||||||
// Check if we're in production environment
|
host = parts[i+1]
|
||||||
if env := os.Getenv("ENVIRONMENT"); env == "production" {
|
}
|
||||||
// Use production servers with RQLite HTTP API ports (network port + 1000)
|
// ignore tcp port in multiaddr, always use 4001
|
||||||
return []string{
|
}
|
||||||
"http://57.129.81.31:5001", // production server 1
|
if host != "" {
|
||||||
"http://38.242.250.186:5001", // production server 2
|
nodes = append(nodes, "http://"+host+":"+port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If no peers found, fallback to localhost:4001
|
||||||
// Fallback to localhost for development
|
if len(nodes) == 0 {
|
||||||
return []string{
|
nodes = append(nodes, "http://localhost:4001")
|
||||||
"http://localhost:5001", // bootstrap
|
|
||||||
"http://localhost:5002", // node1
|
|
||||||
"http://localhost:5003", // node2
|
|
||||||
"http://localhost:5004", // node3 (if exists)
|
|
||||||
}
|
}
|
||||||
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// testConnection performs a health check on the RQLite connection
|
// testConnection performs a health check on the RQLite connection
|
||||||
|
@ -101,10 +101,10 @@ func setDefaultBootstrapConfig() {
|
|||||||
} else {
|
} else {
|
||||||
// Development: only use localhost bootstrap
|
// Development: only use localhost bootstrap
|
||||||
BootstrapPeerIDs = []string{
|
BootstrapPeerIDs = []string{
|
||||||
"12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j",
|
"12D3KooWBQAr9Lj9Z3918wBT523tJaRiPN6zRywAtttvPrwcZfJb",
|
||||||
}
|
}
|
||||||
BootstrapAddresses = []string{
|
BootstrapAddresses = []string{
|
||||||
"/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j",
|
"/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWBQAr9Lj9Z3918wBT523tJaRiPN6zRywAtttvPrwcZfJb",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BootstrapPort = 4001
|
BootstrapPort = 4001
|
||||||
|
@ -16,8 +16,8 @@ INSTALL_DIR="/opt/debros"
|
|||||||
REPO_URL="https://git.debros.io/DeBros/network.git"
|
REPO_URL="https://git.debros.io/DeBros/network.git"
|
||||||
MIN_GO_VERSION="1.19"
|
MIN_GO_VERSION="1.19"
|
||||||
NODE_PORT="4001"
|
NODE_PORT="4001"
|
||||||
RQLITE_NODE_PORT="5001"
|
RQLITE_PORT="4001" # All nodes use same RQLite port to join same cluster
|
||||||
RAFT_NODE_PORT="7001"
|
RAFT_PORT="4002" # All nodes use same Raft port
|
||||||
UPDATE_MODE=false
|
UPDATE_MODE=false
|
||||||
NON_INTERACTIVE=false
|
NON_INTERACTIVE=false
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ install_rqlite() {
|
|||||||
|
|
||||||
# Check port availability
|
# Check port availability
|
||||||
check_ports() {
|
check_ports() {
|
||||||
local ports=($NODE_PORT $RQLITE_NODE_PORT $RAFT_NODE_PORT)
|
local ports=($NODE_PORT $RQLITE_PORT $RAFT_PORT)
|
||||||
|
|
||||||
for port in "${ports[@]}"; do
|
for port in "${ports[@]}"; do
|
||||||
if sudo netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then
|
if sudo netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then
|
||||||
@ -622,8 +622,8 @@ node:
|
|||||||
solana_wallet: "$SOLANA_WALLET"
|
solana_wallet: "$SOLANA_WALLET"
|
||||||
|
|
||||||
database:
|
database:
|
||||||
rqlite_port: $RQLITE_NODE_PORT
|
rqlite_port: $RQLITE_PORT
|
||||||
rqlite_raft_port: $RAFT_NODE_PORT
|
rqlite_raft_port: $RAFT_PORT
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level: "info"
|
level: "info"
|
||||||
@ -647,7 +647,7 @@ configure_firewall() {
|
|||||||
log "Adding UFW rules for DeBros Network ports..."
|
log "Adding UFW rules for DeBros Network ports..."
|
||||||
|
|
||||||
# Add ports for node
|
# Add ports for node
|
||||||
for port in $NODE_PORT $RQLITE_NODE_PORT $RAFT_NODE_PORT; do
|
for port in $NODE_PORT $RQLITE_PORT $RAFT_PORT; do
|
||||||
if ! sudo ufw allow $port; then
|
if ! sudo ufw allow $port; then
|
||||||
error "Failed to allow port $port"
|
error "Failed to allow port $port"
|
||||||
exit 1
|
exit 1
|
||||||
@ -668,7 +668,7 @@ configure_firewall() {
|
|||||||
warning "UFW not found. Please configure firewall manually."
|
warning "UFW not found. Please configure firewall manually."
|
||||||
log "Required ports to allow:"
|
log "Required ports to allow:"
|
||||||
log " - Port $NODE_PORT (Node)"
|
log " - Port $NODE_PORT (Node)"
|
||||||
log " - Port $RQLITE_NODE_PORT (RQLite)"
|
log " - Port $RQLITE_PORT (RQLite)"
|
||||||
log " - Port $RAFT_NODE_PORT (Raft)"
|
log " - Port $RAFT_NODE_PORT (Raft)"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -827,7 +827,7 @@ main() {
|
|||||||
log "${GREEN}Logs:${NOCOLOR} ${CYAN}$INSTALL_DIR/logs/$NODE_TYPE.log${NOCOLOR}"
|
log "${GREEN}Logs:${NOCOLOR} ${CYAN}$INSTALL_DIR/logs/$NODE_TYPE.log${NOCOLOR}"
|
||||||
|
|
||||||
log "${GREEN}Node Port:${NOCOLOR} ${CYAN}$NODE_PORT${NOCOLOR}"
|
log "${GREEN}Node Port:${NOCOLOR} ${CYAN}$NODE_PORT${NOCOLOR}"
|
||||||
log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_NODE_PORT${NOCOLOR}"
|
log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_PORT${NOCOLOR}"
|
||||||
log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_NODE_PORT${NOCOLOR}"
|
log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_NODE_PORT${NOCOLOR}"
|
||||||
|
|
||||||
log "${BLUE}==================================================${NOCOLOR}"
|
log "${BLUE}==================================================${NOCOLOR}"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user