routing: ensure advertised transaction index is within bounds

This commit fixes bug that could result in the panicking or crashing of
nodes in the case of an at-funding-time reorganization within the
network. In order to avoid such a case, we now ensure that the
advertised transaction index is within the bounds of the block before
attempting to access it.

Note that this is a temporary patch commit until full advertisement
validation which is implemented in the discovery PR lands in master.
Additionally, better reorg handling during the funding process is being
specified within the spec and will properly be implemented within lnd
at a later date.
This commit is contained in:
Olaoluwa Osuntokun 2017-02-06 14:54:50 -08:00
parent 71bb430836
commit bf78122dc7
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2

@ -3,6 +3,7 @@ package routing
import (
"bytes"
"encoding/hex"
"fmt"
"sync"
"sync/atomic"
"time"
@ -429,7 +430,7 @@ func (r *ChannelRouter) networkHandler() {
newBlock.Hash, blockHeight, numClosed)
// The retransmission timer has ticked which indicates that we
// should broadcast our personal channel sot the network. This
// should broadcast our personal channel to the network. This
// addresses the case of channel advertisements whether being
// dropped, or not properly propagated through the network.
case <-retransmitTimer.C:
@ -714,7 +715,7 @@ func (r *ChannelRouter) processNetworkAnnouncement(msg lnwire.Message) bool {
// the UTXO itself so we can store the proper capacity.
chanPoint, err := r.fetchChanPoint(&msg.ChannelID)
if err != nil {
log.Errorf("unable to fetch chan point: %v", err)
log.Errorf("unable to fetch chan point for chan_id=%v: %v", chanID, err)
return false
}
utxo, err := r.cfg.Chain.GetUtxo(&chanPoint.Hash,
@ -926,9 +927,18 @@ func (r *ChannelRouter) fetchChanPoint(chanID *lnwire.ChannelID) (*wire.OutPoint
return nil, err
}
// TODO(roasbeef): skipping validation here as
// the discovery service should handle full
// validate
// As a sanity check, ensure that the advertised transaction index is
// within the bounds of the total number of transactions within a
// block.
numTxns := uint32(len(fundingBlock.Transactions))
if chanID.TxIndex > numTxns-1 {
return 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))
}
// TODO(roasbeef): skipping validation here as the discovery service
// should handle full validate
// Finally once we have the block itself, we seek to the targeted
// transaction index to obtain the funding output and txid.