From 25b540fec4a22b44cdb9648ab3587a675e5853fd Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 24 May 2019 18:16:33 -0700 Subject: [PATCH] chainregistry+config: add neutrino flag to assert filter header chain --- chainregistry.go | 38 ++++++++++++++++++++++++++++++++++++++ config.go | 13 +++++++------ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/chainregistry.go b/chainregistry.go index e7b6b841..4962ee02 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -19,6 +19,7 @@ import ( "github.com/btcsuite/btcwallet/wallet" "github.com/btcsuite/btcwallet/walletdb" "github.com/lightninglabs/neutrino" + "github.com/lightninglabs/neutrino/headerfs" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs/bitcoindnotify" "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify" @@ -705,6 +706,13 @@ func initNeutrinoBackend(chainDir string) (*neutrino.ChainService, func(), error "database: %v", err) } + headerStateAssertion, err := parseHeaderStateAssertion( + cfg.NeutrinoMode.AssertFilterHeader, + ) + if err != nil { + return nil, nil, err + } + // With the database open, we can now create an instance of the // neutrino light client. We pass in relevant configuration parameters // required. @@ -735,6 +743,7 @@ func initNeutrinoBackend(chainDir string) (*neutrino.ChainService, func(), error return ips, nil }, + AssertFilterHeader: headerStateAssertion, } neutrino.MaxPeers = 8 @@ -758,3 +767,32 @@ func initNeutrinoBackend(chainDir string) (*neutrino.ChainService, func(), error return neutrinoCS, cleanUp, nil } + +// parseHeaderStateAssertion parses the user-specified neutrino header state +// into a headerfs.FilterHeader. +func parseHeaderStateAssertion(state string) (*headerfs.FilterHeader, error) { + if len(state) == 0 { + return nil, nil + } + + split := strings.Split(state, ":") + if len(split) != 2 { + return nil, fmt.Errorf("header state assertion %v in "+ + "unexpected format, expected format height:hash", state) + } + + height, err := strconv.ParseUint(split[0], 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid filter header height: %v", err) + } + + hash, err := chainhash.NewHashFromStr(split[1]) + if err != nil { + return nil, fmt.Errorf("invalid filter header hash: %v", err) + } + + return &headerfs.FilterHeader{ + Height: uint32(height), + FilterHash: *hash, + }, nil +} diff --git a/config.go b/config.go index c6e4c875..09077620 100644 --- a/config.go +++ b/config.go @@ -169,12 +169,13 @@ type chainConfig struct { } type neutrinoConfig struct { - AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` - ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` - MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"` - BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` - BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` - FeeURL string `long:"feeurl" description:"Optional URL for fee estimation. If a URL is not specified, static fees will be used for estimation."` + AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` + ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` + MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"` + BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` + BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` + FeeURL string `long:"feeurl" description:"Optional URL for fee estimation. If a URL is not specified, static fees will be used for estimation."` + AssertFilterHeader string `long:"assertfilterheader" description:"Optional filter header in height:hash format to assert the state of neutrino's filter header chain on startup. If the assertion does not hold, then the filter header chain will be re-synced from the genesis block."` } type btcdConfig struct {