From d6d05e5399ea85c32a25f5b32438f83a4cfbcb16 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 04:07:45 +0000 Subject: [PATCH] refactor(blockchain): align service names with AX paths Co-Authored-By: Virgil --- cmd_explorer.go | 2 +- cmd_serve.go | 6 +++--- cmd_status.go | 8 +++---- cmd_sync.go | 4 ++-- cmd_wallet.go | 12 +++++------ commands.go | 8 +++---- service.go | 56 ++++++++++++++++++++++++++++++------------------- service_test.go | 26 ++++++++++++++++++----- 8 files changed, 76 insertions(+), 46 deletions(-) diff --git a/cmd_explorer.go b/cmd_explorer.go index f762d45..546f941 100644 --- a/cmd_explorer.go +++ b/cmd_explorer.go @@ -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() diff --git a/cmd_serve.go b/cmd_serve.go index d9f9d89..766c636 100644 --- a/cmd_serve.go +++ b/cmd_serve.go @@ -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") { diff --git a/cmd_status.go b/cmd_status.go index 7b45c96..033d53e 100644 --- a/cmd_status.go +++ b/cmd_status.go @@ -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() diff --git a/cmd_sync.go b/cmd_sync.go index 4a550be..c6204be 100644 --- a/cmd_sync.go +++ b/cmd_sync.go @@ -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() diff --git a/cmd_wallet.go b/cmd_wallet.go index 78eede5..580a8e9 100644 --- a/cmd_wallet.go +++ b/cmd_wallet.go @@ -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) diff --git a/commands.go b/commands.go index 97f30ef..1414a5b 100644 --- a/commands.go +++ b/commands.go @@ -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" diff --git a/service.go b/service.go index 81d224d..a3521c6 100644 --- a/service.go +++ b/service.go @@ -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} diff --git a/service_test.go b/service_test.go index 0c430f7..ac05405 100644 --- a/service_test.go +++ b/service_test.go @@ -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) }