From 4d03f60e405e78be0beac4e7f5705e1b96d986bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20J=C3=A4mthagen?= Date: Fri, 20 Jan 2017 11:51:48 +0100 Subject: [PATCH] lnwallet: handle duplicate payment hashes in toChannelDelta() --- lnwallet/channel.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index b5d25dd9..ed72ee0c 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -230,6 +230,10 @@ type commitment struct { // TODO(roasbeef): properly fill in refund timeouts func (c *commitment) toChannelDelta() (*channeldb.ChannelDelta, error) { numHtlcs := len(c.outgoingHTLCs) + len(c.incomingHTLCs) + + // Save output indexes for RHash values found, so we don't return the + // same output index more than once. + dups := make(map[PaymentHash][]uint16) delta := &channeldb.ChannelDelta{ LocalBalance: c.ourBalance, RemoteBalance: c.theirBalance, @@ -237,6 +241,16 @@ func (c *commitment) toChannelDelta() (*channeldb.ChannelDelta, error) { Htlcs: make([]*channeldb.HTLC, 0, numHtlcs), } + // Check to see if element (e) exists in slice (s) + contains := func(s []uint16, e uint16) bool { + for _, a := range s { + if a == e { + return true + } + } + return false + } + // As we also store the output index of the HTLC for continence // purposes, we create a small helper function to locate the output // index of a particular HTLC within the current commitment @@ -244,9 +258,13 @@ func (c *commitment) toChannelDelta() (*channeldb.ChannelDelta, error) { locateOutputIndex := func(p *PaymentDescriptor) uint16 { var idx uint16 for i, txOut := range c.txn.TxOut { - // TODO(roasbeef): duplicated payment hashes... if bytes.Equal(txOut.PkScript, p.pkScript) { + if contains(dups[p.RHash], uint16(i)) { + continue + } + idx = uint16(i) + dups[p.RHash] = append(dups[p.RHash], idx) break } }