Skip to content

Commit

Permalink
chanbackup: encode broadcast height in chan ID for unconfirmed channels
Browse files Browse the repository at this point in the history
  • Loading branch information
guggero committed Nov 26, 2019
1 parent cb2b8b4 commit d4f836e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
15 changes: 14 additions & 1 deletion chanbackup/single.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type Single struct {
// ShortChannelID encodes the exact location in the chain in which the
// channel was initially confirmed. This includes: the block height,
// transaction index, and the output within the target transaction.
// Channels that were not confirmed at the time of backup creation will
// have the funding TX broadcast height set as their block height in
// the ShortChannelID.
ShortChannelID lnwire.ShortChannelID

// RemoteNodePub is the identity public key of the remote node this
Expand Down Expand Up @@ -126,11 +129,21 @@ func NewSingle(channel *channeldb.OpenChannel,
// key.
_, shaChainPoint := btcec.PrivKeyFromBytes(btcec.S256(), b.Bytes())

// If a channel is unconfirmed, the block height of the ShortChannelID
// is zero. This will lead to problems when trying to restore that
// channel as the spend notifier would get a height hint of zero.
// To work around that problem, we add the channel broadcast height
// to the channel ID so we can use that as height hint on restore.
chanID := channel.ShortChanID()
if chanID.BlockHeight == 0 {
chanID.BlockHeight = channel.FundingBroadcastHeight
}

single := Single{
IsInitiator: channel.IsInitiator,
ChainHash: channel.ChainHash,
FundingOutpoint: channel.FundingOutpoint,
ShortChannelID: channel.ShortChannelID,
ShortChannelID: chanID,
RemoteNodePub: channel.IdentityPub,
Addresses: nodeAddrs,
Capacity: channel.Capacity,
Expand Down
40 changes: 40 additions & 0 deletions chanbackup/single_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,44 @@ func TestSinglePackStaticChanBackups(t *testing.T) {
}
}

// TestSingleUnconfirmedChannel tests that unconfirmed channels get serialized
// correctly by encoding the funding broadcast height as block height of the
// short channel ID.
func TestSingleUnconfirmedChannel(t *testing.T) {
t.Parallel()

var fundingBroadcastHeight = uint32(1234)

// Let's create an open channel shell that contains all the information
// we need to create a static channel backup but simulate an
// unconfirmed channel by setting the block height to 0.
channel, err := genRandomOpenChannelShell()
if err != nil {
t.Fatalf("unable to gen open channel: %v", err)
}
channel.ShortChannelID.BlockHeight = 0
channel.FundingBroadcastHeight = fundingBroadcastHeight

singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2})
keyRing := &mockKeyRing{}

// Pack it and then unpack it again to make sure everything is written
// correctly, then check that the block height of the unpacked
// is the funding broadcast height we set before.
var b bytes.Buffer
if err := singleChanBackup.PackToWriter(&b, keyRing); err != nil {
t.Fatalf("unable to pack single: %v", err)
}
var unpackedSingle Single
err = unpackedSingle.UnpackFromReader(&b, keyRing)
if err != nil {
t.Fatalf("unable to unpack single: %v", err)
}
if unpackedSingle.ShortChannelID.BlockHeight != fundingBroadcastHeight {
t.Fatalf("invalid block height. got %d expected %d.",
unpackedSingle.ShortChannelID.BlockHeight,
fundingBroadcastHeight)
}
}

// TODO(roasbsef): fuzz parsing

0 comments on commit d4f836e

Please sign in to comment.