refactor(blockchain): align service names with AX paths
Some checks are pending
Security Scan / security (push) Waiting to run
Test / Test (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-04 04:07:45 +00:00
parent 2818f1fed9
commit d6d05e5399
8 changed files with 76 additions and 46 deletions

View file

@ -46,7 +46,7 @@ func runExplorer(dataDir, seed string, testnet bool) error {
defer s.Close()
c := chain.New(s)
cfg, forks := resolveConfig(testnet, &seed)
cfg, forks := resolveChainConfig(testnet, &seed)
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT)
defer cancel()

View file

@ -59,7 +59,7 @@ func runServe(dataDir, seed string, testnet bool, rpcBind, rpcPort, walletRPC st
defer s.Close()
c := chain.New(s)
cfg, forks := resolveConfig(testnet, &seed)
cfg, forks := resolveChainConfig(testnet, &seed)
// Set genesis hash for testnet.
if testnet {
@ -124,9 +124,9 @@ func rpcSyncLoop(ctx context.Context, c *chain.Chain, cfg *config.ChainConfig, f
Forks: forks,
}
// Derive RPC URL from seed address (replace P2P port with RPC port).
// Derive the RPC URL from the seed address.
rpcURL := core.Sprintf("http://%s", seed)
// If seed has P2P port, swap to RPC.
// Swap the peer port for the RPC port when the seed uses a default network address.
if core.Contains(seed, ":46942") {
rpcURL = "http://127.0.0.1:46941"
} else if core.Contains(seed, ":36942") {

View file

@ -12,18 +12,18 @@ import (
"github.com/spf13/cobra"
)
func newStatusCmd(dataDir, seed *string, testnet *bool) *cobra.Command {
func newStatusCmd(seed *string) *cobra.Command {
return &cobra.Command{
Use: "status",
Short: "Show chain and network status",
RunE: func(cmd *cobra.Command, args []string) error {
return runStatus(*seed, *testnet)
return runStatus(*seed)
},
}
}
func runStatus(seed string, testnet bool) error {
rpcURL := seedToRPC(seed, testnet)
func runStatus(seed string) error {
rpcURL := seedToRPC(seed)
client := rpc.NewClient(rpcURL)
info, err := client.GetInfo()

View file

@ -60,7 +60,7 @@ func runSyncForeground(dataDir, seed string, testnet bool) error {
defer s.Close()
c := chain.New(s)
cfg, forks := resolveConfig(testnet, &seed)
cfg, forks := resolveChainConfig(testnet, &seed)
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
@ -100,7 +100,7 @@ func runSyncDaemon(dataDir, seed string, testnet bool) error {
defer s.Close()
c := chain.New(s)
cfg, forks := resolveConfig(testnet, &seed)
cfg, forks := resolveChainConfig(testnet, &seed)
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

View file

@ -78,7 +78,7 @@ func newWalletSeedCmd(walletFile *string) *cobra.Command {
func runWalletCreate(walletFile string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet.db")
}
if err := ensureDataDir(core.PathBase(walletFile)); err != nil {
@ -114,7 +114,7 @@ func runWalletCreate(walletFile string) error {
func runWalletAddress(walletFile string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet.db")
}
s, err := store.New(walletFile)
@ -135,7 +135,7 @@ func runWalletAddress(walletFile string) error {
func runWalletSeed(walletFile string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet.db")
}
s, err := store.New(walletFile)
@ -175,7 +175,7 @@ func newWalletScanCmd(walletFile *string) *cobra.Command {
func runWalletScan(walletFile, daemonURL string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet.db")
}
s, err := store.New(walletFile)
@ -312,7 +312,7 @@ func newWalletRestoreCmd(walletFile *string) *cobra.Command {
func runWalletRestore(walletFile, seed string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet-restored.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet-restored.db")
}
account, err := wallet.RestoreFromSeed(seed)
@ -405,7 +405,7 @@ func newWalletInfoCmd(walletFile *string) *cobra.Command {
func runWalletInfo(walletFile string) error {
if walletFile == "" {
walletFile = core.JoinPath(defaultDataDir(), "wallet.db")
walletFile = core.JoinPath(defaultChainDataDir(), "wallet.db")
}
s, err := store.New(walletFile)

View file

@ -30,7 +30,7 @@ func AddChainCommands(root *cobra.Command) {
Long: "Manage the Lethean blockchain — sync, explore, and mine.",
}
chainCmd.PersistentFlags().StringVar(&dataDir, "data-dir", defaultDataDir(), "blockchain data directory")
chainCmd.PersistentFlags().StringVar(&dataDir, "data-dir", defaultChainDataDir(), "blockchain data directory")
chainCmd.PersistentFlags().StringVar(&seed, "seed", "seeds.lthn.io:36942", "seed peer address (host:port)")
chainCmd.PersistentFlags().BoolVar(&testnet, "testnet", false, "use testnet")
@ -38,13 +38,13 @@ func AddChainCommands(root *cobra.Command) {
newExplorerCmd(&dataDir, &seed, &testnet),
newSyncCmd(&dataDir, &seed, &testnet),
newServeCmd(&dataDir, &seed, &testnet),
newStatusCmd(&dataDir, &seed, &testnet),
newStatusCmd(&seed),
)
root.AddCommand(chainCmd)
}
func resolveConfig(testnet bool, seed *string) (config.ChainConfig, []config.HardFork) {
func resolveChainConfig(testnet bool, seed *string) (config.ChainConfig, []config.HardFork) {
if testnet {
if *seed == "seeds.lthn.io:36942" {
*seed = "localhost:46942"
@ -54,7 +54,7 @@ func resolveConfig(testnet bool, seed *string) (config.ChainConfig, []config.Har
return config.Mainnet, config.MainnetForks
}
func defaultDataDir() string {
func defaultChainDataDir() string {
home := core.Env("DIR_HOME")
if home == "" {
return ".lethean"

View file

@ -6,8 +6,8 @@ package blockchain
import (
"context"
"time"
"net/http"
"time"
"dappco.re/go/core"
@ -18,18 +18,29 @@ import (
)
// BlockchainOptions configures the blockchain service.
//
// Usage: opts := blockchain.BlockchainOptions{DataDir: "/var/lib/core", Testnet: true}
type BlockchainOptions struct {
// DataDir is the persistent chain data directory.
// Usage: opts := blockchain.BlockchainOptions{DataDir: "/var/lib/core"}
DataDir string
Seed string
// Seed is the bootstrap peer address used for RPC sync.
// Usage: opts := blockchain.BlockchainOptions{Seed: "127.0.0.1:46942"}
Seed string
// Testnet switches the service onto the testnet genesis and forks.
// Usage: opts := blockchain.BlockchainOptions{Testnet: true}
Testnet bool
// RPCPort is the JSON-RPC port exposed by the embedded daemon.
// Usage: opts := blockchain.BlockchainOptions{RPCPort: "47941"}
RPCPort string
// RPCBind is the bind address for the embedded daemon.
// Usage: opts := blockchain.BlockchainOptions{RPCBind: "127.0.0.1"}
RPCBind string
}
// BlockchainService is a Core-managed blockchain node.
//
// svc := blockchain.NewBlockchainService(c, opts)
// c.RegisterService("blockchain", svc)
// Usage: svc := blockchain.NewBlockchainService(c, opts)
type BlockchainService struct {
core *core.Core
opts BlockchainOptions
@ -43,7 +54,7 @@ type BlockchainService struct {
// NewBlockchainService creates and registers the blockchain as a Core service.
//
// svc := blockchain.NewBlockchainService(c, opts)
// Usage: svc := blockchain.NewBlockchainService(c, opts)
func NewBlockchainService(c *core.Core, opts BlockchainOptions) *BlockchainService {
svc := &BlockchainService{core: c, opts: opts}
@ -56,11 +67,11 @@ func NewBlockchainService(c *core.Core, opts BlockchainOptions) *BlockchainServi
})
// Register blockchain actions.
c.Action("blockchain.height", svc.actionHeight)
c.Action("blockchain.info", svc.actionInfo)
c.Action("blockchain.block", svc.actionBlock)
c.Action("blockchain.aliases", svc.actionAliases)
c.Action("blockchain.alias", svc.actionAlias)
c.Action("blockchain.chain.height", svc.actionChainHeight)
c.Action("blockchain.chain.info", svc.actionChainInfo)
c.Action("blockchain.chain.block", svc.actionChainBlock)
c.Action("blockchain.alias.list", svc.actionAliasList)
c.Action("blockchain.alias.get", svc.actionAliasGet)
c.Action("blockchain.wallet.create", svc.actionWalletCreate)
return svc
@ -94,20 +105,20 @@ func (s *BlockchainService) start() core.Result {
// Wire sync progress events
s.chain.SetSyncCallback(func(localHeight, remoteHeight uint64, blocksPerSecond float64) {
s.events.Emit(Event{Type: EventSyncProgress, Height: localHeight, Data: map[string]interface{}{
"local_height": localHeight,
"remote_height": remoteHeight,
"blocks_per_sec": blocksPerSecond,
"local_height": localHeight,
"remote_height": remoteHeight,
"blocks_per_sec": blocksPerSecond,
}})
})
cfg, forks := resolveConfig(s.opts.Testnet, &s.opts.Seed)
cfg, forks := resolveChainConfig(s.opts.Testnet, &s.opts.Seed)
// Start background sync.
ctx, cancel := context.WithCancel(context.Background())
s.cancel = cancel
go func() {
client := rpc.NewClient(seedToRPC(s.opts.Seed, s.opts.Testnet))
client := rpc.NewClient(seedToRPC(s.opts.Seed))
opts := chain.SyncOptions{Forks: forks}
for {
select {
@ -154,12 +165,12 @@ func (s *BlockchainService) stop() core.Result {
// --- Actions ---
func (s *BlockchainService) actionHeight(ctx context.Context, opts core.Options) core.Result {
func (s *BlockchainService) actionChainHeight(ctx context.Context, opts core.Options) core.Result {
h, _ := s.chain.Height()
return core.Result{Value: h, OK: true}
}
func (s *BlockchainService) actionInfo(ctx context.Context, opts core.Options) core.Result {
func (s *BlockchainService) actionChainInfo(ctx context.Context, opts core.Options) core.Result {
h, _ := s.chain.Height()
_, meta, _ := s.chain.TopBlock()
aliases := s.chain.GetAllAliases()
@ -171,7 +182,7 @@ func (s *BlockchainService) actionInfo(ctx context.Context, opts core.Options) c
}, OK: true}
}
func (s *BlockchainService) actionBlock(ctx context.Context, opts core.Options) core.Result {
func (s *BlockchainService) actionChainBlock(ctx context.Context, opts core.Options) core.Result {
height := uint64(opts.Int("height"))
blk, meta, err := s.chain.GetBlockByHeight(height)
if err != nil {
@ -184,11 +195,11 @@ func (s *BlockchainService) actionBlock(ctx context.Context, opts core.Options)
}, OK: true}
}
func (s *BlockchainService) actionAliases(ctx context.Context, opts core.Options) core.Result {
func (s *BlockchainService) actionAliasList(ctx context.Context, opts core.Options) core.Result {
return core.Result{Value: s.chain.GetAllAliases(), OK: true}
}
func (s *BlockchainService) actionAlias(ctx context.Context, opts core.Options) core.Result {
func (s *BlockchainService) actionAliasGet(ctx context.Context, opts core.Options) core.Result {
name := opts.String("name")
alias, err := s.chain.GetAlias(name)
if err != nil {
@ -204,7 +215,8 @@ func (s *BlockchainService) actionWalletCreate(ctx context.Context, opts core.Op
// --- Helpers ---
func seedToRPC(seed string, testnet bool) string {
// Usage: url := seedToRPC("127.0.0.1:46942")
func seedToRPC(seed string) string {
if core.Contains(seed, ":46942") {
return "http://127.0.0.1:46941"
}
@ -215,6 +227,8 @@ func seedToRPC(seed string, testnet bool) string {
}
// SyncStatus returns the current sync state.
//
// Usage: status := svc.SyncStatus()
func (s *BlockchainService) SyncStatus() map[string]interface{} {
if s.chain == nil {
return map[string]interface{}{"synced": false, "height": 0}

View file

@ -22,16 +22,32 @@ func TestBlockchainService_New_Good(t *testing.T) {
if svc.opts.Testnet != true {
t.Error("expected testnet")
}
expectedActions := []string{
"blockchain.chain.height",
"blockchain.chain.info",
"blockchain.chain.block",
"blockchain.alias.list",
"blockchain.alias.get",
"blockchain.wallet.create",
}
for _, name := range expectedActions {
if !c.Action(name).Exists() {
t.Fatalf("expected action %s to be registered", name)
}
}
}
func TestBlockchainService_SeedToRPC_Good(t *testing.T) {
tests := []struct{ seed string; testnet bool; want string }{
{"127.0.0.1:46942", true, "http://127.0.0.1:46941"},
{"127.0.0.1:36942", false, "http://127.0.0.1:36941"},
{"10.0.0.1:9999", false, "http://10.0.0.1:9999"},
tests := []struct {
seed string
want string
}{
{"127.0.0.1:46942", "http://127.0.0.1:46941"},
{"127.0.0.1:36942", "http://127.0.0.1:36941"},
{"10.0.0.1:9999", "http://10.0.0.1:9999"},
}
for _, tt := range tests {
got := seedToRPC(tt.seed, tt.testnet)
got := seedToRPC(tt.seed)
if got != tt.want {
t.Errorf("seedToRPC(%s): got %s, want %s", tt.seed, got, tt.want)
}