Merge pull request #1839 from cfromknecht/assume-channel-valid
routing: Assume channel valid
This commit is contained in:
commit
309e656a97
8
Makefile
8
Makefile
@ -130,13 +130,13 @@ btcd: $(GLIDE_BIN) $(BTCD_DIR)
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
@$(call print, "Building debug lnd and lncli.")
|
@$(call print, "Building debug lnd and lncli.")
|
||||||
$(GOBUILD) -tags=$(TEST_TAGS) -o lnd-debug $(LDFLAGS) $(PKG)
|
$(GOBUILD) -tags="$(TEST_TAGS) ${tags}" -o lnd-debug $(LDFLAGS) $(PKG)
|
||||||
$(GOBUILD) -tags=$(TEST_TAGS) -o lncli-debug $(LDFLAGS) $(PKG)/cmd/lncli
|
$(GOBUILD) -tags="$(TEST_TAGS) ${tags}" -o lncli-debug $(LDFLAGS) $(PKG)/cmd/lncli
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@$(call print, "Installing lnd and lncli.")
|
@$(call print, "Installing lnd and lncli.")
|
||||||
go install -v $(LDFLAGS) $(PKG)
|
go install -v -tags="${tags}" $(LDFLAGS) $(PKG)
|
||||||
go install -v $(LDFLAGS) $(PKG)/cmd/lncli
|
go install -v -tags="${tags}" $(LDFLAGS) $(PKG)/cmd/lncli
|
||||||
|
|
||||||
scratch: dep build
|
scratch: dep build
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing"
|
||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -234,6 +235,8 @@ type config struct {
|
|||||||
NoChanUpdates bool `long:"nochanupdates" description:"If specified, lnd will not request real-time channel updates from connected peers. This option should be used by routing nodes to save bandwidth."`
|
NoChanUpdates bool `long:"nochanupdates" description:"If specified, lnd will not request real-time channel updates from connected peers. This option should be used by routing nodes to save bandwidth."`
|
||||||
|
|
||||||
net tor.Net
|
net tor.Net
|
||||||
|
|
||||||
|
Routing *routing.Conf `group:"routing" namespace:"routing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadConfig initializes and parses the config using a config file and command
|
// loadConfig initializes and parses the config using a config file and command
|
||||||
@ -692,6 +695,7 @@ func loadConfig() (*config, error) {
|
|||||||
}
|
}
|
||||||
case "neutrino":
|
case "neutrino":
|
||||||
// No need to get RPC parameters.
|
// No need to get RPC parameters.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
str := "%s: only btcd, bitcoind, and neutrino mode " +
|
str := "%s: only btcd, bitcoind, and neutrino mode " +
|
||||||
"supported for bitcoin at this time"
|
"supported for bitcoin at this time"
|
||||||
|
12
routing/conf.go
Normal file
12
routing/conf.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build !experimental
|
||||||
|
|
||||||
|
package routing
|
||||||
|
|
||||||
|
// Conf provides the command line routing configuration. There are no fields in
|
||||||
|
// the production build so that this section is hidden by default.
|
||||||
|
type Conf struct{}
|
||||||
|
|
||||||
|
// UseAssumeChannelValid always returns false when not in experimental builds.
|
||||||
|
func (c *Conf) UseAssumeChannelValid() bool {
|
||||||
|
return false
|
||||||
|
}
|
14
routing/conf_experimental.go
Normal file
14
routing/conf_experimental.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// +build experimental
|
||||||
|
|
||||||
|
package routing
|
||||||
|
|
||||||
|
// Conf exposes the experimental command line routing configurations.
|
||||||
|
type Conf struct {
|
||||||
|
AssumeChannelValid bool `long:"assumechanvalid" description:"Skip checking channel spentness during graph validation. (default: false)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseAssumeChannelValid returns true if the router should skip checking for
|
||||||
|
// spentness when processing channel updates and announcements.
|
||||||
|
func (c *Conf) UseAssumeChannelValid() bool {
|
||||||
|
return c.AssumeChannelValid
|
||||||
|
}
|
@ -177,6 +177,12 @@ type Config struct {
|
|||||||
// date knowledge of the available bandwidth of the link should be
|
// date knowledge of the available bandwidth of the link should be
|
||||||
// returned.
|
// returned.
|
||||||
QueryBandwidth func(edge *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi
|
QueryBandwidth func(edge *channeldb.ChannelEdgeInfo) lnwire.MilliSatoshi
|
||||||
|
|
||||||
|
// AssumeChannelValid toggles whether or not the router will check for
|
||||||
|
// spentness of channel outpoints. For neutrino, this saves long rescans
|
||||||
|
// from blocking initial usage of the wallet. This should only be
|
||||||
|
// enabled on testnet.
|
||||||
|
AssumeChannelValid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// routeTuple is an entry within the ChannelRouter's route cache. We cache
|
// routeTuple is an entry within the ChannelRouter's route cache. We cache
|
||||||
@ -966,7 +972,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// to obtain the full funding outpoint that's encoded within
|
// to obtain the full funding outpoint that's encoded within
|
||||||
// the channel ID.
|
// the channel ID.
|
||||||
channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
||||||
fundingPoint, _, err := r.fetchChanPoint(&channelID)
|
fundingPoint, fundingTxOut, err := r.fetchChanPoint(&channelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.rejectMtx.Lock()
|
r.rejectMtx.Lock()
|
||||||
r.rejectCache[msg.ChannelID] = struct{}{}
|
r.rejectCache[msg.ChannelID] = struct{}{}
|
||||||
@ -990,20 +996,28 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have the funding outpoint of the channel, ensure
|
var chanUtxo *wire.TxOut
|
||||||
// that it hasn't yet been spent. If so, then this channel has
|
if r.cfg.AssumeChannelValid {
|
||||||
// been closed so we'll ignore it.
|
// If AssumeChannelValid is present, we'll just use the
|
||||||
chanUtxo, err := r.cfg.Chain.GetUtxo(
|
// txout returned from fetchChanPoint.
|
||||||
fundingPoint, fundingPkScript, channelID.BlockHeight,
|
chanUtxo = fundingTxOut
|
||||||
|
} else {
|
||||||
|
// Now that we have the funding outpoint of the channel,
|
||||||
|
// ensure that it hasn't yet been spent. If so, then
|
||||||
|
// this channel has been closed so we'll ignore it.
|
||||||
|
chanUtxo, err = r.cfg.Chain.GetUtxo(
|
||||||
|
fundingPoint, fundingPkScript,
|
||||||
|
channelID.BlockHeight,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.rejectMtx.Lock()
|
r.rejectMtx.Lock()
|
||||||
r.rejectCache[msg.ChannelID] = struct{}{}
|
r.rejectCache[msg.ChannelID] = struct{}{}
|
||||||
r.rejectMtx.Unlock()
|
r.rejectMtx.Unlock()
|
||||||
|
|
||||||
return errors.Errorf("unable to fetch utxo for "+
|
return errors.Errorf("unable to fetch utxo "+
|
||||||
"chan_id=%v, chan_point=%v: %v", msg.ChannelID,
|
"for chan_id=%v, chan_point=%v: %v",
|
||||||
fundingPoint, err)
|
msg.ChannelID, fundingPoint, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// By checking the equality of witness pkscripts we checks that
|
// By checking the equality of witness pkscripts we checks that
|
||||||
@ -1108,11 +1122,11 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !exists {
|
if !exists && !r.cfg.AssumeChannelValid {
|
||||||
// Before we can update the channel information, we'll
|
// Before we can update the channel information, we'll
|
||||||
// ensure that the target channel is still open by
|
// ensure that the target channel is still open by
|
||||||
// querying the utxo-set for its existence.
|
// querying the utxo-set for its existence.
|
||||||
chanPoint, fundingPkScript, err := r.fetchChanPoint(
|
chanPoint, fundingTxOut, err := r.fetchChanPoint(
|
||||||
&channelID,
|
&channelID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1125,7 +1139,8 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
msg.ChannelID, err)
|
msg.ChannelID, err)
|
||||||
}
|
}
|
||||||
_, err = r.cfg.Chain.GetUtxo(
|
_, err = r.cfg.Chain.GetUtxo(
|
||||||
chanPoint, fundingPkScript, channelID.BlockHeight,
|
chanPoint, fundingTxOut.PkScript,
|
||||||
|
channelID.BlockHeight,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.rejectMtx.Lock()
|
r.rejectMtx.Lock()
|
||||||
@ -1171,7 +1186,9 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
//
|
//
|
||||||
// TODO(roasbeef): replace with call to GetBlockTransaction? (would allow to
|
// TODO(roasbeef): replace with call to GetBlockTransaction? (would allow to
|
||||||
// later use getblocktxn)
|
// later use getblocktxn)
|
||||||
func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.OutPoint, []byte, error) {
|
func (r *ChannelRouter) fetchChanPoint(
|
||||||
|
chanID *lnwire.ShortChannelID) (*wire.OutPoint, *wire.TxOut, error) {
|
||||||
|
|
||||||
// First fetch the block hash by the block number encoded, then use
|
// First fetch the block hash by the block number encoded, then use
|
||||||
// that hash to fetch the block itself.
|
// that hash to fetch the block itself.
|
||||||
blockNum := int64(chanID.BlockHeight)
|
blockNum := int64(chanID.BlockHeight)
|
||||||
@ -1195,12 +1212,15 @@ func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.Out
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally once we have the block itself, we seek to the targeted
|
// Finally once we have the block itself, we seek to the targeted
|
||||||
// transaction index to obtain the funding output and txid.
|
// transaction index to obtain the funding output and txout.
|
||||||
fundingTx := fundingBlock.Transactions[chanID.TxIndex]
|
fundingTx := fundingBlock.Transactions[chanID.TxIndex]
|
||||||
return &wire.OutPoint{
|
outPoint := &wire.OutPoint{
|
||||||
Hash: fundingTx.TxHash(),
|
Hash: fundingTx.TxHash(),
|
||||||
Index: uint32(chanID.TxPosition),
|
Index: uint32(chanID.TxPosition),
|
||||||
}, fundingTx.TxOut[chanID.TxPosition].PkScript, nil
|
}
|
||||||
|
txOut := fundingTx.TxOut[chanID.TxPosition]
|
||||||
|
|
||||||
|
return outPoint, txOut, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// routingMsg couples a routing related routing topology update to the
|
// routingMsg couples a routing related routing topology update to the
|
||||||
|
@ -549,6 +549,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
// for the available bandwidth for the link.
|
// for the available bandwidth for the link.
|
||||||
return link.Bandwidth()
|
return link.Bandwidth()
|
||||||
},
|
},
|
||||||
|
AssumeChannelValid: cfg.Routing.UseAssumeChannelValid(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't create router: %v", err)
|
return nil, fmt.Errorf("can't create router: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user