config: parse different ZMQ hosts for block and tx notifications
Due to recent changes to the BitcoindClient interface, we now require the backing bitcoind to use different hosts for its ZMQ raw block and raw transaction notifications. This was needed as the notification queue maintained by the bitcoind node would sometimes overflow with transactions and cause block notifications to be dropped/missed. In this commit, we expand extractBitcoindRPCParams to account for this.
This commit is contained in:
parent
533a45574c
commit
75192a15e3
118
config.go
118
config.go
@ -133,11 +133,12 @@ type btcdConfig struct {
|
||||
}
|
||||
|
||||
type bitcoindConfig struct {
|
||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||
ZMQPath string `long:"zmqpath" description:"The path to the ZMQ socket providing at least raw blocks. Raw transactions can be handled as well."`
|
||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||
ZMQPubRawBlock string `long:"zmqpubrawblock" description:"The address listening for ZMQ connections to deliver raw block notifications"`
|
||||
ZMQPubRawTx string `long:"zmqpubrawtx" description:"The address listening for ZMQ connections to deliver raw transaction notifications"`
|
||||
}
|
||||
|
||||
type autoPilotConfig struct {
|
||||
@ -1057,8 +1058,12 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
daemonName = "btcd"
|
||||
confDir = conf.Dir
|
||||
confFile = "btcd"
|
||||
case litecoinChain:
|
||||
daemonName = "ltcd"
|
||||
confDir = conf.Dir
|
||||
confFile = "ltcd"
|
||||
}
|
||||
|
||||
// If only ONE of RPCUser or RPCPass is set, we assume the
|
||||
@ -1068,18 +1073,11 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
"%[1]v.rpcuser, %[1]v.rpcpass", daemonName)
|
||||
}
|
||||
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
confDir = conf.Dir
|
||||
confFile = "btcd"
|
||||
case litecoinChain:
|
||||
confDir = conf.Dir
|
||||
confFile = "ltcd"
|
||||
}
|
||||
case *bitcoindConfig:
|
||||
// If all of RPCUser, RPCPass, and ZMQPath are set, we assume
|
||||
// those parameters are good to use.
|
||||
if conf.RPCUser != "" && conf.RPCPass != "" && conf.ZMQPath != "" {
|
||||
// If all of RPCUser, RPCPass, ZMQBlockHost, and ZMQTxHost are
|
||||
// set, we assume those parameters are good to use.
|
||||
if conf.RPCUser != "" && conf.RPCPass != "" &&
|
||||
conf.ZMQPubRawBlock != "" && conf.ZMQPubRawTx != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1087,25 +1085,24 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
daemonName = "bitcoind"
|
||||
case litecoinChain:
|
||||
daemonName = "litecoind"
|
||||
}
|
||||
// If only one or two of the parameters are set, we assume the
|
||||
// user did that unintentionally.
|
||||
if conf.RPCUser != "" || conf.RPCPass != "" || conf.ZMQPath != "" {
|
||||
return fmt.Errorf("please set all or none of "+
|
||||
"%[1]v.rpcuser, %[1]v.rpcpass, "+
|
||||
"and %[1]v.zmqpath", daemonName)
|
||||
}
|
||||
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
confDir = conf.Dir
|
||||
confFile = "bitcoin"
|
||||
case litecoinChain:
|
||||
daemonName = "litecoind"
|
||||
confDir = conf.Dir
|
||||
confFile = "litecoin"
|
||||
}
|
||||
|
||||
// If only one or two of the parameters are set, we assume the
|
||||
// user did that unintentionally.
|
||||
if conf.RPCUser != "" || conf.RPCPass != "" ||
|
||||
conf.ZMQPubRawBlock != "" || conf.ZMQPubRawTx != "" {
|
||||
|
||||
return fmt.Errorf("please set all or none of "+
|
||||
"%[1]v.rpcuser, %[1]v.rpcpass, "+
|
||||
"%[1]v.zmqpubrawblock, %[1]v.zmqpubrawtx",
|
||||
daemonName)
|
||||
}
|
||||
}
|
||||
|
||||
// If we're in simnet mode, then the running btcd instance won't read
|
||||
@ -1132,13 +1129,15 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
||||
case "bitcoind", "litecoind":
|
||||
nConf := nodeConfig.(*bitcoindConfig)
|
||||
rpcUser, rpcPass, zmqPath, err := extractBitcoindRPCParams(confFile)
|
||||
rpcUser, rpcPass, zmqBlockHost, zmqTxHost, err :=
|
||||
extractBitcoindRPCParams(confFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to extract RPC credentials:"+
|
||||
" %v, cannot start w/o RPC connection",
|
||||
err)
|
||||
}
|
||||
nConf.RPCUser, nConf.RPCPass, nConf.ZMQPath = rpcUser, rpcPass, zmqPath
|
||||
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
||||
nConf.ZMQPubRawBlock, nConf.ZMQPubRawTx = zmqBlockHost, zmqTxHost
|
||||
}
|
||||
|
||||
fmt.Printf("Automatically obtained %v's RPC credentials\n", daemonName)
|
||||
@ -1196,13 +1195,12 @@ func extractBtcdRPCParams(btcdConfigPath string) (string, string, error) {
|
||||
// location of bitcoind's bitcoin.conf on the target system. The routine looks
|
||||
// for a cookie first, optionally following the datadir configuration option in
|
||||
// the bitcoin.conf. If it doesn't find one, it looks for rpcuser/rpcpassword.
|
||||
func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string, error) {
|
||||
|
||||
func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string, string, error) {
|
||||
// First, we'll open up the bitcoind configuration file found at the
|
||||
// target destination.
|
||||
bitcoindConfigFile, err := os.Open(bitcoindConfigPath)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
defer bitcoindConfigFile.Close()
|
||||
|
||||
@ -1210,18 +1208,36 @@ func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string
|
||||
// we can attempt to locate the RPC credentials.
|
||||
configContents, err := ioutil.ReadAll(bitcoindConfigFile)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
|
||||
// First, we look for the ZMQ path for raw blocks. If raw transactions
|
||||
// are sent over this interface, we can also get unconfirmed txs.
|
||||
zmqPathRE, err := regexp.Compile(`(?m)^\s*zmqpubrawblock\s*=\s*([^\s]+)`)
|
||||
// First, we'll look for the ZMQ hosts providing raw block and raw
|
||||
// transaction notifications.
|
||||
zmqBlockHostRE, err := regexp.Compile(
|
||||
`(?m)^\s*zmqpubrawblock\s*=\s*([^\s]+)`,
|
||||
)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
zmqPathSubmatches := zmqPathRE.FindSubmatch(configContents)
|
||||
if len(zmqPathSubmatches) < 2 {
|
||||
return "", "", "", fmt.Errorf("unable to find zmqpubrawblock in config")
|
||||
zmqBlockHostSubmatches := zmqBlockHostRE.FindSubmatch(configContents)
|
||||
if len(zmqBlockHostSubmatches) < 2 {
|
||||
return "", "", "", "", fmt.Errorf("unable to find " +
|
||||
"zmqpubrawblock in config")
|
||||
}
|
||||
zmqTxHostRE, err := regexp.Compile(`(?m)^\s*zmqpubrawtx\s*=\s*([^\s]+)`)
|
||||
if err != nil {
|
||||
return "", "", "", "", err
|
||||
}
|
||||
zmqTxHostSubmatches := zmqTxHostRE.FindSubmatch(configContents)
|
||||
if len(zmqTxHostSubmatches) < 2 {
|
||||
return "", "", "", "", errors.New("unable to find zmqpubrawtx " +
|
||||
"in config")
|
||||
}
|
||||
zmqBlockHost := string(zmqBlockHostSubmatches[1])
|
||||
zmqTxHost := string(zmqTxHostSubmatches[1])
|
||||
if zmqBlockHost == zmqTxHost {
|
||||
return "", "", "", "", errors.New("zmqpubrawblock and " +
|
||||
"zmqpubrawtx must be different")
|
||||
}
|
||||
|
||||
// Next, we'll try to find an auth cookie. We need to detect the chain
|
||||
@ -1229,7 +1245,7 @@ func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string
|
||||
dataDir := path.Dir(bitcoindConfigPath)
|
||||
dataDirRE, err := regexp.Compile(`(?m)^\s*datadir\s*=\s*([^\s]+)`)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
dataDirSubmatches := dataDirRE.FindSubmatch(configContents)
|
||||
if dataDirSubmatches != nil {
|
||||
@ -1250,8 +1266,8 @@ func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string
|
||||
if err == nil {
|
||||
splitCookie := strings.Split(string(cookie), ":")
|
||||
if len(splitCookie) == 2 {
|
||||
return splitCookie[0], splitCookie[1],
|
||||
string(zmqPathSubmatches[1]), nil
|
||||
return splitCookie[0], splitCookie[1], zmqBlockHost,
|
||||
zmqTxHost, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -1260,11 +1276,12 @@ func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string
|
||||
// expression then we'll exit with an error.
|
||||
rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser\s*=\s*([^\s]+)`)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
userSubmatches := rpcUserRegexp.FindSubmatch(configContents)
|
||||
if userSubmatches == nil {
|
||||
return "", "", "", fmt.Errorf("unable to find rpcuser in config")
|
||||
return "", "", "", "", fmt.Errorf("unable to find rpcuser in " +
|
||||
"config")
|
||||
}
|
||||
|
||||
// Similarly, we'll use another regular expression to find the set
|
||||
@ -1272,15 +1289,16 @@ func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string
|
||||
// error.
|
||||
rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpassword\s*=\s*([^\s]+)`)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return "", "", "", "", err
|
||||
}
|
||||
passSubmatches := rpcPassRegexp.FindSubmatch(configContents)
|
||||
if passSubmatches == nil {
|
||||
return "", "", "", fmt.Errorf("unable to find rpcpassword in config")
|
||||
return "", "", "", "", fmt.Errorf("unable to find rpcpassword " +
|
||||
"in config")
|
||||
}
|
||||
|
||||
return string(userSubmatches[1]), string(passSubmatches[1]),
|
||||
string(zmqPathSubmatches[1]), nil
|
||||
zmqBlockHost, zmqTxHost, nil
|
||||
}
|
||||
|
||||
// normalizeNetwork returns the common name of a network type used to create
|
||||
|
Loading…
Reference in New Issue
Block a user