mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
Deletes pkg/cpp/ (11 tracked files: consensus.cpp, mlx_consensus.cpp, chain.cpp, network.cpp, vote_processor.cpp + 2 headers + 2 tests + 2 examples + CMakeLists.txt). The sources are now committed in ~/work/luxcpp/consensus/ (commit 6b43843). cpp_node.go's hardcoded "pkg/cpp/build" path updated to point at $HOME/work/luxcpp/consensus/build so the e2e harness still finds the built artifact in its new home. Rule: Go repos hold only Go + CGO bindings. Heavy C++/Metal/CUDA lives in ~/work/luxcpp/<package>/. No mixed-language source trees in the Go monorepo.
114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/luxfi/consensus/utils/ids"
|
|
)
|
|
|
|
// CppNode implements NodeRunner for C++ implementation
|
|
type CppNode struct {
|
|
t *testing.T
|
|
cmd *exec.Cmd
|
|
decisions map[ids.ID]bool
|
|
mu sync.RWMutex
|
|
healthy bool
|
|
}
|
|
|
|
// NewCppNode creates a new C++ consensus node
|
|
func NewCppNode(t *testing.T) *CppNode {
|
|
return &CppNode{
|
|
t: t,
|
|
decisions: make(map[ids.ID]bool),
|
|
}
|
|
}
|
|
|
|
// Start initializes and starts the C++ consensus engine
|
|
func (n *CppNode) Start(ctx context.Context, port int) error {
|
|
n.t.Logf("Starting C++ node on port %d", port)
|
|
|
|
// C++ side lives in ~/work/luxcpp/consensus/. The Go repo holds only
|
|
// CGO bindings; the build is driven from luxcpp.
|
|
if !checkBuild(n.t, "C++", []string{"cmake", "--build", os.ExpandEnv("$HOME/work/luxcpp/consensus/build")}) {
|
|
n.t.Log("⚠️ C++ binary not built (luxcpp/consensus), skipping C++ node")
|
|
n.healthy = false
|
|
return fmt.Errorf("c++ binary not available")
|
|
}
|
|
|
|
n.healthy = true
|
|
n.t.Log("C++ node started (simulated)")
|
|
return nil
|
|
}
|
|
|
|
// Stop shuts down the C++ consensus engine
|
|
func (n *CppNode) Stop() error {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
|
|
n.t.Log("Stopping C++ node")
|
|
|
|
if n.cmd != nil && n.cmd.Process != nil {
|
|
if err := n.cmd.Process.Kill(); err != nil {
|
|
n.t.Logf("Error killing C++ process: %v", err)
|
|
}
|
|
}
|
|
|
|
n.healthy = false
|
|
return nil
|
|
}
|
|
|
|
// ProposeBlock submits a block to the C++ consensus engine
|
|
func (n *CppNode) ProposeBlock(testBlock *Block) error {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
|
|
if !n.healthy {
|
|
return fmt.Errorf("c++ node not healthy")
|
|
}
|
|
|
|
n.t.Logf("C++ node: proposing block %s (height %d)", testBlock.ID, testBlock.Height)
|
|
|
|
// Simulated consensus for E2E cross-language test.
|
|
blockData := map[string]interface{}{
|
|
"id": testBlock.ID.String(),
|
|
"parent_id": testBlock.ParentID.String(),
|
|
"height": testBlock.Height,
|
|
"data": string(testBlock.Data),
|
|
}
|
|
|
|
if data, err := json.Marshal(blockData); err == nil {
|
|
n.t.Logf("C++ block data: %s", string(data))
|
|
}
|
|
|
|
// Simulate acceptance
|
|
n.decisions[testBlock.ID] = true
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetDecision returns whether a block was accepted
|
|
func (n *CppNode) GetDecision(blockID ids.ID) (bool, error) {
|
|
n.mu.RLock()
|
|
defer n.mu.RUnlock()
|
|
|
|
decision, exists := n.decisions[blockID]
|
|
if !exists {
|
|
return false, fmt.Errorf("no decision for block %s", blockID)
|
|
}
|
|
|
|
return decision, nil
|
|
}
|
|
|
|
// IsHealthy returns whether the C++ node is healthy
|
|
func (n *CppNode) IsHealthy() bool {
|
|
n.mu.RLock()
|
|
defer n.mu.RUnlock()
|
|
return n.healthy
|
|
}
|