mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 04:34:19 +01:00
wallet: bitcoind support with RPC polling (#254)
* support bitcoind connection * fix: wallet should be the varibale, not s.wallet * block cache: up to 2M blocks * WithBitcoind wait for sync * WithBitcoind rename * switch based on the ENV VARs * Add make targets
This commit is contained in:
2
server/.gitignore
vendored
2
server/.gitignore
vendored
@@ -25,4 +25,4 @@ go.work.sum
|
|||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
tmp/
|
data/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: build clean cov help intergrationtest lint run run-signet test vet proto proto-lint
|
.PHONY: build clean cov help intergrationtest lint run run-neutrino run-neutrino-signet test vet proto proto-lint
|
||||||
|
|
||||||
## build: build for all platforms
|
## build: build for all platforms
|
||||||
build:
|
build:
|
||||||
@@ -30,26 +30,43 @@ lint:
|
|||||||
@echo "Linting code..."
|
@echo "Linting code..."
|
||||||
@golangci-lint run --fix
|
@golangci-lint run --fix
|
||||||
|
|
||||||
## run: run in regtest mode
|
## run: run in regtest mode with bitcoind
|
||||||
run: clean
|
run: clean
|
||||||
@echo "Running arkd in dev mode..."
|
@echo "Running arkd with Bitcoin Core in regtest mode ..."
|
||||||
@export ARK_NEUTRINO_PEER=localhost:18444; \
|
@export ARK_ROUND_INTERVAL=10; \
|
||||||
export ARK_ROUND_INTERVAL=10; \
|
|
||||||
export ARK_LOG_LEVEL=5; \
|
export ARK_LOG_LEVEL=5; \
|
||||||
export ARK_NETWORK=regtest; \
|
export ARK_NETWORK=regtest; \
|
||||||
export ARK_PORT=7070; \
|
export ARK_PORT=7070; \
|
||||||
export ARK_NO_TLS=true; \
|
export ARK_NO_TLS=true; \
|
||||||
export ARK_NO_MACAROONS=true; \
|
export ARK_NO_MACAROONS=true; \
|
||||||
|
export ARK_MIN_RELAY_FEE=200; \
|
||||||
export ARK_TX_BUILDER_TYPE=covenantless; \
|
export ARK_TX_BUILDER_TYPE=covenantless; \
|
||||||
export ARK_ESPLORA_URL=http://localhost:3000; \
|
export ARK_ESPLORA_URL=http://localhost:3000; \
|
||||||
export ARK_MIN_RELAY_FEE=200; \
|
export ARK_BITCOIND_RPC_USER=admin1; \
|
||||||
|
export ARK_BITCOIND_RPC_PASS=123; \
|
||||||
|
export ARK_BITCOIND_RPC_HOST=localhost:18443; \
|
||||||
|
export ARK_DATADIR=./data/regtest; \
|
||||||
go run ./cmd/arkd
|
go run ./cmd/arkd
|
||||||
|
|
||||||
## export ARK_NEUTRINO_PEER=44.240.54.180:38333 ; \
|
## run-neutrino: run in regtest mode with neutrino
|
||||||
|
run-neutrino: clean
|
||||||
|
@echo "Running arkd with Neutrino in regtest mode ..."
|
||||||
|
@export ARK_ROUND_INTERVAL=10; \
|
||||||
|
export ARK_LOG_LEVEL=5; \
|
||||||
|
export ARK_NETWORK=regtest; \
|
||||||
|
export ARK_PORT=7070; \
|
||||||
|
export ARK_NO_TLS=true; \
|
||||||
|
export ARK_NO_MACAROONS=true; \
|
||||||
|
export ARK_MIN_RELAY_FEE=200; \
|
||||||
|
export ARK_TX_BUILDER_TYPE=covenantless; \
|
||||||
|
export ARK_ESPLORA_URL=http://localhost:3000; \
|
||||||
|
export ARK_NEUTRINO_PEER=localhost:18444; \
|
||||||
|
export ARK_DATADIR=./data/regtest; \
|
||||||
|
go run ./cmd/arkd
|
||||||
|
|
||||||
## run: run in signet mode
|
## run-neutrino-signet: run in signet mode
|
||||||
run-signet: clean
|
run-neutrino-signet: clean
|
||||||
@echo "Running arkd in signet mode..."
|
@echo "Running arkd with Neutrino in signet mode ..."
|
||||||
@export ARK_ROUND_INTERVAL=10; \
|
@export ARK_ROUND_INTERVAL=10; \
|
||||||
export ARK_LOG_LEVEL=5; \
|
export ARK_LOG_LEVEL=5; \
|
||||||
export ARK_NETWORK=signet; \
|
export ARK_NETWORK=signet; \
|
||||||
@@ -60,7 +77,7 @@ run-signet: clean
|
|||||||
export ARK_ESPLORA_URL=https://mutinynet.com/api; \
|
export ARK_ESPLORA_URL=https://mutinynet.com/api; \
|
||||||
export ARK_NEUTRINO_PEER=45.79.52.207:38333; \
|
export ARK_NEUTRINO_PEER=45.79.52.207:38333; \
|
||||||
export ARK_MIN_RELAY_FEE=200; \
|
export ARK_MIN_RELAY_FEE=200; \
|
||||||
export ARK_DATADIR=./tmp/signet/arkd-data; \
|
export ARK_DATADIR=./data/signet; \
|
||||||
go run ./cmd/arkd
|
go run ./cmd/arkd
|
||||||
|
|
||||||
## test: runs unit and component tests
|
## test: runs unit and component tests
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ func mainAction(_ *cli.Context) error {
|
|||||||
UnilateralExitDelay: cfg.UnilateralExitDelay,
|
UnilateralExitDelay: cfg.UnilateralExitDelay,
|
||||||
EsploraURL: cfg.EsploraURL,
|
EsploraURL: cfg.EsploraURL,
|
||||||
NeutrinoPeer: cfg.NeutrinoPeer,
|
NeutrinoPeer: cfg.NeutrinoPeer,
|
||||||
|
BitcoindRpcUser: cfg.BitcoindRpcUser,
|
||||||
|
BitcoindRpcPass: cfg.BitcoindRpcPass,
|
||||||
|
BitcoindRpcHost: cfg.BitcoindRpcHost,
|
||||||
}
|
}
|
||||||
svc, err := grpcservice.NewService(svcConfig, appConfig)
|
svc, err := grpcservice.NewService(svcConfig, appConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -64,8 +64,11 @@ type Config struct {
|
|||||||
RoundLifetime int64
|
RoundLifetime int64
|
||||||
UnilateralExitDelay int64
|
UnilateralExitDelay int64
|
||||||
|
|
||||||
EsploraURL string
|
EsploraURL string
|
||||||
NeutrinoPeer string
|
NeutrinoPeer string
|
||||||
|
BitcoindRpcUser string
|
||||||
|
BitcoindRpcPass string
|
||||||
|
BitcoindRpcHost string
|
||||||
|
|
||||||
repo ports.RepoManager
|
repo ports.RepoManager
|
||||||
svc application.Service
|
svc application.Service
|
||||||
@@ -230,13 +233,34 @@ func (c *Config) walletService() error {
|
|||||||
return fmt.Errorf("missing esplora url, covenant-less ark requires ARK_ESPLORA_URL to be set")
|
return fmt.Errorf("missing esplora url, covenant-less ark requires ARK_ESPLORA_URL to be set")
|
||||||
}
|
}
|
||||||
|
|
||||||
svc, err := btcwallet.NewService(btcwallet.WalletConfig{
|
// Check if both Neutrino peer and Bitcoind RPC credentials are provided
|
||||||
Datadir: c.DbDir,
|
if c.NeutrinoPeer != "" && (c.BitcoindRpcUser != "" || c.BitcoindRpcPass != "") {
|
||||||
Network: c.Network,
|
return fmt.Errorf("cannot use both Neutrino peer and Bitcoind RPC credentials")
|
||||||
EsploraURL: c.EsploraURL,
|
}
|
||||||
},
|
|
||||||
btcwallet.WithNeutrino(c.NeutrinoPeer),
|
var svc ports.WalletService
|
||||||
)
|
var err error
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case c.NeutrinoPeer != "":
|
||||||
|
svc, err = btcwallet.NewService(btcwallet.WalletConfig{
|
||||||
|
Datadir: c.DbDir,
|
||||||
|
Network: c.Network,
|
||||||
|
EsploraURL: c.EsploraURL,
|
||||||
|
}, btcwallet.WithNeutrino(c.NeutrinoPeer))
|
||||||
|
|
||||||
|
case c.BitcoindRpcUser != "" && c.BitcoindRpcPass != "":
|
||||||
|
svc, err = btcwallet.NewService(btcwallet.WalletConfig{
|
||||||
|
Datadir: c.DbDir,
|
||||||
|
Network: c.Network,
|
||||||
|
EsploraURL: c.EsploraURL,
|
||||||
|
}, btcwallet.WithPollingBitcoind(c.BitcoindRpcHost, c.BitcoindRpcUser, c.BitcoindRpcPass))
|
||||||
|
|
||||||
|
// Placeholder for future initializers like WithBitcoindZMQ
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("either Neutrino peer or Bitcoind RPC credentials must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ type Config struct {
|
|||||||
UnilateralExitDelay int64
|
UnilateralExitDelay int64
|
||||||
EsploraURL string
|
EsploraURL string
|
||||||
NeutrinoPeer string
|
NeutrinoPeer string
|
||||||
|
BitcoindRpcUser string
|
||||||
|
BitcoindRpcPass string
|
||||||
|
BitcoindRpcHost string
|
||||||
TLSExtraIPs []string
|
TLSExtraIPs []string
|
||||||
TLSExtraDomains []string
|
TLSExtraDomains []string
|
||||||
}
|
}
|
||||||
@@ -53,6 +56,9 @@ var (
|
|||||||
UnilateralExitDelay = "UNILATERAL_EXIT_DELAY"
|
UnilateralExitDelay = "UNILATERAL_EXIT_DELAY"
|
||||||
EsploraURL = "ESPLORA_URL"
|
EsploraURL = "ESPLORA_URL"
|
||||||
NeutrinoPeer = "NEUTRINO_PEER"
|
NeutrinoPeer = "NEUTRINO_PEER"
|
||||||
|
BitcoindRpcUser = "BITCOIND_RPC_USER"
|
||||||
|
BitcoindRpcPass = "BITCOIND_RPC_PASS"
|
||||||
|
BitcoindRpcHost = "BITCOIND_RPC_HOST"
|
||||||
NoMacaroons = "NO_MACAROONS"
|
NoMacaroons = "NO_MACAROONS"
|
||||||
NoTLS = "NO_TLS"
|
NoTLS = "NO_TLS"
|
||||||
TLSExtraIP = "TLS_EXTRA_IP"
|
TLSExtraIP = "TLS_EXTRA_IP"
|
||||||
@@ -128,6 +134,9 @@ func LoadConfig() (*Config, error) {
|
|||||||
UnilateralExitDelay: viper.GetInt64(UnilateralExitDelay),
|
UnilateralExitDelay: viper.GetInt64(UnilateralExitDelay),
|
||||||
EsploraURL: viper.GetString(EsploraURL),
|
EsploraURL: viper.GetString(EsploraURL),
|
||||||
NeutrinoPeer: viper.GetString(NeutrinoPeer),
|
NeutrinoPeer: viper.GetString(NeutrinoPeer),
|
||||||
|
BitcoindRpcUser: viper.GetString(BitcoindRpcUser),
|
||||||
|
BitcoindRpcPass: viper.GetString(BitcoindRpcPass),
|
||||||
|
BitcoindRpcHost: viper.GetString(BitcoindRpcHost),
|
||||||
NoMacaroons: viper.GetBool(NoMacaroons),
|
NoMacaroons: viper.GetBool(NoMacaroons),
|
||||||
TLSExtraIPs: viper.GetStringSlice(TLSExtraIP),
|
TLSExtraIPs: viper.GetStringSlice(TLSExtraIP),
|
||||||
TLSExtraDomains: viper.GetStringSlice(TLSExtraDomain),
|
TLSExtraDomains: viper.GetStringSlice(TLSExtraDomain),
|
||||||
|
|||||||
@@ -138,6 +138,68 @@ func WithNeutrino(initialPeer string) WalletOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithPollingBitcoind(host, user, pass string) WalletOption {
|
||||||
|
return func(s *service) error {
|
||||||
|
netParams := s.cfg.chainParams()
|
||||||
|
// Create a new bitcoind configuration
|
||||||
|
bitcoindConfig := &chain.BitcoindConfig{
|
||||||
|
ChainParams: netParams,
|
||||||
|
Host: host,
|
||||||
|
User: user,
|
||||||
|
Pass: pass,
|
||||||
|
PollingConfig: &chain.PollingConfig{
|
||||||
|
BlockPollingInterval: 10 * time.Second,
|
||||||
|
TxPollingInterval: 5 * time.Second,
|
||||||
|
TxPollingIntervalJitter: 0.1,
|
||||||
|
RPCBatchSize: 20,
|
||||||
|
RPCBatchInterval: 1 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.UseLogger(logger("chain"))
|
||||||
|
|
||||||
|
// Create the BitcoindConn first
|
||||||
|
bitcoindConn, err := chain.NewBitcoindConn(bitcoindConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create bitcoind connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the bitcoind connection
|
||||||
|
if err := bitcoindConn.Start(); err != nil {
|
||||||
|
return fmt.Errorf("failed to start bitcoind connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now create the BitcoindClient using the connection
|
||||||
|
chainClient := bitcoindConn.NewBitcoindClient()
|
||||||
|
|
||||||
|
// Start the chain client
|
||||||
|
if err := chainClient.Start(); err != nil {
|
||||||
|
bitcoindConn.Stop()
|
||||||
|
return fmt.Errorf("failed to start bitcoind client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for bitcoind to sync
|
||||||
|
for !chainClient.IsCurrent() {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the wallet as chain source and scanner
|
||||||
|
if err := withChainSource(chainClient)(s); err != nil {
|
||||||
|
chainClient.Stop()
|
||||||
|
bitcoindConn.Stop()
|
||||||
|
return fmt.Errorf("failed to set chain source: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := withScanner(chainClient)(s); err != nil {
|
||||||
|
chainClient.Stop()
|
||||||
|
bitcoindConn.Stop()
|
||||||
|
return fmt.Errorf("failed to set scanner: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewService creates the wallet service, an option must be set to configure the chain source.
|
// NewService creates the wallet service, an option must be set to configure the chain source.
|
||||||
func NewService(cfg WalletConfig, options ...WalletOption) (ports.WalletService, error) {
|
func NewService(cfg WalletConfig, options ...WalletOption) (ports.WalletService, error) {
|
||||||
wallet.UseLogger(logger("wallet"))
|
wallet.UseLogger(logger("wallet"))
|
||||||
|
|||||||
Reference in New Issue
Block a user