mirror of
https://github.com/aljazceru/ark.git
synced 2026-02-16 08:34:19 +01:00
committed by
GitHub
parent
d37af7daf5
commit
1d40892196
@@ -79,19 +79,21 @@ func mainAction(_ *cli.Context) error {
|
||||
BitcoindRpcPass: cfg.BitcoindRpcPass,
|
||||
BitcoindRpcHost: cfg.BitcoindRpcHost,
|
||||
BoardingExitDelay: cfg.BoardingExitDelay,
|
||||
UnlockerType: cfg.UnlockerType,
|
||||
UnlockerFilePath: cfg.UnlockerFilePath,
|
||||
}
|
||||
svc, err := grpcservice.NewService(svcConfig, appConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.RegisterExitHandler(svc.Stop)
|
||||
|
||||
log.Info("starting service...")
|
||||
if err := svc.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.RegisterExitHandler(svc.Stop)
|
||||
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, os.Interrupt)
|
||||
<-sigChan
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
scheduler "github.com/ark-network/ark/server/internal/infrastructure/scheduler/gocron"
|
||||
txbuilder "github.com/ark-network/ark/server/internal/infrastructure/tx-builder/covenant"
|
||||
cltxbuilder "github.com/ark-network/ark/server/internal/infrastructure/tx-builder/covenantless"
|
||||
fileunlocker "github.com/ark-network/ark/server/internal/infrastructure/unlocker/file"
|
||||
btcwallet "github.com/ark-network/ark/server/internal/infrastructure/wallet/btc-embedded"
|
||||
liquidwallet "github.com/ark-network/ark/server/internal/infrastructure/wallet/liquid-standalone"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -37,6 +38,9 @@ var (
|
||||
"ocean": {},
|
||||
"btcwallet": {},
|
||||
}
|
||||
supportedUnlockers = supportedType{
|
||||
"file": {},
|
||||
}
|
||||
supportedNetworks = supportedType{
|
||||
common.Bitcoin.Name: {},
|
||||
common.BitcoinTestNet.Name: {},
|
||||
@@ -70,6 +74,9 @@ type Config struct {
|
||||
BitcoindRpcPass string
|
||||
BitcoindRpcHost string
|
||||
|
||||
UnlockerType string
|
||||
UnlockerFilePath string
|
||||
|
||||
repo ports.RepoManager
|
||||
svc application.Service
|
||||
adminSvc application.AdminService
|
||||
@@ -77,6 +84,7 @@ type Config struct {
|
||||
txBuilder ports.TxBuilder
|
||||
scanner ports.BlockchainScanner
|
||||
scheduler ports.SchedulerService
|
||||
unlocker ports.Unlocker
|
||||
}
|
||||
|
||||
func (c *Config) Validate() error {
|
||||
@@ -95,6 +103,9 @@ func (c *Config) Validate() error {
|
||||
if !supportedScanners.supports(c.BlockchainScannerType) {
|
||||
return fmt.Errorf("blockchain scanner type not supported, please select one of: %s", supportedScanners)
|
||||
}
|
||||
if len(c.UnlockerType) > 0 && !supportedUnlockers.supports(c.UnlockerType) {
|
||||
return fmt.Errorf("unlocker type not supported, please select one of: %s", supportedUnlockers)
|
||||
}
|
||||
if c.RoundInterval < 2 {
|
||||
return fmt.Errorf("invalid round interval, must be at least 2 seconds")
|
||||
}
|
||||
@@ -151,7 +162,7 @@ func (c *Config) Validate() error {
|
||||
return err
|
||||
}
|
||||
if err := c.walletService(); err != nil {
|
||||
return fmt.Errorf("failed to connect to wallet: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := c.txBuilderService(); err != nil {
|
||||
return err
|
||||
@@ -165,6 +176,9 @@ func (c *Config) Validate() error {
|
||||
if err := c.adminService(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.unlockerService(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -185,6 +199,10 @@ func (c *Config) WalletService() ports.WalletService {
|
||||
return c.wallet
|
||||
}
|
||||
|
||||
func (c *Config) UnlockerService() ports.Unlocker {
|
||||
return c.unlocker
|
||||
}
|
||||
|
||||
func (c *Config) repoManager() error {
|
||||
var svc ports.RepoManager
|
||||
var err error
|
||||
@@ -227,7 +245,7 @@ func (c *Config) walletService() error {
|
||||
if common.IsLiquid(c.Network) {
|
||||
svc, err := liquidwallet.NewService(c.WalletAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to connect to wallet: %s", err)
|
||||
}
|
||||
|
||||
c.wallet = svc
|
||||
@@ -353,6 +371,26 @@ func (c *Config) adminService() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) unlockerService() error {
|
||||
if len(c.UnlockerType) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var svc ports.Unlocker
|
||||
var err error
|
||||
switch c.UnlockerType {
|
||||
case "file":
|
||||
svc, err = fileunlocker.NewService(c.UnlockerFilePath)
|
||||
default:
|
||||
err = fmt.Errorf("unknown unlocker type")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.unlocker = svc
|
||||
return nil
|
||||
}
|
||||
|
||||
type supportedType map[string]struct{}
|
||||
|
||||
func (t supportedType) String() string {
|
||||
|
||||
@@ -36,6 +36,8 @@ type Config struct {
|
||||
BitcoindRpcHost string
|
||||
TLSExtraIPs []string
|
||||
TLSExtraDomains []string
|
||||
UnlockerType string
|
||||
UnlockerFilePath string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -59,12 +61,14 @@ var (
|
||||
// #nosec G101
|
||||
BitcoindRpcUser = "BITCOIND_RPC_USER"
|
||||
// #nosec G101
|
||||
BitcoindRpcPass = "BITCOIND_RPC_PASS"
|
||||
BitcoindRpcHost = "BITCOIND_RPC_HOST"
|
||||
NoMacaroons = "NO_MACAROONS"
|
||||
NoTLS = "NO_TLS"
|
||||
TLSExtraIP = "TLS_EXTRA_IP"
|
||||
TLSExtraDomain = "TLS_EXTRA_DOMAIN"
|
||||
BitcoindRpcPass = "BITCOIND_RPC_PASS"
|
||||
BitcoindRpcHost = "BITCOIND_RPC_HOST"
|
||||
NoMacaroons = "NO_MACAROONS"
|
||||
NoTLS = "NO_TLS"
|
||||
TLSExtraIP = "TLS_EXTRA_IP"
|
||||
TLSExtraDomain = "TLS_EXTRA_DOMAIN"
|
||||
UnlockerType = "UNLOCKER_TYPE"
|
||||
UnlockerFilePath = "UNLOCKER_FILE_PATH"
|
||||
|
||||
defaultDatadir = common.AppDataDir("arkd", false)
|
||||
defaultRoundInterval = 5
|
||||
@@ -142,6 +146,8 @@ func LoadConfig() (*Config, error) {
|
||||
NoMacaroons: viper.GetBool(NoMacaroons),
|
||||
TLSExtraIPs: viper.GetStringSlice(TLSExtraIP),
|
||||
TLSExtraDomains: viper.GetStringSlice(TLSExtraDomain),
|
||||
UnlockerType: viper.GetString(UnlockerType),
|
||||
UnlockerFilePath: viper.GetString(UnlockerFilePath),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
7
server/internal/core/ports/unlocker.go
Normal file
7
server/internal/core/ports/unlocker.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package ports
|
||||
|
||||
import "context"
|
||||
|
||||
type Unlocker interface {
|
||||
GetPassword(ctx context.Context) (string, error)
|
||||
}
|
||||
37
server/internal/infrastructure/unlocker/file/service.go
Normal file
37
server/internal/infrastructure/unlocker/file/service.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package fileunlocker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ark-network/ark/server/internal/core/ports"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
filePath string
|
||||
}
|
||||
|
||||
func NewService(filePath string) (ports.Unlocker, error) {
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("password file not found at path %s", filePath)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &service{filePath: filePath}, nil
|
||||
}
|
||||
|
||||
func (s *service) GetPassword(_ context.Context) (string, error) {
|
||||
buf, err := os.ReadFile(s.filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
password := bytes.TrimFunc(buf, func(r rune) bool {
|
||||
return r == 10 || r == 13 || r == 32
|
||||
})
|
||||
|
||||
return string(password), nil
|
||||
}
|
||||
@@ -304,6 +304,10 @@ func (s *service) Restore(_ context.Context, seed, password string) error {
|
||||
}
|
||||
|
||||
func (s *service) Unlock(_ context.Context, password string) error {
|
||||
if !s.walletInitialized() {
|
||||
return fmt.Errorf("wallet not initialized")
|
||||
}
|
||||
|
||||
if !s.walletLoaded() {
|
||||
pwd := []byte(password)
|
||||
opt := btcwallet.LoaderWithLocalWalletDB(s.cfg.Datadir, false, time.Minute)
|
||||
|
||||
@@ -94,7 +94,13 @@ func NewService(
|
||||
|
||||
func (s *service) Start() error {
|
||||
withoutAppSvc := false
|
||||
return s.start(withoutAppSvc)
|
||||
if err := s.start(withoutAppSvc); err != nil {
|
||||
return err
|
||||
}
|
||||
if s.appConfig.UnlockerService() != nil {
|
||||
return s.autoUnlock()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) Stop() {
|
||||
@@ -314,6 +320,33 @@ func (s *service) onInit(password string) {
|
||||
log.Debugf("generated macaroons at path %s", datadir)
|
||||
}
|
||||
|
||||
func (s *service) autoUnlock() error {
|
||||
ctx := context.Background()
|
||||
wallet := s.appConfig.WalletService()
|
||||
|
||||
status, err := wallet.Status(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get wallet status: %s", err)
|
||||
}
|
||||
if !status.IsInitialized() {
|
||||
log.Debug("wallet not initiialized, skipping auto unlock")
|
||||
return nil
|
||||
}
|
||||
|
||||
password, err := s.appConfig.UnlockerService().GetPassword(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get password: %s", err)
|
||||
}
|
||||
if err := wallet.Unlock(ctx, password); err != nil {
|
||||
return fmt.Errorf("failed to auto unlock: %s", err)
|
||||
}
|
||||
|
||||
go s.onUnlock(password)
|
||||
|
||||
log.Debug("service auto unlocked")
|
||||
return nil
|
||||
}
|
||||
|
||||
func router(
|
||||
grpcServer *grpc.Server, grpcGateway http.Handler,
|
||||
) http.Handler {
|
||||
|
||||
Reference in New Issue
Block a user