routing: update UTXO verification to use new interface, graph pruning too
This commit is contained in:
parent
fb98f59407
commit
8c0a151cec
@ -10,15 +10,15 @@ import (
|
|||||||
|
|
||||||
prand "math/rand"
|
prand "math/rand"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||||
"github.com/btcsuite/btcd/btcec"
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
|
||||||
"github.com/btcsuite/btcutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -176,7 +176,7 @@ func (m *mockChain) addUtxo(op wire.OutPoint, out *wire.TxOut) {
|
|||||||
m.utxos[op] = *out
|
m.utxos[op] = *out
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
}
|
}
|
||||||
func (m *mockChain) GetUtxo(op *wire.OutPoint, _ uint32) (*wire.TxOut, error) {
|
func (m *mockChain) GetUtxo(op *wire.OutPoint, _ []byte, _ uint32) (*wire.TxOut, error) {
|
||||||
m.RLock()
|
m.RLock()
|
||||||
defer m.RUnlock()
|
defer m.RUnlock()
|
||||||
|
|
||||||
@ -242,12 +242,12 @@ func (m *mockChainView) Reset() {
|
|||||||
m.staleBlocks = make(chan *chainview.FilteredBlock, 10)
|
m.staleBlocks = make(chan *chainview.FilteredBlock, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockChainView) UpdateFilter(ops []wire.OutPoint, updateHeight uint32) error {
|
func (m *mockChainView) UpdateFilter(ops []channeldb.EdgePoint, updateHeight uint32) error {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, op := range ops {
|
||||||
m.filter[op] = struct{}{}
|
m.filter[op.OutPoint] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -967,7 +967,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, _, 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{}{}
|
||||||
@ -977,11 +977,25 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
"chan_id=%v: %v", msg.ChannelID, err)
|
"chan_id=%v: %v", msg.ChannelID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recreate witness output to be sure that declared in channel
|
||||||
|
// edge bitcoin keys and channel value corresponds to the
|
||||||
|
// reality.
|
||||||
|
witnessScript, err := lnwallet.GenMultiSigScript(
|
||||||
|
msg.BitcoinKey1Bytes[:], msg.BitcoinKey2Bytes[:],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fundingPkScript, err := lnwallet.WitnessScriptHash(witnessScript)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we have the funding outpoint of the channel, ensure
|
// Now that we have the funding outpoint of the channel, ensure
|
||||||
// that it hasn't yet been spent. If so, then this channel has
|
// that it hasn't yet been spent. If so, then this channel has
|
||||||
// been closed so we'll ignore it.
|
// been closed so we'll ignore it.
|
||||||
chanUtxo, err := r.cfg.Chain.GetUtxo(
|
chanUtxo, err := r.cfg.Chain.GetUtxo(
|
||||||
fundingPoint, channelID.BlockHeight,
|
fundingPoint, fundingPkScript, channelID.BlockHeight,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.rejectMtx.Lock()
|
r.rejectMtx.Lock()
|
||||||
@ -993,26 +1007,14 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
fundingPoint, err)
|
fundingPoint, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recreate witness output to be sure that declared in channel
|
|
||||||
// edge bitcoin keys and channel value corresponds to the
|
|
||||||
// reality.
|
|
||||||
_, witnessOutput, err := lnwallet.GenFundingPkScript(
|
|
||||||
msg.BitcoinKey1Bytes[:], msg.BitcoinKey2Bytes[:],
|
|
||||||
chanUtxo.Value,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Errorf("unable to create funding pk "+
|
|
||||||
"script: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// By checking the equality of witness pkscripts we checks that
|
// By checking the equality of witness pkscripts we checks that
|
||||||
// funding witness script is multisignature lock which contains
|
// funding witness script is multisignature lock which contains
|
||||||
// both local and remote public keys which was declared in
|
// both local and remote public keys which was declared in
|
||||||
// channel edge and also that the announced channel value is
|
// channel edge and also that the announced channel value is
|
||||||
// right.
|
// right.
|
||||||
if !bytes.Equal(witnessOutput.PkScript, chanUtxo.PkScript) {
|
if !bytes.Equal(fundingPkScript, chanUtxo.PkScript) {
|
||||||
return errors.Errorf("pkScript mismatch: expected %x, "+
|
return errors.Errorf("pkScript mismatch: expected %x, "+
|
||||||
"got %x", witnessOutput.PkScript, chanUtxo.PkScript)
|
"got %x", fundingPkScript, chanUtxo.PkScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): this is a hack, needs to be removed
|
// TODO(roasbeef): this is a hack, needs to be removed
|
||||||
@ -1034,7 +1036,12 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// update the current UTXO filter within our active
|
// update the current UTXO filter within our active
|
||||||
// FilteredChainView so we are notified if/when this channel is
|
// FilteredChainView so we are notified if/when this channel is
|
||||||
// closed.
|
// closed.
|
||||||
filterUpdate := []wire.OutPoint{*fundingPoint}
|
filterUpdate := []channeldb.EdgePoint{
|
||||||
|
{
|
||||||
|
FundingPkScript: fundingPkScript,
|
||||||
|
OutPoint: *fundingPoint,
|
||||||
|
},
|
||||||
|
}
|
||||||
err = r.cfg.ChainView.UpdateFilter(
|
err = r.cfg.ChainView.UpdateFilter(
|
||||||
filterUpdate, atomic.LoadUint32(&r.bestHeight),
|
filterUpdate, atomic.LoadUint32(&r.bestHeight),
|
||||||
)
|
)
|
||||||
@ -1105,7 +1112,9 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// 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, err := r.fetchChanPoint(&channelID)
|
chanPoint, fundingPkScript, 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{}{}
|
||||||
@ -1116,7 +1125,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
msg.ChannelID, err)
|
msg.ChannelID, err)
|
||||||
}
|
}
|
||||||
_, err = r.cfg.Chain.GetUtxo(
|
_, err = r.cfg.Chain.GetUtxo(
|
||||||
chanPoint, channelID.BlockHeight,
|
chanPoint, fundingPkScript, channelID.BlockHeight,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.rejectMtx.Lock()
|
r.rejectMtx.Lock()
|
||||||
@ -1157,21 +1166,22 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fetchChanPoint retrieves the original outpoint which is encoded within the
|
// fetchChanPoint retrieves the original outpoint which is encoded within the
|
||||||
// channelID.
|
// channelID. This method also return the public key script for the target
|
||||||
|
// transaction.
|
||||||
//
|
//
|
||||||
// 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, error) {
|
func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.OutPoint, []byte, 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)
|
||||||
blockHash, err := r.cfg.Chain.GetBlockHash(blockNum)
|
blockHash, err := r.cfg.Chain.GetBlockHash(blockNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
fundingBlock, err := r.cfg.Chain.GetBlock(blockHash)
|
fundingBlock, err := r.cfg.Chain.GetBlock(blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// As a sanity check, ensure that the advertised transaction index is
|
// As a sanity check, ensure that the advertised transaction index is
|
||||||
@ -1179,7 +1189,7 @@ func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.Out
|
|||||||
// block.
|
// block.
|
||||||
numTxns := uint32(len(fundingBlock.Transactions))
|
numTxns := uint32(len(fundingBlock.Transactions))
|
||||||
if chanID.TxIndex > numTxns-1 {
|
if chanID.TxIndex > numTxns-1 {
|
||||||
return nil, fmt.Errorf("tx_index=#%v is out of range "+
|
return nil, nil, fmt.Errorf("tx_index=#%v is out of range "+
|
||||||
"(max_index=%v), network_chan_id=%v\n", chanID.TxIndex,
|
"(max_index=%v), network_chan_id=%v\n", chanID.TxIndex,
|
||||||
numTxns-1, spew.Sdump(chanID))
|
numTxns-1, spew.Sdump(chanID))
|
||||||
}
|
}
|
||||||
@ -1190,7 +1200,7 @@ func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.Out
|
|||||||
return &wire.OutPoint{
|
return &wire.OutPoint{
|
||||||
Hash: fundingTx.TxHash(),
|
Hash: fundingTx.TxHash(),
|
||||||
Index: uint32(chanID.TxPosition),
|
Index: uint32(chanID.TxPosition),
|
||||||
}, nil
|
}, fundingTx.TxOut[chanID.TxPosition].PkScript, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// routingMsg couples a routing related routing topology update to the
|
// routingMsg couples a routing related routing topology update to the
|
||||||
|
Loading…
Reference in New Issue
Block a user