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"
|
||||
|
||||
"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/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"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 (
|
||||
@ -176,7 +176,7 @@ func (m *mockChain) addUtxo(op wire.OutPoint, out *wire.TxOut) {
|
||||
m.utxos[op] = *out
|
||||
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()
|
||||
defer m.RUnlock()
|
||||
|
||||
@ -242,12 +242,12 @@ func (m *mockChainView) Reset() {
|
||||
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()
|
||||
defer m.Unlock()
|
||||
|
||||
for _, op := range ops {
|
||||
m.filter[op] = struct{}{}
|
||||
m.filter[op.OutPoint] = struct{}{}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -967,7 +967,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
// to obtain the full funding outpoint that's encoded within
|
||||
// the channel ID.
|
||||
channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
||||
fundingPoint, err := r.fetchChanPoint(&channelID)
|
||||
fundingPoint, _, err := r.fetchChanPoint(&channelID)
|
||||
if err != nil {
|
||||
r.rejectMtx.Lock()
|
||||
r.rejectCache[msg.ChannelID] = struct{}{}
|
||||
@ -977,11 +977,25 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
"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
|
||||
// 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, channelID.BlockHeight,
|
||||
fundingPoint, fundingPkScript, channelID.BlockHeight,
|
||||
)
|
||||
if err != nil {
|
||||
r.rejectMtx.Lock()
|
||||
@ -993,26 +1007,14 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
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
|
||||
// funding witness script is multisignature lock which contains
|
||||
// both local and remote public keys which was declared in
|
||||
// channel edge and also that the announced channel value is
|
||||
// right.
|
||||
if !bytes.Equal(witnessOutput.PkScript, chanUtxo.PkScript) {
|
||||
if !bytes.Equal(fundingPkScript, chanUtxo.PkScript) {
|
||||
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
|
||||
@ -1034,7 +1036,12 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
// update the current UTXO filter within our active
|
||||
// FilteredChainView so we are notified if/when this channel is
|
||||
// closed.
|
||||
filterUpdate := []wire.OutPoint{*fundingPoint}
|
||||
filterUpdate := []channeldb.EdgePoint{
|
||||
{
|
||||
FundingPkScript: fundingPkScript,
|
||||
OutPoint: *fundingPoint,
|
||||
},
|
||||
}
|
||||
err = r.cfg.ChainView.UpdateFilter(
|
||||
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
|
||||
// ensure that the target channel is still open by
|
||||
// querying the utxo-set for its existence.
|
||||
chanPoint, err := r.fetchChanPoint(&channelID)
|
||||
chanPoint, fundingPkScript, err := r.fetchChanPoint(
|
||||
&channelID,
|
||||
)
|
||||
if err != nil {
|
||||
r.rejectMtx.Lock()
|
||||
r.rejectCache[msg.ChannelID] = struct{}{}
|
||||
@ -1116,7 +1125,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
msg.ChannelID, err)
|
||||
}
|
||||
_, err = r.cfg.Chain.GetUtxo(
|
||||
chanPoint, channelID.BlockHeight,
|
||||
chanPoint, fundingPkScript, channelID.BlockHeight,
|
||||
)
|
||||
if err != nil {
|
||||
r.rejectMtx.Lock()
|
||||
@ -1157,21 +1166,22 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// that hash to fetch the block itself.
|
||||
blockNum := int64(chanID.BlockHeight)
|
||||
blockHash, err := r.cfg.Chain.GetBlockHash(blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
fundingBlock, err := r.cfg.Chain.GetBlock(blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// 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.
|
||||
numTxns := uint32(len(fundingBlock.Transactions))
|
||||
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,
|
||||
numTxns-1, spew.Sdump(chanID))
|
||||
}
|
||||
@ -1190,7 +1200,7 @@ func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ShortChannelID) (*wire.Out
|
||||
return &wire.OutPoint{
|
||||
Hash: fundingTx.TxHash(),
|
||||
Index: uint32(chanID.TxPosition),
|
||||
}, nil
|
||||
}, fundingTx.TxOut[chanID.TxPosition].PkScript, nil
|
||||
}
|
||||
|
||||
// routingMsg couples a routing related routing topology update to the
|
||||
|
Loading…
Reference in New Issue
Block a user