diff --git a/README.md b/README.md index d2f369e..92d81b1 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ There are four vigilante programs: ## Requirements -- Go 1.23 +- [Go 1.23](https://go.dev/dl/go1.23.0.src.tar.gz) +- [Bitcoind](https://bitcoincore.org/bin) - Package [libzmq](https://github.com/zeromq/libzmq) -- [btcd](https://github.com/btcsuite/btcd/tree/master?tab=readme-ov-file#installation) binaries (only for testing) ## Building @@ -66,100 +66,69 @@ This will be later used to retrieve the certificate required for RPC connections mkdir $TESTNET_PATH/bitcoin ``` -For a Docker deployment, we want the vigilante to be able to communicate with -the Babylon and Bitcoin instances running on the local network. -We can accomplish that through the `host.docker.internal` DNS name, -which the Docker network translates to the Docker machine. -To enable Bitcoin RPC requests, we need to add the `host.docker.internal` -DNS host to the `rpc.cert` file that was created by the previous command. -To do that we use the btcd `gencerts` utility, +```bash +# Download Bitcoin Core binary +wget https://bitcoincore.org/bin/bitcoin-core-27.0/bitcoin-27.0-x86_64-linux-gnu.tar.gz # or choose a version depending on your os -```shell -gencerts -d $TESTNET_PATH/bitcoin/ -H host.docker.internal -``` - -#### Running a Bitcoin simnet with an arbitrary mining address +# Extract the downloaded archive +tar -xvf bitcoin-27.0-x86_64-linux-gnu.tar.gz -Launch a simnet Bitcoin node -which listens for RPC connections at port `18556` and -stores the RPC certificate under the `$TESTNET_PATH/bitcoin` directory. -The mining address is arbitrary. - -```shell -btcd --simnet --rpclisten 127.0.0.1:18556 --rpcuser rpcuser --rpcpass rpcpass \ - --rpccert $TESTNET_PATH/bitcoin/rpc.cert --rpckey $TESTNET_PATH/bitcoin/rpc.key \ - --miningaddr SQqHYFTSPh8WAyJvzbAC8hoLbF12UVsE5s +# Provide execution permissions to binaries +chmod +x bitcoin-27.0/bin/bitcoind +chmod +x bitcoin-27.0/bin/bitcoin-cli ``` -#### Running a Bitcoin simnet with a wallet +#### Running a Bitcoin regtest with a wallet -Launch a simnet Bitcoin node -which listens for RPC connections at port `18556` and -stores the RPC certificate under the `$TESTNET_PATH/bitcoin` directory. +Launch a regtest Bitcoind node which listens for RPC connections at port `18443`. ```shell -btcd --simnet --rpclisten 127.0.0.1:18556 --rpcuser rpcuser --rpcpass rpcpass \ - --rpccert $TESTNET_PATH/bitcoin/rpc.cert --rpckey $TESTNET_PATH/bitcoin/rpc.key +bitcoind -regtest \ + -txindex \ + -rpcuser= \ + -rpcpassword= \ + -rpcbind=0.0.0.0:18443 \ + -zmqpubsequence=tcp://0.0.0.0:28333 \ + -datadir=/data/.bitcoin \ + ``` Leave this process running. -Then, create a simnet Bitcoin wallet. +Then, create a regtest Bitcoin wallet. If you want to use the default vigilante file, then give the password `walletpass`. Otherwise, make sure to edit the `vigilante.yaml` to reflect the correct password. ```shell -btcwallet --simnet -u rpcuser -P rpcpass \ - --rpccert $TESTNET_PATH/bitcoin/rpc-wallet.cert --rpckey $TESTNET_PATH/bitcoin/rpc-wallet.key \ - --cafile $TESTNET_PATH/bitcoin/rpc.cert \ - --create +bitcoin-cli -regtest \ + -rpcuser= \ + -rpcpassword= \ + -named createwallet \ + wallet_name="" \ + passphrase="" \ + load_on_startup=true \ + descriptors=true ``` +You can generate a btc address through the `getnewaddress` command: -The above instruction is going to prompt you for a password and going to give you the seed. -Store those securely. - -Afterwards, start the wallet service listening to port `18554`: - -```shell -btcwallet --simnet -u rpcuser -P rpcpass --rpclisten=127.0.0.1:18554 \ - --rpccert $TESTNET_PATH/bitcoin/rpc-wallet.cert --rpckey $TESTNET_PATH/bitcoin/rpc-wallet.key \ - --cafile $TESTNET_PATH/bitcoin/rpc.cert +```bash +bitcoin-cli -regtest \ + -rpcuser= \ + -rpcpassword= \ + getnewaddress ``` -Leave this process running. If you get an error that a wallet already exists and you still want -to create one, delete the `wallet.db` file located in the path displayed by the error message. - -Create an address that will be later used for mining. The output below is a sample one. - -```shell -$ btcctl --simnet --wallet -u rpcuser -P rpcpass \ - --rpccert $TESTNET_PATH/bitcoin/rpc-wallet.cert \ - --rpcserver 127.0.0.1 getnewaddress - -SQqHYFTSPh8WAyJvzbAC8hoLbF12UVsE5s -``` - -Finally, restart the btcd service with the new address. -First, kill the `btcd` process that you started in the first step, and then: - -```shell -btcd --simnet --rpclisten 127.0.0.1:18556 --rpcuser rpcuser --rpcpass rpcpass \ - --rpccert $TESTNET_PATH/bitcoin/rpc.cert --rpckey $TESTNET_PATH/bitcoin/rpc.key \ - --miningaddr $MINING_ADDRESS -``` - -where `$MINING_ADDRESS` is the address that you got as an output in the previous command. - #### Generating BTC blocks While running this setup, one might want to generate BTC blocks. -We accomplish that through the btcd `btcctl` utility and the use +We accomplish that through the `bitcoin-cli` utility and the use of the parameters we defined above. ```shell -btcctl --simnet --wallet --rpcuser=rpcuser --rpcpass=rpcpass \ - --rpccert=$TESTNET_PATH/bitcoin/rpc-wallet.cert \ - generate $NUM_BLOCKS +bitcoin-cli -chain=regtest \ + -rpcuser= \ + -rpcpassword= \ + -generate $NUM_BLOCKS ``` where `$NUM_BLOCKS` is the number of blocks you want to generate. @@ -241,7 +210,7 @@ cp sample-vigilante-docker.yml $TESTNET_PATH/vigilante/vigilante.yml make reporter-build ``` -Afterwards, run the above image and attach the directories +Afterward, run the above image and attach the directories that contain the configuration for Babylon, Bitcoin, and the vigilante. ```shell diff --git a/btcclient/client_wallet.go b/btcclient/client_wallet.go index 16c964b..fef4835 100644 --- a/btcclient/client_wallet.go +++ b/btcclient/client_wallet.go @@ -13,7 +13,6 @@ import ( "github.com/babylonlabs-io/vigilante/config" "github.com/babylonlabs-io/vigilante/netparams" - "github.com/babylonlabs-io/vigilante/types" ) // NewWallet creates a new BTC wallet @@ -30,38 +29,21 @@ func NewWallet(cfg *config.BTCConfig, parentLogger *zap.Logger) (*Client, error) wallet.params = params wallet.logger = parentLogger.With(zap.String("module", "btcclient_wallet")).Sugar() - connCfg := &rpcclient.ConnConfig{} - switch cfg.BtcBackend { - case types.Bitcoind: - // TODO Currently we are not using Params field of rpcclient.ConnConfig due to bug in btcd - // when handling signet. - connCfg = &rpcclient.ConnConfig{ - // this will work with node loaded with multiple wallets - Host: cfg.Endpoint + "/wallet/" + cfg.WalletName, - HTTPPostMode: true, - User: cfg.Username, - Pass: cfg.Password, - DisableTLS: cfg.DisableClientTLS, - } - case types.Btcd: - // TODO Currently we are not using Params field of rpcclient.ConnConfig due to bug in btcd - // when handling signet. - connCfg = &rpcclient.ConnConfig{ - Host: cfg.WalletEndpoint, - Endpoint: "ws", // websocket - User: cfg.Username, - Pass: cfg.Password, - DisableTLS: cfg.DisableClientTLS, - Certificates: cfg.ReadWalletCAFile(), - } + connCfg := &rpcclient.ConnConfig{ + // this will work with node loaded with multiple wallets + Host: cfg.Endpoint + "/wallet/" + cfg.WalletName, + HTTPPostMode: true, + User: cfg.Username, + Pass: cfg.Password, + DisableTLS: true, } rpcClient, err := rpcclient.New(connCfg, nil) if err != nil { - return nil, fmt.Errorf("failed to create rpc client to BTC for %s backend: %w", cfg.BtcBackend, err) + return nil, fmt.Errorf("failed to create rpc client to BTC: %w", err) } - wallet.logger.Infof("Successfully connected to %s backend", cfg.BtcBackend) + wallet.logger.Infof("Successfully connected to bitcoind") wallet.Client = rpcClient diff --git a/btcclient/notifier.go b/btcclient/notifier.go index 2ecc10c..79f328b 100644 --- a/btcclient/notifier.go +++ b/btcclient/notifier.go @@ -1,34 +1,19 @@ package btcclient import ( - "encoding/hex" "fmt" "github.com/babylonlabs-io/vigilante/netparams" "net" - "os" "time" "github.com/babylonlabs-io/vigilante/config" - "github.com/babylonlabs-io/vigilante/types" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcwallet/chain" "github.com/lightningnetwork/lnd/blockcache" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs/bitcoindnotify" - "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify" ) -type Btcd struct { - RPCHost string - RPCUser string - RPCPass string - RPCCert string - RawCert string - DisableTLS bool - BlockCacheSize uint64 -} - type Bitcoind struct { RPCHost string RPCUser string @@ -60,45 +45,17 @@ func DefaultBitcoindConfig() Bitcoind { } } -type BtcNodeBackendConfig struct { - Btcd *Btcd - Bitcoind *Bitcoind - ActiveNodeBackend types.SupportedBtcBackend -} - -func CfgToBtcNodeBackendConfig(cfg config.BTCConfig, rawCert string) *BtcNodeBackendConfig { - switch cfg.BtcBackend { - case types.Bitcoind: - defaultBitcoindCfg := DefaultBitcoindConfig() - // Re-rewrite defaults by values from global cfg - defaultBitcoindCfg.RPCHost = cfg.Endpoint - defaultBitcoindCfg.RPCUser = cfg.Username - defaultBitcoindCfg.RPCPass = cfg.Password - defaultBitcoindCfg.ZMQPubRawBlock = cfg.ZmqBlockEndpoint - defaultBitcoindCfg.ZMQPubRawTx = cfg.ZmqTxEndpoint - defaultBitcoindCfg.EstimateMode = cfg.EstimateMode +func ToBitcoindConfig(cfg config.BTCConfig) *Bitcoind { + defaultBitcoindCfg := DefaultBitcoindConfig() + // Re-rewrite defaults by values from global cfg + defaultBitcoindCfg.RPCHost = cfg.Endpoint + defaultBitcoindCfg.RPCUser = cfg.Username + defaultBitcoindCfg.RPCPass = cfg.Password + defaultBitcoindCfg.ZMQPubRawBlock = cfg.ZmqBlockEndpoint + defaultBitcoindCfg.ZMQPubRawTx = cfg.ZmqTxEndpoint + defaultBitcoindCfg.EstimateMode = cfg.EstimateMode - return &BtcNodeBackendConfig{ - ActiveNodeBackend: types.Bitcoind, - Bitcoind: &defaultBitcoindCfg, - } - case types.Btcd: - return &BtcNodeBackendConfig{ - ActiveNodeBackend: types.Btcd, - Btcd: &Btcd{ - RPCHost: cfg.Endpoint, - RPCUser: cfg.Username, - RPCPass: cfg.Password, - RPCCert: cfg.CAFile, - RawCert: rawCert, - DisableTLS: cfg.DisableClientTLS, - // TODO: Make block cache size configurable. Note: this is value is in bytes. - BlockCacheSize: config.DefaultBtcblockCacheSize, - }, - } - default: - panic(fmt.Sprintf("unknown btc backend: %v", cfg.BtcBackend)) - } + return &defaultBitcoindCfg } type NodeBackend struct { @@ -110,9 +67,6 @@ type HintCache interface { chainntnfs.ConfirmHintCache } -// type for disabled hint cache -// TODO: Determine if we need hint cache backed up by database which is provided -// by lnd. type EmptyHintCache struct{} var _ HintCache = (*EmptyHintCache)(nil) @@ -148,116 +102,63 @@ func BuildDialer(rpcHost string) func(string) (net.Conn, error) { } func NewNodeBackend( - cfg *BtcNodeBackendConfig, + cfg *Bitcoind, params *chaincfg.Params, hintCache HintCache, ) (*NodeBackend, error) { - switch cfg.ActiveNodeBackend { - case types.Bitcoind: - bitcoindCfg := &chain.BitcoindConfig{ - ChainParams: params, - Host: cfg.Bitcoind.RPCHost, - User: cfg.Bitcoind.RPCUser, - Pass: cfg.Bitcoind.RPCPass, - Dialer: BuildDialer(cfg.Bitcoind.RPCHost), - PrunedModeMaxPeers: cfg.Bitcoind.PrunedNodeMaxPeers, - } - - if cfg.Bitcoind.RPCPolling { - bitcoindCfg.PollingConfig = &chain.PollingConfig{ - BlockPollingInterval: cfg.Bitcoind.BlockPollingInterval, - TxPollingInterval: cfg.Bitcoind.TxPollingInterval, - TxPollingIntervalJitter: config.DefaultTxPollingJitter, - } - } else { - bitcoindCfg.ZMQConfig = &chain.ZMQConfig{ - ZMQBlockHost: cfg.Bitcoind.ZMQPubRawBlock, - ZMQTxHost: cfg.Bitcoind.ZMQPubRawTx, - ZMQReadDeadline: cfg.Bitcoind.ZMQReadDeadline, - MempoolPollingInterval: cfg.Bitcoind.TxPollingInterval, - PollingIntervalJitter: config.DefaultTxPollingJitter, - } - } - - bitcoindConn, err := chain.NewBitcoindConn(bitcoindCfg) - if err != nil { - return nil, err - } - - if err := bitcoindConn.Start(); err != nil { - return nil, fmt.Errorf("unable to connect to "+ - "bitcoind: %v", err) - } - - chainNotifier := bitcoindnotify.New( - bitcoindConn, params, hintCache, - hintCache, blockcache.NewBlockCache(cfg.Bitcoind.BlockCacheSize), - ) - - return &NodeBackend{ - ChainNotifier: chainNotifier, - }, nil - - case types.Btcd: - btcdUser := cfg.Btcd.RPCUser - btcdPass := cfg.Btcd.RPCPass - btcdHost := cfg.Btcd.RPCHost - - var certs []byte - if !cfg.Btcd.DisableTLS { - if cfg.Btcd.RawCert != "" { - decoded, err := hex.DecodeString(cfg.Btcd.RawCert) - if err != nil { - return nil, fmt.Errorf("error decoding btcd cert: %v", err) - } - certs = decoded + bitcoindCfg := &chain.BitcoindConfig{ + ChainParams: params, + Host: cfg.RPCHost, + User: cfg.RPCUser, + Pass: cfg.RPCPass, + Dialer: BuildDialer(cfg.RPCHost), + PrunedModeMaxPeers: cfg.PrunedNodeMaxPeers, + } - } else { - certificates, err := os.ReadFile(cfg.Btcd.RPCCert) - if err != nil { - return nil, fmt.Errorf("error reading btcd cert file: %v", err) - } - certs = certificates - } + if cfg.RPCPolling { + bitcoindCfg.PollingConfig = &chain.PollingConfig{ + BlockPollingInterval: cfg.BlockPollingInterval, + TxPollingInterval: cfg.TxPollingInterval, + TxPollingIntervalJitter: config.DefaultTxPollingJitter, } - - rpcConfig := &rpcclient.ConnConfig{ - Host: btcdHost, - Endpoint: "ws", - User: btcdUser, - Pass: btcdPass, - Certificates: certs, - DisableTLS: cfg.Btcd.DisableTLS, - DisableConnectOnNew: true, - DisableAutoReconnect: false, + } else { + bitcoindCfg.ZMQConfig = &chain.ZMQConfig{ + ZMQBlockHost: cfg.ZMQPubRawBlock, + ZMQTxHost: cfg.ZMQPubRawTx, + ZMQReadDeadline: cfg.ZMQReadDeadline, + MempoolPollingInterval: cfg.TxPollingInterval, + PollingIntervalJitter: config.DefaultTxPollingJitter, } + } - chainNotifier, err := btcdnotify.New( - rpcConfig, params, hintCache, - hintCache, blockcache.NewBlockCache(cfg.Btcd.BlockCacheSize), - ) + bitcoindConn, err := chain.NewBitcoindConn(bitcoindCfg) + if err != nil { + return nil, err + } - if err != nil { - return nil, err - } + if err := bitcoindConn.Start(); err != nil { + return nil, fmt.Errorf("unable to connect to "+ + "bitcoind: %v", err) + } - return &NodeBackend{ - ChainNotifier: chainNotifier, - }, nil + chainNotifier := bitcoindnotify.New( + bitcoindConn, params, hintCache, + hintCache, blockcache.NewBlockCache(cfg.BlockCacheSize), + ) - default: - return nil, fmt.Errorf("unknown node backend: %v", cfg.ActiveNodeBackend) - } + return &NodeBackend{ + ChainNotifier: chainNotifier, + }, nil } // NewNodeBackendWithParams creates a new NodeBackend by incorporating parameter retrieval and config conversion. -func NewNodeBackendWithParams(cfg config.BTCConfig, rawCert string) (*NodeBackend, error) { +func NewNodeBackendWithParams(cfg config.BTCConfig) (*NodeBackend, error) { btcParams, err := netparams.GetBTCParams(cfg.NetParams) if err != nil { return nil, fmt.Errorf("failed to get BTC net params: %w", err) } - btcNotifier, err := NewNodeBackend(CfgToBtcNodeBackendConfig(cfg, rawCert), btcParams, &EmptyHintCache{}) + btcNotifier, err := NewNodeBackend(ToBitcoindConfig(cfg), btcParams, &EmptyHintCache{}) if err != nil { return nil, fmt.Errorf("failed to initialize notifier: %w", err) } diff --git a/cmd/vigilante/cmd/btcstaking_tracker.go b/cmd/vigilante/cmd/btcstaking_tracker.go index d479417..1874b75 100644 --- a/cmd/vigilante/cmd/btcstaking_tracker.go +++ b/cmd/vigilante/cmd/btcstaking_tracker.go @@ -68,7 +68,7 @@ func GetBTCStakingTracker() *cobra.Command { // create BTC notifier // TODO: is it possible to merge BTC client and BTC notifier? - btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC, "") + btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC) if err != nil { panic(err) } diff --git a/cmd/vigilante/cmd/monitor.go b/cmd/vigilante/cmd/monitor.go index 49259c5..fe2b742 100644 --- a/cmd/vigilante/cmd/monitor.go +++ b/cmd/vigilante/cmd/monitor.go @@ -74,7 +74,7 @@ func GetMonitorCmd() *cobra.Command { monitorMetrics := metrics.NewMonitorMetrics() // create the chain notifier - btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC, "") + btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC) if err != nil { panic(err) } diff --git a/cmd/vigilante/cmd/reporter.go b/cmd/vigilante/cmd/reporter.go index 5c9a0b6..0d763d1 100644 --- a/cmd/vigilante/cmd/reporter.go +++ b/cmd/vigilante/cmd/reporter.go @@ -62,7 +62,7 @@ func GetReporterCmd() *cobra.Command { reporterMetrics := metrics.NewReporterMetrics() // create the chain notifier - btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC, "") + btcNotifier, err := btcclient.NewNodeBackendWithParams(cfg.BTC) if err != nil { panic(err) } diff --git a/config/bitcoin.go b/config/bitcoin.go index aa2b5e9..0b89ea0 100644 --- a/config/bitcoin.go +++ b/config/bitcoin.go @@ -3,8 +3,6 @@ package config import ( "errors" "fmt" - "os" - "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/babylonlabs-io/vigilante/types" @@ -12,27 +10,22 @@ import ( // BTCConfig defines configuration for the Bitcoin client type BTCConfig struct { - DisableClientTLS bool `mapstructure:"no-client-tls"` - CAFile string `mapstructure:"ca-file"` - Endpoint string `mapstructure:"endpoint"` - WalletEndpoint string `mapstructure:"wallet-endpoint"` - WalletPassword string `mapstructure:"wallet-password"` - WalletName string `mapstructure:"wallet-name"` - WalletCAFile string `mapstructure:"wallet-ca-file"` - WalletLockTime int64 `mapstructure:"wallet-lock-time"` // time duration in which the wallet remains unlocked, in seconds - TxFeeMin chainfee.SatPerKVByte `mapstructure:"tx-fee-min"` // minimum tx fee, sat/kvb - TxFeeMax chainfee.SatPerKVByte `mapstructure:"tx-fee-max"` // maximum tx fee, sat/kvb - DefaultFee chainfee.SatPerKVByte `mapstructure:"default-fee"` // default BTC tx fee in case estimation fails, sat/kvb - EstimateMode string `mapstructure:"estimate-mode"` // the BTC tx fee estimate mode, which is only used by bitcoind, must be either ECONOMICAL or CONSERVATIVE - TargetBlockNum int64 `mapstructure:"target-block-num"` // this implies how soon the tx is estimated to be included in a block, e.g., 1 means the tx is estimated to be included in the next block - NetParams string `mapstructure:"net-params"` - Username string `mapstructure:"username"` - Password string `mapstructure:"password"` - ReconnectAttempts int `mapstructure:"reconnect-attempts"` - BtcBackend types.SupportedBtcBackend `mapstructure:"btc-backend"` - ZmqSeqEndpoint string `mapstructure:"zmq-seq-endpoint"` - ZmqBlockEndpoint string `mapstructure:"zmq-block-endpoint"` - ZmqTxEndpoint string `mapstructure:"zmq-tx-endpoint"` + Endpoint string `mapstructure:"endpoint"` + WalletPassword string `mapstructure:"wallet-password"` + WalletName string `mapstructure:"wallet-name"` + WalletLockTime int64 `mapstructure:"wallet-lock-time"` // time duration in which the wallet remains unlocked, in seconds + TxFeeMin chainfee.SatPerKVByte `mapstructure:"tx-fee-min"` // minimum tx fee, sat/kvb + TxFeeMax chainfee.SatPerKVByte `mapstructure:"tx-fee-max"` // maximum tx fee, sat/kvb + DefaultFee chainfee.SatPerKVByte `mapstructure:"default-fee"` // default BTC tx fee in case estimation fails, sat/kvb + EstimateMode string `mapstructure:"estimate-mode"` // the BTC tx fee estimate mode, which is only used by bitcoind, must be either ECONOMICAL or CONSERVATIVE + TargetBlockNum int64 `mapstructure:"target-block-num"` // this implies how soon the tx is estimated to be included in a block, e.g., 1 means the tx is estimated to be included in the next block + NetParams string `mapstructure:"net-params"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + ReconnectAttempts int `mapstructure:"reconnect-attempts"` + ZmqSeqEndpoint string `mapstructure:"zmq-seq-endpoint"` + ZmqBlockEndpoint string `mapstructure:"zmq-block-endpoint"` + ZmqTxEndpoint string `mapstructure:"zmq-tx-endpoint"` } func (cfg *BTCConfig) Validate() error { @@ -44,27 +37,21 @@ func (cfg *BTCConfig) Validate() error { return errors.New("invalid net params") } - if _, ok := types.GetValidBtcBackends()[cfg.BtcBackend]; !ok { - return errors.New("invalid btc backend") + // TODO: implement regex validation for zmq endpoint + if cfg.ZmqBlockEndpoint == "" { + return errors.New("zmq block endpoint cannot be empty") } - if cfg.BtcBackend == types.Bitcoind { - // TODO: implement regex validation for zmq endpoint - if cfg.ZmqBlockEndpoint == "" { - return errors.New("zmq block endpoint cannot be empty") - } - - if cfg.ZmqTxEndpoint == "" { - return errors.New("zmq tx endpoint cannot be empty") - } + if cfg.ZmqTxEndpoint == "" { + return errors.New("zmq tx endpoint cannot be empty") + } - if cfg.ZmqSeqEndpoint == "" { - return errors.New("zmq seq endpoint cannot be empty") - } + if cfg.ZmqSeqEndpoint == "" { + return errors.New("zmq seq endpoint cannot be empty") + } - if cfg.EstimateMode != "ECONOMICAL" && cfg.EstimateMode != "CONSERVATIVE" { - return errors.New("estimate-mode must be either ECONOMICAL or CONSERVATIVE when the backend is bitcoind") - } + if cfg.EstimateMode != "ECONOMICAL" && cfg.EstimateMode != "CONSERVATIVE" { + return errors.New("estimate-mode must be either ECONOMICAL or CONSERVATIVE when the backend is bitcoind") } if cfg.TargetBlockNum <= 0 { @@ -109,15 +96,10 @@ const ( func DefaultBTCConfig() BTCConfig { return BTCConfig{ - DisableClientTLS: false, - CAFile: defaultBtcCAFile, Endpoint: DefaultRpcBtcNodeHost, - WalletEndpoint: "localhost:18554", WalletPassword: "walletpass", WalletName: "default", - WalletCAFile: defaultBtcWalletCAFile, WalletLockTime: 10, - BtcBackend: types.Btcd, TxFeeMax: chainfee.SatPerKVByte(20 * 1000), // 20,000sat/kvb = 20sat/vbyte TxFeeMin: chainfee.SatPerKVByte(1 * 1000), // 1,000sat/kvb = 1sat/vbyte DefaultFee: chainfee.SatPerKVByte(1 * 1000), // 1,000sat/kvb = 1sat/vbyte @@ -132,35 +114,3 @@ func DefaultBTCConfig() BTCConfig { ZmqTxEndpoint: DefaultZmqTxEndpoint, } } - -func (cfg *BTCConfig) ReadCAFile() []byte { - if cfg.DisableClientTLS { - return nil - } - - // Read certificate file if TLS is not disabled. - certs, err := os.ReadFile(cfg.CAFile) - if err != nil { - // If there's an error reading the CA file, continue - // with nil certs and without the client connection. - return nil - } - - return certs -} - -func (cfg *BTCConfig) ReadWalletCAFile() []byte { - if cfg.DisableClientTLS { - // Chain server RPC TLS is disabled - return nil - } - - // Read certificate file if TLS is not disabled. - certs, err := os.ReadFile(cfg.WalletCAFile) - if err != nil { - // If there's an error reading the CA file, continue - // with nil certs and without the client connection. - return nil - } - return certs -} diff --git a/config/config.go b/config/config.go index 281c797..f498f65 100644 --- a/config/config.go +++ b/config/config.go @@ -18,12 +18,10 @@ const ( ) var ( - defaultBtcCAFile = filepath.Join(btcutil.AppDataDir("btcd", false), "rpc.cert") - defaultBtcWalletCAFile = filepath.Join(btcutil.AppDataDir("btcwallet", false), "rpc.cert") - defaultAppDataDir = btcutil.AppDataDir("babylon-vigilante", false) - defaultConfigFile = filepath.Join(defaultAppDataDir, defaultConfigFilename) - defaultRPCKeyFile = filepath.Join(defaultAppDataDir, "rpc.key") - defaultRPCCertFile = filepath.Join(defaultAppDataDir, "rpc.cert") + defaultAppDataDir = btcutil.AppDataDir("babylon-vigilante", false) + defaultConfigFile = filepath.Join(defaultAppDataDir, defaultConfigFilename) + defaultRPCKeyFile = filepath.Join(defaultAppDataDir, "rpc.key") + defaultRPCCertFile = filepath.Join(defaultAppDataDir, "rpc.cert") ) // Config defines the server's top level configuration diff --git a/e2etest/atomicslasher_e2e_test.go b/e2etest/atomicslasher_e2e_test.go index c979902..ba56d6b 100644 --- a/e2etest/atomicslasher_e2e_test.go +++ b/e2etest/atomicslasher_e2e_test.go @@ -36,10 +36,8 @@ func TestAtomicSlasher(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) @@ -156,10 +154,8 @@ func TestAtomicSlasher_Unbonding(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) diff --git a/e2etest/reporter_e2e_test.go b/e2etest/reporter_e2e_test.go index 9fec7d9..2d25fa3 100644 --- a/e2etest/reporter_e2e_test.go +++ b/e2etest/reporter_e2e_test.go @@ -65,7 +65,7 @@ func TestReporter_BoostrapUnderFrequentBTCHeaders(t *testing.T) { // create the chain notifier btcParams, err := netparams.GetBTCParams(tm.Config.BTC.NetParams) require.NoError(t, err) - btcCfg := btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, "") + btcCfg := btcclient.ToBitcoindConfig(tm.Config.BTC) btcNotifier, err := btcclient.NewNodeBackend(btcCfg, btcParams, &btcclient.EmptyHintCache{}) require.NoError(t, err) @@ -128,7 +128,7 @@ func TestRelayHeadersAndHandleRollbacks(t *testing.T) { btcParams, err := netparams.GetBTCParams(tm.Config.BTC.NetParams) require.NoError(t, err) - btcCfg := btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, "") + btcCfg := btcclient.ToBitcoindConfig(tm.Config.BTC) btcNotifier, err := btcclient.NewNodeBackend(btcCfg, btcParams, &btcclient.EmptyHintCache{}) require.NoError(t, err) @@ -179,7 +179,7 @@ func TestHandleReorgAfterRestart(t *testing.T) { btcParams, err := netparams.GetBTCParams(tm.Config.BTC.NetParams) require.NoError(t, err) - btcCfg := btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, "") + btcCfg := btcclient.ToBitcoindConfig(tm.Config.BTC) btcNotifier, err := btcclient.NewNodeBackend(btcCfg, btcParams, &btcclient.EmptyHintCache{}) require.NoError(t, err) diff --git a/e2etest/slasher_e2e_test.go b/e2etest/slasher_e2e_test.go index b9a94e3..01a87b5 100644 --- a/e2etest/slasher_e2e_test.go +++ b/e2etest/slasher_e2e_test.go @@ -28,10 +28,8 @@ func TestSlasher_GracefulShutdown(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) @@ -80,10 +78,8 @@ func TestSlasher_Slasher(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) @@ -150,10 +146,8 @@ func TestSlasher_SlashingUnbonding(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) @@ -245,10 +239,9 @@ func TestSlasher_Bootstrapping(t *testing.T) { tm.VoteAndEquivocate(t, fpSK) emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false + backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) diff --git a/e2etest/test_manager.go b/e2etest/test_manager.go index e7e2b00..d5b9936 100644 --- a/e2etest/test_manager.go +++ b/e2etest/test_manager.go @@ -17,7 +17,6 @@ import ( btclctypes "github.com/babylonlabs-io/babylon/x/btclightclient/types" "github.com/babylonlabs-io/vigilante/btcclient" "github.com/babylonlabs-io/vigilante/config" - "github.com/babylonlabs-io/vigilante/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -39,16 +38,12 @@ var ( func defaultVigilanteConfig() *config.Config { defaultConfig := config.DefaultConfig() - // Config setting necessary to connect btcd daemon defaultConfig.BTC.NetParams = regtestParams.Name defaultConfig.BTC.Endpoint = "127.0.0.1:18443" // Config setting necessary to connect btcwallet daemon - defaultConfig.BTC.BtcBackend = types.Bitcoind - defaultConfig.BTC.WalletEndpoint = "127.0.0.1:18554" defaultConfig.BTC.WalletPassword = "pass" defaultConfig.BTC.Username = "user" defaultConfig.BTC.Password = "pass" - defaultConfig.BTC.DisableClientTLS = true defaultConfig.BTC.ZmqSeqEndpoint = config.DefaultZmqSeqEndpoint return defaultConfig diff --git a/e2etest/unbondingwatcher_e2e_test.go b/e2etest/unbondingwatcher_e2e_test.go index fc60c51..d4ba0d9 100644 --- a/e2etest/unbondingwatcher_e2e_test.go +++ b/e2etest/unbondingwatcher_e2e_test.go @@ -30,10 +30,8 @@ func TestUnbondingWatcher(t *testing.T) { emptyHintCache := btcclient.EmptyHintCache{} - // TODO: our config only support btcd wallet tls, not btcd directly - tm.Config.BTC.DisableClientTLS = false backend, err := btcclient.NewNodeBackend( - btcclient.CfgToBtcNodeBackendConfig(tm.Config.BTC, ""), + btcclient.ToBitcoindConfig(tm.Config.BTC), &chaincfg.RegressionNetParams, &emptyHintCache, ) diff --git a/sample-vigilante.yml b/sample-vigilante.yml index 03d0b2d..076733e 100644 --- a/sample-vigilante.yml +++ b/sample-vigilante.yml @@ -21,7 +21,6 @@ btc: username: rpcuser password: rpcpass reconnect-attempts: 3 - btc-backend: btcd # {btcd, bitcoind} zmq-endpoint: ~ # use tcp://127.0.0.1:29000 if btc-backend is bitcoind babylon: key: node0 diff --git a/submitter/relayer/estimator.go b/submitter/relayer/estimator.go index 33b2ec3..a9a395d 100644 --- a/submitter/relayer/estimator.go +++ b/submitter/relayer/estimator.go @@ -7,59 +7,33 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/babylonlabs-io/vigilante/config" - "github.com/babylonlabs-io/vigilante/types" ) -// NewFeeEstimator creates a fee estimator based on the given backend -// currently, we only support bitcoind and btcd +// NewFeeEstimator creates a fee estimator for bitcoind func NewFeeEstimator(cfg *config.BTCConfig) (chainfee.Estimator, error) { + // TODO Currently we are not using Params field of rpcclient.ConnConfig due to bug in btcd + // when handling signet. + // todo(lazar955): check if we should start specifying this, considering we are no longer using btcd based on comment above ^^ + connCfg := &rpcclient.ConnConfig{ + // this will work with node loaded with multiple wallets + Host: cfg.Endpoint + "/wallet/" + cfg.WalletName, + HTTPPostMode: true, + User: cfg.Username, + Pass: cfg.Password, + DisableTLS: true, + } + + estimator, err := chainfee.NewBitcoindEstimator( + *connCfg, cfg.EstimateMode, cfg.DefaultFee.FeePerKWeight(), + ) - var connCfg *rpcclient.ConnConfig - var est chainfee.Estimator - switch cfg.BtcBackend { - case types.Bitcoind: - // TODO Currently we are not using Params field of rpcclient.ConnConfig due to bug in btcd - // when handling signet. - connCfg = &rpcclient.ConnConfig{ - // this will work with node loaded with multiple wallets - Host: cfg.Endpoint + "/wallet/" + cfg.WalletName, - HTTPPostMode: true, - User: cfg.Username, - Pass: cfg.Password, - DisableTLS: cfg.DisableClientTLS, - } - bitcoindEst, err := chainfee.NewBitcoindEstimator( - *connCfg, cfg.EstimateMode, cfg.DefaultFee.FeePerKWeight(), - ) - if err != nil { - return nil, fmt.Errorf("failed to create fee estimator for %s backend: %w", types.Bitcoind, err) - } - est = bitcoindEst - case types.Btcd: - // TODO Currently we are not using Params field of rpcclient.ConnConfig due to bug in btcd - // when handling signet. - connCfg = &rpcclient.ConnConfig{ - Host: cfg.WalletEndpoint, - Endpoint: "ws", // websocket - User: cfg.Username, - Pass: cfg.Password, - DisableTLS: cfg.DisableClientTLS, - Certificates: cfg.ReadWalletCAFile(), - } - btcdEst, err := chainfee.NewBtcdEstimator( - *connCfg, cfg.DefaultFee.FeePerKWeight(), - ) - if err != nil { - return nil, fmt.Errorf("failed to create fee estimator for %s backend: %w", types.Btcd, err) - } - est = btcdEst - default: - return nil, fmt.Errorf("unsupported backend for fee estimator") + if err != nil { + return nil, fmt.Errorf("failed to create fee estimator: %w", err) } - if err := est.Start(); err != nil { - return nil, fmt.Errorf("failed to initiate the fee estimator for %s backend: %w", cfg.BtcBackend, err) + if err := estimator.Start(); err != nil { + return nil, fmt.Errorf("failed to initiate the fee estimator: %w", err) } - return est, nil + return estimator, nil } diff --git a/submitter/submitter.go b/submitter/submitter.go index f689cb4..da1fd74 100644 --- a/submitter/submitter.go +++ b/submitter/submitter.go @@ -69,7 +69,7 @@ func New( if err != nil { return nil, fmt.Errorf("failed to create fee estimator: %w", err) } - logger.Sugar().Infof("Successfully started fee estimator for %s backend", btcCfg.BtcBackend) + logger.Sugar().Infof("Successfully started fee estimator for bitcoind") r := relayer.New( btcWallet, diff --git a/types/utils.go b/types/utils.go index 4529782..bb39fd5 100644 --- a/types/utils.go +++ b/types/utils.go @@ -1,13 +1,12 @@ package types import ( - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" ) type ( SupportedBtcNetwork string - SupportedBtcBackend string ) const ( @@ -16,19 +15,12 @@ const ( BtcSimnet SupportedBtcNetwork = "simnet" BtcRegtest SupportedBtcNetwork = "regtest" BtcSignet SupportedBtcNetwork = "signet" - - Btcd SupportedBtcBackend = "btcd" - Bitcoind SupportedBtcBackend = "bitcoind" ) func (c SupportedBtcNetwork) String() string { return string(c) } -func (c SupportedBtcBackend) String() string { - return string(c) -} - func GetWrappedTxs(msg *wire.MsgBlock) []*btcutil.Tx { btcTxs := []*btcutil.Tx{} @@ -53,12 +45,3 @@ func GetValidNetParams() map[string]bool { return params } - -func GetValidBtcBackends() map[SupportedBtcBackend]bool { - validBtcBackends := map[SupportedBtcBackend]bool{ - Bitcoind: true, - Btcd: true, - } - - return validBtcBackends -}