htlcswitch: keep final htlc outcome
This commit is contained in:
20 files changed
+466
-111
No files matched your search
+163
-9
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/btcsuite/btcwallet/walletdb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
@@ -135,6 +136,26 @@ var (
|
|||||||
// sent was a revocation and false when it was a commitment signature.
|
// sent was a revocation and false when it was a commitment signature.
|
||||||
// This is nil in the case of new channels with no updates exchanged.
|
// This is nil in the case of new channels with no updates exchanged.
|
||||||
lastWasRevokeKey = []byte("last-was-revoke")
|
lastWasRevokeKey = []byte("last-was-revoke")
|
||||||
|
|
||||||
|
// finalHtlcsBucket contains the htlcs that have been resolved
|
||||||
|
// definitively. Within this bucket, there is a sub-bucket for each
|
||||||
|
// channel. In each channel bucket, the htlc indices are stored along
|
||||||
|
// with final outcome.
|
||||||
|
//
|
||||||
|
// final-htlcs -> chanID -> htlcIndex -> outcome
|
||||||
|
//
|
||||||
|
// 'outcome' is a byte value that encodes:
|
||||||
|
//
|
||||||
|
// | true false
|
||||||
|
// ------+------------------
|
||||||
|
// bit 0 | settled failed
|
||||||
|
// bit 1 | offchain onchain
|
||||||
|
//
|
||||||
|
// This bucket is positioned at the root level, because its contents
|
||||||
|
// will be kept independent of the channel lifecycle. This is to avoid
|
||||||
|
// the situation where a channel force-closes autonomously and the user
|
||||||
|
// not being able to query for htlc outcomes anymore.
|
||||||
|
finalHtlcsBucket = []byte("final-htlcs")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -618,6 +639,20 @@ func (c ChannelStatus) String() string {
|
|||||||
return statusStr
|
return statusStr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FinalHtlcByte defines a byte type that encodes information about the final
|
||||||
|
// htlc resolution.
|
||||||
|
type FinalHtlcByte byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FinalHtlcSettledBit is the bit that encodes whether the htlc was
|
||||||
|
// settled or failed.
|
||||||
|
FinalHtlcSettledBit FinalHtlcByte = 1 << 0
|
||||||
|
|
||||||
|
// FinalHtlcOffchainBit is the bit that encodes whether the htlc was
|
||||||
|
// resolved offchain or onchain.
|
||||||
|
FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
|
||||||
|
)
|
||||||
|
|
||||||
// OpenChannel encapsulates the persistent and dynamic state of an open channel
|
// OpenChannel encapsulates the persistent and dynamic state of an open channel
|
||||||
// with a remote node. An open channel supports several options for on-disk
|
// with a remote node. An open channel supports several options for on-disk
|
||||||
// serialization depending on the exact context. Full (upon channel creation)
|
// serialization depending on the exact context. Full (upon channel creation)
|
||||||
@@ -1043,6 +1078,26 @@ func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
|
|||||||
return chanBucket, nil
|
return chanBucket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
|
||||||
|
chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
|
||||||
|
|
||||||
|
finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var chanIDBytes [8]byte
|
||||||
|
byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
|
||||||
|
chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
|
||||||
|
chanIDBytes[:],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return chanBucket, nil
|
||||||
|
}
|
||||||
|
|
||||||
// fullSync syncs the contents of an OpenChannel while re-using an existing
|
// fullSync syncs the contents of an OpenChannel while re-using an existing
|
||||||
// database transaction.
|
// database transaction.
|
||||||
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
|
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
|
||||||
@@ -1739,8 +1794,12 @@ func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
|
|||||||
// persisted to be able to produce a valid commit signature if a restart would
|
// persisted to be able to produce a valid commit signature if a restart would
|
||||||
// occur. This method its to be called when we revoke our prior commitment
|
// occur. This method its to be called when we revoke our prior commitment
|
||||||
// state.
|
// state.
|
||||||
|
//
|
||||||
|
// A map is returned of all the htlc resolutions that were locked in in this
|
||||||
|
// commitment. Keys correspond to htlc indices and values indicate whether the
|
||||||
|
// htlc was settled or failed.
|
||||||
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
||||||
unsignedAckedUpdates []LogUpdate) error {
|
unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
|
||||||
|
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
@@ -1749,9 +1808,11 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
|||||||
// state as all, as it's impossible to do so in a protocol compliant
|
// state as all, as it's impossible to do so in a protocol compliant
|
||||||
// manner.
|
// manner.
|
||||||
if c.hasChanStatus(ChanStatusRestored) {
|
if c.hasChanStatus(ChanStatusRestored) {
|
||||||
return ErrNoRestoredChannelMutation
|
return nil, ErrNoRestoredChannelMutation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var finalHtlcs = make(map[uint64]bool)
|
||||||
|
|
||||||
err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
|
err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
|
||||||
chanBucket, err := fetchChanBucketRw(
|
chanBucket, err := fetchChanBucketRw(
|
||||||
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
|
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
|
||||||
@@ -1822,17 +1883,35 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var validUpdates []LogUpdate
|
// Get the bucket where settled htlcs are recorded.
|
||||||
|
finalHtlcsBucket, err := fetchFinalHtlcsBucketRw(
|
||||||
|
tx, c.ShortChannelID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var unsignedUpdates []LogUpdate
|
||||||
for _, upd := range updates {
|
for _, upd := range updates {
|
||||||
// Filter for updates that are not on our local
|
// Gather updates that are not on our local commitment.
|
||||||
// commitment.
|
|
||||||
if upd.LogIndex >= newCommitment.LocalLogIndex {
|
if upd.LogIndex >= newCommitment.LocalLogIndex {
|
||||||
validUpdates = append(validUpdates, upd)
|
unsignedUpdates = append(unsignedUpdates, upd)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// The update was locked in. If the update was a
|
||||||
|
// resolution, then store it in the database.
|
||||||
|
err := processFinalHtlc(
|
||||||
|
finalHtlcsBucket, upd, finalHtlcs,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var b3 bytes.Buffer
|
var b3 bytes.Buffer
|
||||||
err = serializeLogUpdates(&b3, validUpdates)
|
err = serializeLogUpdates(&b3, unsignedUpdates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to serialize log updates: %v", err)
|
return fmt.Errorf("unable to serialize log updates: %v", err)
|
||||||
}
|
}
|
||||||
@@ -1843,12 +1922,57 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, func() {})
|
}, func() {
|
||||||
|
finalHtlcs = make(map[uint64]bool)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.LocalCommitment = *newCommitment
|
||||||
|
|
||||||
|
return finalHtlcs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// processFinalHtlc stores a final htlc outcome in the database if signaled via
|
||||||
|
// the supplied log update. An in-memory htlcs map is updated too.
|
||||||
|
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
|
||||||
|
finalHtlcs map[uint64]bool) error {
|
||||||
|
|
||||||
|
var (
|
||||||
|
settled bool
|
||||||
|
id uint64
|
||||||
|
)
|
||||||
|
|
||||||
|
switch msg := upd.UpdateMsg.(type) {
|
||||||
|
case *lnwire.UpdateFulfillHTLC:
|
||||||
|
settled = true
|
||||||
|
id = msg.ID
|
||||||
|
|
||||||
|
case *lnwire.UpdateFailHTLC:
|
||||||
|
settled = false
|
||||||
|
id = msg.ID
|
||||||
|
|
||||||
|
case *lnwire.UpdateFailMalformedHTLC:
|
||||||
|
settled = false
|
||||||
|
id = msg.ID
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := putFinalHtlc(
|
||||||
|
finalHtlcsBucket, id,
|
||||||
|
FinalHtlcInfo{
|
||||||
|
Settled: settled,
|
||||||
|
Offchain: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.LocalCommitment = *newCommitment
|
finalHtlcs[id] = settled
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -2681,6 +2805,36 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FinalHtlcInfo contains information about the final outcome of an htlc.
|
||||||
|
type FinalHtlcInfo struct {
|
||||||
|
// Settled is true is the htlc was settled. If false, the htlc was
|
||||||
|
// failed.
|
||||||
|
Settled bool
|
||||||
|
|
||||||
|
// Offchain indicates whether the htlc was resolved off-chain or
|
||||||
|
// on-chain.
|
||||||
|
Offchain bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
|
||||||
|
// records whether the htlc was resolved off-chain or on-chain.
|
||||||
|
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
|
||||||
|
info FinalHtlcInfo) error {
|
||||||
|
|
||||||
|
var key [8]byte
|
||||||
|
byteOrder.PutUint64(key[:], id)
|
||||||
|
|
||||||
|
var finalHtlcByte FinalHtlcByte
|
||||||
|
if info.Settled {
|
||||||
|
finalHtlcByte |= FinalHtlcSettledBit
|
||||||
|
}
|
||||||
|
if info.Offchain {
|
||||||
|
finalHtlcByte |= FinalHtlcOffchainBit
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
|
||||||
|
}
|
||||||
|
|
||||||
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
|
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
|
||||||
// this always returns the next index that has been not been allocated, this
|
// this always returns the next index that has been not been allocated, this
|
||||||
// will first try to examine any pending commitments, before falling back to the
|
// will first try to examine any pending commitments, before falling back to the
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ func TestChannelStateTransition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = channel.UpdateCommitment(&commitment, unsignedAckedUpdates)
|
_, err = channel.UpdateCommitment(&commitment, unsignedAckedUpdates)
|
||||||
require.NoError(t, err, "unable to update commitment")
|
require.NoError(t, err, "unable to update commitment")
|
||||||
|
|
||||||
// Assert that update is correctly written to the database.
|
// Assert that update is correctly written to the database.
|
||||||
@@ -1457,3 +1457,41 @@ func TestKeyLocatorEncoding(t *testing.T) {
|
|||||||
// version are equal.
|
// version are equal.
|
||||||
require.Equal(t, keyLoc, decodedKeyLoc)
|
require.Equal(t, keyLoc, decodedKeyLoc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFinalHtlcs tests final htlc storage and retrieval.
|
||||||
|
func TestFinalHtlcs(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
fullDB, err := MakeTestDB(t)
|
||||||
|
require.NoError(t, err, "unable to make test database")
|
||||||
|
|
||||||
|
cdb := fullDB.ChannelStateDB()
|
||||||
|
|
||||||
|
chanID := lnwire.ShortChannelID{
|
||||||
|
BlockHeight: 1,
|
||||||
|
TxIndex: 2,
|
||||||
|
TxPosition: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test offchain final htlcs.
|
||||||
|
const offchainHtlcID = 1
|
||||||
|
|
||||||
|
err = kvdb.Update(cdb.backend, func(tx kvdb.RwTx) error {
|
||||||
|
bucket, err := fetchFinalHtlcsBucketRw(
|
||||||
|
tx, chanID,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return putFinalHtlc(bucket, offchainHtlcID, FinalHtlcInfo{
|
||||||
|
Settled: true,
|
||||||
|
Offchain: true,
|
||||||
|
})
|
||||||
|
}, func() {})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Test onchain final htlcs.
|
||||||
|
const onchainHtlcID = 2
|
||||||
|
|
||||||
|
err = cdb.PutOnchainFinalHtlcOutcome(chanID, onchainHtlcID, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
@@ -1652,6 +1652,27 @@ func (c *ChannelStateDB) FetchHistoricalChannel(outPoint *wire.OutPoint) (
|
|||||||
return channel, nil
|
return channel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutOnchainFinalHtlcOutcome stores the final on-chain outcome of an htlc in
|
||||||
|
// the database.
|
||||||
|
func (c *ChannelStateDB) PutOnchainFinalHtlcOutcome(
|
||||||
|
chanID lnwire.ShortChannelID, htlcID uint64, settled bool) error {
|
||||||
|
|
||||||
|
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||||
|
finalHtlcsBucket, err := fetchFinalHtlcsBucketRw(tx, chanID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return putFinalHtlc(
|
||||||
|
finalHtlcsBucket, htlcID,
|
||||||
|
FinalHtlcInfo{
|
||||||
|
Settled: settled,
|
||||||
|
Offchain: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}, func() {})
|
||||||
|
}
|
||||||
|
|
||||||
// MakeTestDB creates a new instance of the ChannelDB for testing purposes.
|
// MakeTestDB creates a new instance of the ChannelDB for testing purposes.
|
||||||
// A callback which cleans up the created temporary directories is also
|
// A callback which cleans up the created temporary directories is also
|
||||||
// returned and intended to be executed after the test completes.
|
// returned and intended to be executed after the test completes.
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ func TestRestoreChannelShells(t *testing.T) {
|
|||||||
// Ensure that it isn't possible to modify the commitment state machine
|
// Ensure that it isn't possible to modify the commitment state machine
|
||||||
// of this restored channel.
|
// of this restored channel.
|
||||||
channel := nodeChans[0]
|
channel := nodeChans[0]
|
||||||
err = channel.UpdateCommitment(nil, nil)
|
_, err = channel.UpdateCommitment(nil, nil)
|
||||||
if err != ErrNoRestoredChannelMutation {
|
if err != ErrNoRestoredChannelMutation {
|
||||||
t.Fatalf("able to mutate restored channel")
|
t.Fatalf("able to mutate restored channel")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2451,7 +2451,7 @@ func forceStateTransition(chanA, chanB *lnwallet.LightningChannel) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bobRevocation, _, err := chanB.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -2468,7 +2468,7 @@ func forceStateTransition(chanA, chanB *lnwallet.LightningChannel) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceRevocation, _, err := chanA.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,11 @@ type ChainArbitratorConfig struct {
|
|||||||
// complete.
|
// complete.
|
||||||
SubscribeBreachComplete func(op *wire.OutPoint, c chan struct{}) (
|
SubscribeBreachComplete func(op *wire.OutPoint, c chan struct{}) (
|
||||||
bool, error)
|
bool, error)
|
||||||
|
|
||||||
|
// PutFinalHtlcOutcome stores the final outcome of an htlc in the
|
||||||
|
// database.
|
||||||
|
PutFinalHtlcOutcome func(chanId lnwire.ShortChannelID,
|
||||||
|
htlcId uint64, settled bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
|
// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
|
||||||
|
|||||||
@@ -1460,6 +1460,10 @@ const (
|
|||||||
// other party time it out, or eventually learn of the pre-image, in
|
// other party time it out, or eventually learn of the pre-image, in
|
||||||
// which case we'll claim on chain.
|
// which case we'll claim on chain.
|
||||||
HtlcIncomingWatchAction = 5
|
HtlcIncomingWatchAction = 5
|
||||||
|
|
||||||
|
// HtlcIncomingDustFinalAction indicates that we should mark an incoming
|
||||||
|
// dust htlc as final because it can't be claimed on-chain.
|
||||||
|
HtlcIncomingDustFinalAction = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns a human readable string describing a chain action.
|
// String returns a human readable string describing a chain action.
|
||||||
@@ -1483,6 +1487,9 @@ func (c ChainAction) String() string {
|
|||||||
case HtlcIncomingWatchAction:
|
case HtlcIncomingWatchAction:
|
||||||
return "HtlcIncomingWatchAction"
|
return "HtlcIncomingWatchAction"
|
||||||
|
|
||||||
|
case HtlcIncomingDustFinalAction:
|
||||||
|
return "HtlcIncomingDustFinalAction"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "<unknown action>"
|
return "<unknown action>"
|
||||||
}
|
}
|
||||||
@@ -1698,6 +1705,10 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32,
|
|||||||
"needed for incoming dust htlc=%x",
|
"needed for incoming dust htlc=%x",
|
||||||
c.cfg.ChanPoint, htlc.RHash[:])
|
c.cfg.ChanPoint, htlc.RHash[:])
|
||||||
|
|
||||||
|
actionMap[HtlcIncomingDustFinalAction] = append(
|
||||||
|
actionMap[HtlcIncomingDustFinalAction], htlc,
|
||||||
|
)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2213,6 +2224,27 @@ func (c *ChannelArbitrator) prepContractResolutions(
|
|||||||
htlcResolvers = append(htlcResolvers, resolver)
|
htlcResolvers = append(htlcResolvers, resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We've lost an htlc because it isn't manifested on the
|
||||||
|
// commitment transaction that closed the channel.
|
||||||
|
case HtlcIncomingDustFinalAction:
|
||||||
|
for _, htlc := range htlcs {
|
||||||
|
htlc := htlc
|
||||||
|
|
||||||
|
key := channeldb.CircuitKey{
|
||||||
|
ChanID: c.cfg.ShortChanID,
|
||||||
|
HtlcID: htlc.HtlcIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark this dust htlc as final failed.
|
||||||
|
chainArbCfg := c.cfg.ChainArbitratorConfig
|
||||||
|
err := chainArbCfg.PutFinalHtlcOutcome(
|
||||||
|
key.ChanID, key.HtlcID, false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, if this is an outgoing HTLC we've sent, then we'll
|
// Finally, if this is an outgoing HTLC we've sent, then we'll
|
||||||
// launch a resolver to watch for the pre-image (and settle
|
// launch a resolver to watch for the pre-image (and settle
|
||||||
// backwards), or just timeout.
|
// backwards), or just timeout.
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ type chanArbTestCtx struct {
|
|||||||
|
|
||||||
breachSubscribed chan struct{}
|
breachSubscribed chan struct{}
|
||||||
breachResolutionChan chan struct{}
|
breachResolutionChan chan struct{}
|
||||||
|
|
||||||
|
finalHtlcs map[uint64]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *chanArbTestCtx) CleanUp() {
|
func (c *chanArbTestCtx) CleanUp() {
|
||||||
@@ -306,6 +308,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
|
|||||||
|
|
||||||
chanArbCtx := &chanArbTestCtx{
|
chanArbCtx := &chanArbTestCtx{
|
||||||
breachSubscribed: make(chan struct{}),
|
breachSubscribed: make(chan struct{}),
|
||||||
|
finalHtlcs: make(map[uint64]bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
chanPoint := wire.OutPoint{}
|
chanPoint := wire.OutPoint{}
|
||||||
@@ -360,6 +363,13 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
|
|||||||
},
|
},
|
||||||
Clock: clock.NewDefaultClock(),
|
Clock: clock.NewDefaultClock(),
|
||||||
Sweeper: mockSweeper,
|
Sweeper: mockSweeper,
|
||||||
|
PutFinalHtlcOutcome: func(chanId lnwire.ShortChannelID,
|
||||||
|
htlcId uint64, settled bool) error {
|
||||||
|
|
||||||
|
chanArbCtx.finalHtlcs[htlcId] = settled
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll use the resolvedChan to synchronize on call to
|
// We'll use the resolvedChan to synchronize on call to
|
||||||
@@ -966,6 +976,12 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) {
|
|||||||
t.Fatalf("unable to stop chan arb: %v", err)
|
t.Fatalf("unable to stop chan arb: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that a final resolution was stored for the incoming dust htlc.
|
||||||
|
expectedFinalHtlcs := map[uint64]bool{
|
||||||
|
incomingDustHtlc.HtlcIndex: false,
|
||||||
|
}
|
||||||
|
require.Equal(t, expectedFinalHtlcs, chanArbCtx.finalHtlcs)
|
||||||
|
|
||||||
// We'll no re-create the resolver, notice that we use the existing
|
// We'll no re-create the resolver, notice that we use the existing
|
||||||
// arbLog so it carries over the same on-disk state.
|
// arbLog so it carries over the same on-disk state.
|
||||||
chanArbCtxNew, err := chanArbCtx.Restart(nil)
|
chanArbCtxNew, err := chanArbCtx.Restart(nil)
|
||||||
|
|||||||
@@ -50,6 +50,18 @@ func newIncomingContestResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *htlcIncomingContestResolver) processFinalHtlcFail() error {
|
||||||
|
// Mark the htlc as final failed.
|
||||||
|
err := h.ChainArbitratorConfig.PutFinalHtlcOutcome(
|
||||||
|
h.ChannelArbitratorConfig.ShortChanID, h.htlc.HtlcIndex, false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve attempts to resolve this contract. As we don't yet know of the
|
// Resolve attempts to resolve this contract. As we don't yet know of the
|
||||||
// preimage for the contract, we'll wait for one of two things to happen:
|
// preimage for the contract, we'll wait for one of two things to happen:
|
||||||
//
|
//
|
||||||
@@ -83,6 +95,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
// link has ran.
|
// link has ran.
|
||||||
h.resolved = true
|
h.resolved = true
|
||||||
|
|
||||||
|
if err := h.processFinalHtlcFail(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// We write a report to disk that indicates we could not decode
|
// We write a report to disk that indicates we could not decode
|
||||||
// the htlc.
|
// the htlc.
|
||||||
resReport := h.report().resolverReport(
|
resReport := h.report().resolverReport(
|
||||||
@@ -129,6 +145,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
h.htlcExpiry, currentHeight)
|
h.htlcExpiry, currentHeight)
|
||||||
h.resolved = true
|
h.resolved = true
|
||||||
|
|
||||||
|
if err := h.processFinalHtlcFail(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, get our report and checkpoint our resolver with a
|
// Finally, get our report and checkpoint our resolver with a
|
||||||
// timeout outcome report.
|
// timeout outcome report.
|
||||||
report := h.report().resolverReport(
|
report := h.report().resolverReport(
|
||||||
@@ -201,6 +221,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
|
|
||||||
h.resolved = true
|
h.resolved = true
|
||||||
|
|
||||||
|
if err := h.processFinalHtlcFail(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Checkpoint our resolver with an abandoned outcome
|
// Checkpoint our resolver with an abandoned outcome
|
||||||
// because we take no further action on this htlc.
|
// because we take no further action on this htlc.
|
||||||
report := h.report().resolverReport(
|
report := h.report().resolverReport(
|
||||||
@@ -343,6 +367,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
h.htlcExpiry, currentHeight)
|
h.htlcExpiry, currentHeight)
|
||||||
h.resolved = true
|
h.resolved = true
|
||||||
|
|
||||||
|
if err := h.processFinalHtlcFail(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
report := h.report().resolverReport(
|
report := h.report().resolverReport(
|
||||||
nil,
|
nil,
|
||||||
channeldb.ResolverTypeIncomingHtlc,
|
channeldb.ResolverTypeIncomingHtlc,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -298,14 +299,15 @@ func (o *mockOnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
type incomingResolverTestContext struct {
|
type incomingResolverTestContext struct {
|
||||||
registry *mockRegistry
|
registry *mockRegistry
|
||||||
witnessBeacon *mockWitnessBeacon
|
witnessBeacon *mockWitnessBeacon
|
||||||
resolver *htlcIncomingContestResolver
|
resolver *htlcIncomingContestResolver
|
||||||
notifier *mock.ChainNotifier
|
notifier *mock.ChainNotifier
|
||||||
onionProcessor *mockOnionProcessor
|
onionProcessor *mockOnionProcessor
|
||||||
resolveErr chan error
|
resolveErr chan error
|
||||||
nextResolver ContractResolver
|
nextResolver ContractResolver
|
||||||
t *testing.T
|
finalHtlcOutcomeStored bool
|
||||||
|
t *testing.T
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolverTestContext {
|
func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolverTestContext {
|
||||||
@@ -323,12 +325,27 @@ func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolver
|
|||||||
|
|
||||||
checkPointChan := make(chan struct{}, 1)
|
checkPointChan := make(chan struct{}, 1)
|
||||||
|
|
||||||
|
c := &incomingResolverTestContext{
|
||||||
|
registry: registry,
|
||||||
|
witnessBeacon: witnessBeacon,
|
||||||
|
notifier: notifier,
|
||||||
|
onionProcessor: onionProcessor,
|
||||||
|
t: t,
|
||||||
|
}
|
||||||
|
|
||||||
chainCfg := ChannelArbitratorConfig{
|
chainCfg := ChannelArbitratorConfig{
|
||||||
ChainArbitratorConfig: ChainArbitratorConfig{
|
ChainArbitratorConfig: ChainArbitratorConfig{
|
||||||
Notifier: notifier,
|
Notifier: notifier,
|
||||||
PreimageDB: witnessBeacon,
|
PreimageDB: witnessBeacon,
|
||||||
Registry: registry,
|
Registry: registry,
|
||||||
OnionProcessor: onionProcessor,
|
OnionProcessor: onionProcessor,
|
||||||
|
PutFinalHtlcOutcome: func(chanId lnwire.ShortChannelID,
|
||||||
|
htlcId uint64, settled bool) error {
|
||||||
|
|
||||||
|
c.finalHtlcOutcomeStored = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
PutResolverReport: func(_ kvdb.RwTx,
|
PutResolverReport: func(_ kvdb.RwTx,
|
||||||
_ *channeldb.ResolverReport) error {
|
_ *channeldb.ResolverReport) error {
|
||||||
@@ -346,7 +363,8 @@ func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolver
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
resolver := &htlcIncomingContestResolver{
|
|
||||||
|
c.resolver = &htlcIncomingContestResolver{
|
||||||
htlcSuccessResolver: &htlcSuccessResolver{
|
htlcSuccessResolver: &htlcSuccessResolver{
|
||||||
contractResolverKit: *newContractResolverKit(cfg),
|
contractResolverKit: *newContractResolverKit(cfg),
|
||||||
htlcResolution: lnwallet.IncomingHtlcResolution{},
|
htlcResolution: lnwallet.IncomingHtlcResolution{},
|
||||||
@@ -359,14 +377,7 @@ func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolver
|
|||||||
htlcExpiry: testHtlcExpiry,
|
htlcExpiry: testHtlcExpiry,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &incomingResolverTestContext{
|
return c
|
||||||
registry: registry,
|
|
||||||
witnessBeacon: witnessBeacon,
|
|
||||||
resolver: resolver,
|
|
||||||
notifier: notifier,
|
|
||||||
onionProcessor: onionProcessor,
|
|
||||||
t: t,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *incomingResolverTestContext) resolve() {
|
func (i *incomingResolverTestContext) resolve() {
|
||||||
@@ -400,6 +411,10 @@ func (i *incomingResolverTestContext) waitForResult(expectSuccessRes bool) {
|
|||||||
if i.nextResolver != nil {
|
if i.nextResolver != nil {
|
||||||
i.t.Fatal("expected no next resolver")
|
i.t.Fatal("expected no next resolver")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require.True(i.t, i.finalHtlcOutcomeStored,
|
||||||
|
"expected final htlc outcome to be stored")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -469,6 +469,14 @@ func (h *htlcSuccessResolver) resolveRemoteCommitOutput() (
|
|||||||
func (h *htlcSuccessResolver) checkpointClaim(spendTx *chainhash.Hash,
|
func (h *htlcSuccessResolver) checkpointClaim(spendTx *chainhash.Hash,
|
||||||
outcome channeldb.ResolverOutcome) error {
|
outcome channeldb.ResolverOutcome) error {
|
||||||
|
|
||||||
|
// Mark the htlc as final settled.
|
||||||
|
err := h.ChainArbitratorConfig.PutFinalHtlcOutcome(
|
||||||
|
h.ChannelArbitratorConfig.ShortChanID, h.htlc.HtlcIndex, true,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Create a resolver report for claiming of the htlc itself.
|
// Create a resolver report for claiming of the htlc itself.
|
||||||
amt := btcutil.Amount(h.htlcResolution.SweepSignDesc.Output.Value)
|
amt := btcutil.Amount(h.htlcResolution.SweepSignDesc.Output.Value)
|
||||||
reports := []*channeldb.ResolverReport{
|
reports := []*channeldb.ResolverReport{
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ type htlcResolverTestContext struct {
|
|||||||
resolverResultChan chan resolveResult
|
resolverResultChan chan resolveResult
|
||||||
resolutionChan chan ResolutionMsg
|
resolutionChan chan ResolutionMsg
|
||||||
|
|
||||||
|
finalHtlcOutcomeStored bool
|
||||||
|
|
||||||
t *testing.T
|
t *testing.T
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +77,13 @@ func newHtlcResolverTestContext(t *testing.T,
|
|||||||
testCtx.resolutionChan <- msgs[0]
|
testCtx.resolutionChan <- msgs[0]
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
PutFinalHtlcOutcome: func(chanId lnwire.ShortChannelID,
|
||||||
|
htlcId uint64, settled bool) error {
|
||||||
|
|
||||||
|
testCtx.finalHtlcOutcomeStored = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
PutResolverReport: func(_ kvdb.RwTx,
|
PutResolverReport: func(_ kvdb.RwTx,
|
||||||
report *channeldb.ResolverReport) error {
|
report *channeldb.ResolverReport) error {
|
||||||
@@ -186,6 +195,7 @@ func TestHtlcSuccessSingleStage(t *testing.T) {
|
|||||||
reports: []*channeldb.ResolverReport{
|
reports: []*channeldb.ResolverReport{
|
||||||
claim,
|
claim,
|
||||||
},
|
},
|
||||||
|
finalHtlcStored: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +279,7 @@ func TestHtlcSuccessSecondStageResolution(t *testing.T) {
|
|||||||
secondStage,
|
secondStage,
|
||||||
firstStage,
|
firstStage,
|
||||||
},
|
},
|
||||||
|
finalHtlcStored: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,6 +461,7 @@ func TestHtlcSuccessSecondStageResolutionSweeper(t *testing.T) {
|
|||||||
secondStage,
|
secondStage,
|
||||||
firstStage,
|
firstStage,
|
||||||
},
|
},
|
||||||
|
finalHtlcStored: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,9 +477,10 @@ type checkpoint struct {
|
|||||||
preCheckpoint func(*htlcResolverTestContext, bool) error
|
preCheckpoint func(*htlcResolverTestContext, bool) error
|
||||||
|
|
||||||
// data we expect the resolver to be checkpointed with next.
|
// data we expect the resolver to be checkpointed with next.
|
||||||
incubating bool
|
incubating bool
|
||||||
resolved bool
|
resolved bool
|
||||||
reports []*channeldb.ResolverReport
|
reports []*channeldb.ResolverReport
|
||||||
|
finalHtlcStored bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// testHtlcSuccess tests resolution of a success resolver. It takes a a list of
|
// testHtlcSuccess tests resolution of a success resolver. It takes a a list of
|
||||||
@@ -573,6 +586,11 @@ func runFromCheckpoint(t *testing.T, ctx *htlcResolverTestContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the final htlc outcome is stored.
|
||||||
|
if cp.finalHtlcStored != ctx.finalHtlcOutcomeStored {
|
||||||
|
t.Fatal("final htlc store expectation failed")
|
||||||
|
}
|
||||||
|
|
||||||
// Finally encode the resolver, and store it for later use.
|
// Finally encode the resolver, and store it for later use.
|
||||||
b := bytes.Buffer{}
|
b := bytes.Buffer{}
|
||||||
if err := resolver.Encode(&b); err != nil {
|
if err := resolver.Encode(&b); err != nil {
|
||||||
|
|||||||
+2
-1
@@ -1920,7 +1920,8 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
|
|||||||
// As we've just accepted a new state, we'll now
|
// As we've just accepted a new state, we'll now
|
||||||
// immediately send the remote peer a revocation for our prior
|
// immediately send the remote peer a revocation for our prior
|
||||||
// state.
|
// state.
|
||||||
nextRevocation, currentHtlcs, err := l.channel.RevokeCurrentCommitment()
|
nextRevocation, currentHtlcs, _, err :=
|
||||||
|
l.channel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.log.Errorf("unable to revoke commitment: %v", err)
|
l.log.Errorf("unable to revoke commitment: %v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ func (l *linkTestContext) receiveCommitSigAlice(expHtlcs int) *lnwire.CommitSig
|
|||||||
func (l *linkTestContext) sendRevAndAckBobToAlice() {
|
func (l *linkTestContext) sendRevAndAckBobToAlice() {
|
||||||
l.t.Helper()
|
l.t.Helper()
|
||||||
|
|
||||||
rev, _, err := l.bobChannel.RevokeCurrentCommitment()
|
rev, _, _, err := l.bobChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.t.Fatalf("unable to revoke commitment: %v", err)
|
l.t.Fatalf("unable to revoke commitment: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1958,7 +1958,7 @@ func handleStateUpdate(link *channelLink,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteRev, _, err := remoteChannel.RevokeCurrentCommitment()
|
remoteRev, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -2062,7 +2062,7 @@ func updateState(batchTick chan time.Time, link *channelLink,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lastly, send a revocation back to the link.
|
// Lastly, send a revocation back to the link.
|
||||||
remoteRev, _, err := remoteChannel.RevokeCurrentCommitment()
|
remoteRev, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -3134,7 +3134,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) {
|
|||||||
|
|
||||||
// Next, revoke Bob's current commitment and send it to Alice so that we
|
// Next, revoke Bob's current commitment and send it to Alice so that we
|
||||||
// can test that Alice's circuits aren't trimmed.
|
// can test that Alice's circuits aren't trimmed.
|
||||||
rev, _, err := bobChan.RevokeCurrentCommitment()
|
rev, _, _, err := bobChan.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke current commitment")
|
require.NoError(t, err, "unable to revoke current commitment")
|
||||||
|
|
||||||
_, _, _, _, err = alice.channel.ReceiveRevocation(rev)
|
_, _, _, _, err = alice.channel.ReceiveRevocation(rev)
|
||||||
|
|||||||
+9
-7
@@ -4779,15 +4779,17 @@ func (lc *LightningChannel) PendingLocalUpdateCount() uint64 {
|
|||||||
// chain is advanced by a single commitment. This now lowest unrevoked
|
// chain is advanced by a single commitment. This now lowest unrevoked
|
||||||
// commitment becomes our currently accepted state within the channel. This
|
// commitment becomes our currently accepted state within the channel. This
|
||||||
// method also returns the set of HTLC's currently active within the commitment
|
// method also returns the set of HTLC's currently active within the commitment
|
||||||
// transaction. This return value allows callers to act once an HTLC has been
|
// transaction and the htlcs the were resolved. This return value allows callers
|
||||||
// locked into our commitment transaction.
|
// to act once an HTLC has been locked into our commitment transaction.
|
||||||
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []channeldb.HTLC, error) {
|
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck,
|
||||||
|
[]channeldb.HTLC, map[uint64]bool, error) {
|
||||||
|
|
||||||
lc.Lock()
|
lc.Lock()
|
||||||
defer lc.Unlock()
|
defer lc.Unlock()
|
||||||
|
|
||||||
revocationMsg, err := lc.generateRevocation(lc.currentHeight)
|
revocationMsg, err := lc.generateRevocation(lc.currentHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.log.Tracef("revoking height=%v, now at height=%v",
|
lc.log.Tracef("revoking height=%v, now at height=%v",
|
||||||
@@ -4808,11 +4810,11 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []c
|
|||||||
// is committed locally.
|
// is committed locally.
|
||||||
unsignedAckedUpdates := lc.getUnsignedAckedUpdates()
|
unsignedAckedUpdates := lc.getUnsignedAckedUpdates()
|
||||||
|
|
||||||
err = lc.channelState.UpdateCommitment(
|
finalHtlcs, err := lc.channelState.UpdateCommitment(
|
||||||
newCommitment, unsignedAckedUpdates,
|
newCommitment, unsignedAckedUpdates,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.log.Tracef("state transition accepted: "+
|
lc.log.Tracef("state transition accepted: "+
|
||||||
@@ -4825,7 +4827,7 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []c
|
|||||||
&lc.channelState.FundingOutpoint,
|
&lc.channelState.FundingOutpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
return revocationMsg, newCommitment.Htlcs, nil
|
return revocationMsg, newCommitment.Htlcs, finalHtlcs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiveRevocation processes a revocation sent by the remote party for the
|
// ReceiveRevocation processes a revocation sent by the remote party for the
|
||||||
|
|||||||
+78
-62
@@ -104,7 +104,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) {
|
|||||||
|
|
||||||
// Bob revokes his prior commitment given to him by Alice, since he now
|
// Bob revokes his prior commitment given to him by Alice, since he now
|
||||||
// has a valid signature for a newer commitment.
|
// has a valid signature for a newer commitment.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
// Bob finally send a signature for Alice's commitment transaction.
|
// Bob finally send a signature for Alice's commitment transaction.
|
||||||
@@ -135,7 +135,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) {
|
|||||||
require.NoError(t, err, "alice unable to process bob's new commitment")
|
require.NoError(t, err, "alice unable to process bob's new commitment")
|
||||||
|
|
||||||
// Alice then generates a revocation for bob.
|
// Alice then generates a revocation for bob.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke alice channel")
|
require.NoError(t, err, "unable to revoke alice channel")
|
||||||
|
|
||||||
// Finally Bob processes Alice's revocation, at this point the new HTLC
|
// Finally Bob processes Alice's revocation, at this point the new HTLC
|
||||||
@@ -220,7 +220,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) {
|
|||||||
err = aliceChannel.ReceiveNewCommitment(bobSig2, bobHtlcSigs2)
|
err = aliceChannel.ReceiveNewCommitment(bobSig2, bobHtlcSigs2)
|
||||||
require.NoError(t, err, "alice unable to process bob's new commitment")
|
require.NoError(t, err, "alice unable to process bob's new commitment")
|
||||||
|
|
||||||
aliceRevocation2, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation2, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to generate revocation")
|
require.NoError(t, err, "alice unable to generate revocation")
|
||||||
aliceSig2, aliceHtlcSigs2, _, err := aliceChannel.SignNextCommitment()
|
aliceSig2, aliceHtlcSigs2, _, err := aliceChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "alice unable to sign new commitment")
|
require.NoError(t, err, "alice unable to sign new commitment")
|
||||||
@@ -239,8 +239,17 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) {
|
|||||||
err = bobChannel.ReceiveNewCommitment(aliceSig2, aliceHtlcSigs2)
|
err = bobChannel.ReceiveNewCommitment(aliceSig2, aliceHtlcSigs2)
|
||||||
require.NoError(t, err, "bob unable to process alice's new commitment")
|
require.NoError(t, err, "bob unable to process alice's new commitment")
|
||||||
|
|
||||||
bobRevocation2, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation2, _, finalHtlcs, err := bobChannel.
|
||||||
|
RevokeCurrentCommitment()
|
||||||
|
|
||||||
require.NoError(t, err, "bob unable to revoke commitment")
|
require.NoError(t, err, "bob unable to revoke commitment")
|
||||||
|
|
||||||
|
// Check finalHtlcs for the expected final resolution.
|
||||||
|
require.Len(t, finalHtlcs, 1, "final htlc expected")
|
||||||
|
for _, settled := range finalHtlcs {
|
||||||
|
require.True(t, settled, "final settle expected")
|
||||||
|
}
|
||||||
|
|
||||||
fwdPkg, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation2)
|
fwdPkg, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation2)
|
||||||
require.NoError(t, err, "alice unable to process bob's revocation")
|
require.NoError(t, err, "alice unable to process bob's revocation")
|
||||||
if len(fwdPkg.Adds) != 0 {
|
if len(fwdPkg.Adds) != 0 {
|
||||||
@@ -393,7 +402,7 @@ func TestChannelZeroAddLocalHeight(t *testing.T) {
|
|||||||
|
|
||||||
// Alice should reply with a revocation.
|
// Alice should reply with a revocation.
|
||||||
// -----rev----->
|
// -----rev----->
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
@@ -570,7 +579,7 @@ func testCommitHTLCSigTieBreak(t *testing.T, restart bool) {
|
|||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive alice's commitment")
|
require.NoError(t, err, "unable to receive alice's commitment")
|
||||||
|
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob's commitment")
|
require.NoError(t, err, "unable to revoke bob's commitment")
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err, "unable to receive bob's revocation")
|
require.NoError(t, err, "unable to receive bob's revocation")
|
||||||
@@ -2312,7 +2321,7 @@ func TestUpdateFeeConcurrentSig(t *testing.T) {
|
|||||||
|
|
||||||
// Bob can revoke the prior commitment he had. This should lock in the
|
// Bob can revoke the prior commitment he had. This should lock in the
|
||||||
// fee update for him.
|
// fee update for him.
|
||||||
_, _, err = bobChannel.RevokeCurrentCommitment()
|
_, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
if chainfee.SatPerKWeight(bobChannel.channelState.LocalCommitment.FeePerKw) != fee {
|
||||||
@@ -2378,7 +2387,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
|||||||
|
|
||||||
// Bob can revoke the prior commitment he had. This should lock in the
|
// Bob can revoke the prior commitment he had. This should lock in the
|
||||||
// fee update for him.
|
// fee update for him.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -2413,7 +2422,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
|||||||
|
|
||||||
// Alice can revoke the old commitment, which will lock in the fee
|
// Alice can revoke the old commitment, which will lock in the fee
|
||||||
// update.
|
// update.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke alice channel")
|
require.NoError(t, err, "unable to revoke alice channel")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -2480,7 +2489,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
|||||||
// Alice can revoke the prior commitment she had, this will ack
|
// Alice can revoke the prior commitment she had, this will ack
|
||||||
// everything received before last commitment signature, but in this
|
// everything received before last commitment signature, but in this
|
||||||
// case that is nothing.
|
// case that is nothing.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
// Bob receives the revocation of the old commitment
|
// Bob receives the revocation of the old commitment
|
||||||
@@ -2508,7 +2517,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
|||||||
// Bob can revoke the old commitment. This will ack what he has
|
// Bob can revoke the old commitment. This will ack what he has
|
||||||
// received, including the HTLC and fee update. This will lock in the
|
// received, including the HTLC and fee update. This will lock in the
|
||||||
// fee update for bob.
|
// fee update for bob.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke alice channel")
|
require.NoError(t, err, "unable to revoke alice channel")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -2542,7 +2551,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
|||||||
|
|
||||||
// After Alice now revokes her old commitment, the fee update should
|
// After Alice now revokes her old commitment, the fee update should
|
||||||
// lock in.
|
// lock in.
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -2644,7 +2653,7 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
|||||||
|
|
||||||
// Bob can revoke the prior commitment he had. This should lock in the
|
// Bob can revoke the prior commitment he had. This should lock in the
|
||||||
// fee update for him.
|
// fee update for him.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to generate bob revocation")
|
require.NoError(t, err, "unable to generate bob revocation")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -2680,7 +2689,7 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
|||||||
|
|
||||||
// Alice can revoke the old commitment, which will lock in the fee
|
// Alice can revoke the old commitment, which will lock in the fee
|
||||||
// update.
|
// update.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke alice channel")
|
require.NoError(t, err, "unable to revoke alice channel")
|
||||||
|
|
||||||
if chainfee.SatPerKWeight(
|
if chainfee.SatPerKWeight(
|
||||||
@@ -3074,7 +3083,7 @@ func TestChanSyncOweCommitment(t *testing.T) {
|
|||||||
// adding one of her own.
|
// adding one of her own.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "bob unable to process alice's commitment")
|
require.NoError(t, err, "bob unable to process alice's commitment")
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "bob unable to sign commitment")
|
require.NoError(t, err, "bob unable to sign commitment")
|
||||||
@@ -3082,7 +3091,7 @@ func TestChanSyncOweCommitment(t *testing.T) {
|
|||||||
require.NoError(t, err, "alice unable to recv revocation")
|
require.NoError(t, err, "alice unable to recv revocation")
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "alice unable to rev bob's commitment")
|
require.NoError(t, err, "alice unable to rev bob's commitment")
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -3234,7 +3243,7 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
|
|||||||
// completes, the htlc is settled on the local commitment
|
// completes, the htlc is settled on the local commitment
|
||||||
// transaction. Bob still owes Alice a signature to also settle
|
// transaction. Bob still owes Alice a signature to also settle
|
||||||
// the htlc on her local commitment transaction.
|
// the htlc on her local commitment transaction.
|
||||||
bobRevoke, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevoke, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to revoke commitment: %v", err)
|
t.Fatalf("unable to revoke commitment: %v", err)
|
||||||
}
|
}
|
||||||
@@ -3264,7 +3273,7 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
aliceRevoke, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevoke, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -3330,7 +3339,7 @@ func TestChanSyncOweRevocation(t *testing.T) {
|
|||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "bob unable to process alice's commitment")
|
require.NoError(t, err, "bob unable to process alice's commitment")
|
||||||
|
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "bob unable to sign commitment")
|
require.NoError(t, err, "bob unable to sign commitment")
|
||||||
@@ -3342,7 +3351,7 @@ func TestChanSyncOweRevocation(t *testing.T) {
|
|||||||
|
|
||||||
// At this point, we'll simulate the connection breaking down by Bob's
|
// At this point, we'll simulate the connection breaking down by Bob's
|
||||||
// lack of knowledge of the revocation message that Alice just sent.
|
// lack of knowledge of the revocation message that Alice just sent.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
|
|
||||||
// If we fetch the channel sync messages at this state, then Alice
|
// If we fetch the channel sync messages at this state, then Alice
|
||||||
@@ -3482,7 +3491,7 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
|
|||||||
|
|
||||||
// Bob generates the revoke and sig message, but the messages don't
|
// Bob generates the revoke and sig message, but the messages don't
|
||||||
// reach Alice before the connection dies.
|
// reach Alice before the connection dies.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "bob unable to sign commitment")
|
require.NoError(t, err, "bob unable to sign commitment")
|
||||||
@@ -3559,7 +3568,7 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
|
|||||||
require.NoError(t, err, "alice unable to recv revocation")
|
require.NoError(t, err, "alice unable to recv revocation")
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "alice unable to rev bob's commitment")
|
require.NoError(t, err, "alice unable to rev bob's commitment")
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -3630,7 +3639,7 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
|
|||||||
// signature for Bob's updated state. Instead she will issue a new
|
// signature for Bob's updated state. Instead she will issue a new
|
||||||
// update before sending a new CommitSig. This will lead to Alice's
|
// update before sending a new CommitSig. This will lead to Alice's
|
||||||
// local commit chain getting height > remote commit chain.
|
// local commit chain getting height > remote commit chain.
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -3652,7 +3661,7 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
|
|||||||
// Bob then sends his revocation message, but before Alice can process
|
// Bob then sends his revocation message, but before Alice can process
|
||||||
// it (and before he scan send his CommitSig message), then connection
|
// it (and before he scan send his CommitSig message), then connection
|
||||||
// dies.
|
// dies.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
|
|
||||||
// Now if we attempt to synchronize states at this point, Alice should
|
// Now if we attempt to synchronize states at this point, Alice should
|
||||||
@@ -3746,7 +3755,7 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
|
|||||||
bobSigMsg.CommitSig, bobSigMsg.HtlcSigs,
|
bobSigMsg.CommitSig, bobSigMsg.HtlcSigs,
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "alice unable to rev bob's commitment")
|
require.NoError(t, err, "alice unable to rev bob's commitment")
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -4132,7 +4141,7 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
|||||||
|
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "bob unable to process alice's commitment")
|
require.NoError(t, err, "bob unable to process alice's commitment")
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "bob unable to sign commitment")
|
require.NoError(t, err, "bob unable to sign commitment")
|
||||||
@@ -4140,7 +4149,7 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
|||||||
require.NoError(t, err, "alice unable to recv revocation")
|
require.NoError(t, err, "alice unable to recv revocation")
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "alice unable to rev bob's commitment")
|
require.NoError(t, err, "alice unable to rev bob's commitment")
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -4330,7 +4339,7 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
|||||||
// transition.
|
// transition.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "bob unable to process alice's commitment")
|
require.NoError(t, err, "bob unable to process alice's commitment")
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "bob unable to sign commitment")
|
require.NoError(t, err, "bob unable to sign commitment")
|
||||||
@@ -4338,7 +4347,7 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
|||||||
require.NoError(t, err, "alice unable to recv revocation")
|
require.NoError(t, err, "alice unable to recv revocation")
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "alice unable to rev bob's commitment")
|
require.NoError(t, err, "alice unable to rev bob's commitment")
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "alice unable to revoke commitment")
|
require.NoError(t, err, "alice unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to recv revocation")
|
require.NoError(t, err, "bob unable to recv revocation")
|
||||||
@@ -5013,7 +5022,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5043,7 +5052,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5087,7 +5096,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5130,11 +5139,18 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
err = aliceChannel.ReceiveFailHTLC(htlc2.ID, []byte("bad"))
|
err = aliceChannel.ReceiveFailHTLC(htlc2.ID, []byte("bad"))
|
||||||
require.NoError(t, err, "unable to recv htlc cancel")
|
require.NoError(t, err, "unable to recv htlc cancel")
|
||||||
|
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, finalHtlcs, err := bobChannel.
|
||||||
|
RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check finalHtlcs for the expected final resolution.
|
||||||
|
require.Len(t, finalHtlcs, 1, "final htlc expected")
|
||||||
|
for _, settled := range finalHtlcs {
|
||||||
|
require.False(t, settled, "final fail expected")
|
||||||
|
}
|
||||||
|
|
||||||
// Alice should detect that she doesn't need to forward any Adds's, but
|
// Alice should detect that she doesn't need to forward any Adds's, but
|
||||||
// that the Fail has been locked in an can be forwarded.
|
// that the Fail has been locked in an can be forwarded.
|
||||||
_, adds, settleFails, _, err := aliceChannel.ReceiveRevocation(bobRevocation)
|
_, adds, settleFails, _, err := aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
@@ -5179,7 +5195,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5210,7 +5226,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5240,7 +5256,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -5852,13 +5868,13 @@ func TestMaxAsynchronousHtlcs(t *testing.T) {
|
|||||||
require.NoError(t, err, "unable to receive new commitment")
|
require.NoError(t, err, "unable to receive new commitment")
|
||||||
|
|
||||||
// Both sides exchange revocations as in step 4 & 5.
|
// Both sides exchange revocations as in step 4 & 5.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke revocation")
|
require.NoError(t, err, "unable to revoke revocation")
|
||||||
|
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err, "unable to receive revocation")
|
require.NoError(t, err, "unable to receive revocation")
|
||||||
|
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke revocation")
|
require.NoError(t, err, "unable to revoke revocation")
|
||||||
|
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
@@ -6549,7 +6565,7 @@ func TestChannelRestoreUpdateLogs(t *testing.T) {
|
|||||||
// Bob receives this commitment signature, and revokes his old state.
|
// Bob receives this commitment signature, and revokes his old state.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
// When Alice now receives this revocation, she will advance her remote
|
// When Alice now receives this revocation, she will advance her remote
|
||||||
@@ -6728,7 +6744,7 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) {
|
|||||||
assertInLogs(t, aliceChannel, 1, 0, 0, 1)
|
assertInLogs(t, aliceChannel, 1, 0, 0, 1)
|
||||||
restoreAndAssert(t, aliceChannel, 1, 0, 0, 0)
|
restoreAndAssert(t, aliceChannel, 1, 0, 0, 0)
|
||||||
|
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err, "bob unable to process alice's revocation")
|
require.NoError(t, err, "bob unable to process alice's revocation")
|
||||||
@@ -6758,7 +6774,7 @@ func TestChannelRestoreUpdateLogsFailedHTLC(t *testing.T) {
|
|||||||
// When Alice receives Bob's revocation, the Fail is irrevocably locked
|
// When Alice receives Bob's revocation, the Fail is irrevocably locked
|
||||||
// in on both sides. She should compact the logs, removing the HTLC and
|
// in on both sides. She should compact the logs, removing the HTLC and
|
||||||
// the corresponding Fail from the local update log.
|
// the corresponding Fail from the local update log.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err, "unable to receive revocation")
|
require.NoError(t, err, "unable to receive revocation")
|
||||||
@@ -6974,7 +6990,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
// Bob receives this commitment signature, and revokes his old state.
|
// Bob receives this commitment signature, and revokes his old state.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
// Now the HTLC is locked into Bob's commitment, a restoration should
|
// Now the HTLC is locked into Bob's commitment, a restoration should
|
||||||
@@ -7004,7 +7020,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
|
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
// Now both the local and remote add heights should be properly set.
|
// Now both the local and remote add heights should be properly set.
|
||||||
@@ -7046,7 +7062,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
|
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
// Since Bob just revoked another commitment, a restoration should
|
// Since Bob just revoked another commitment, a restoration should
|
||||||
@@ -7082,7 +7098,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
// Alice should receive the commitment and send over a revocation.
|
// Alice should receive the commitment and send over a revocation.
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
// Both heights should be 2 and they are on both commitments.
|
// Both heights should be 2 and they are on both commitments.
|
||||||
@@ -7119,7 +7135,7 @@ func TestChannelRestoreCommitHeight(t *testing.T) {
|
|||||||
// Alice receives commitment, sends revocation.
|
// Alice receives commitment, sends revocation.
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
_, _, err = aliceChannel.RevokeCurrentCommitment()
|
_, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke commitment")
|
require.NoError(t, err, "unable to revoke commitment")
|
||||||
|
|
||||||
aliceChannel = restoreAndAssertCommitHeights(
|
aliceChannel = restoreAndAssertCommitHeights(
|
||||||
@@ -7173,7 +7189,7 @@ func TestForceCloseBorkedState(t *testing.T) {
|
|||||||
require.NoError(t, err, "unable to sign commit")
|
require.NoError(t, err, "unable to sign commit")
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSigs, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSigs, aliceHtlcSigs)
|
||||||
require.NoError(t, err, "unable to receive commitment")
|
require.NoError(t, err, "unable to receive commitment")
|
||||||
revokeMsg, _, err := bobChannel.RevokeCurrentCommitment()
|
revokeMsg, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err, "unable to revoke bob commitment")
|
require.NoError(t, err, "unable to revoke bob commitment")
|
||||||
bobSigs, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
bobSigs, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
require.NoError(t, err, "unable to sign commit")
|
require.NoError(t, err, "unable to sign commit")
|
||||||
@@ -7213,7 +7229,7 @@ func TestForceCloseBorkedState(t *testing.T) {
|
|||||||
if err != channeldb.ErrChanBorked {
|
if err != channeldb.ErrChanBorked {
|
||||||
t.Fatalf("sign commitment should have failed: %v", err)
|
t.Fatalf("sign commitment should have failed: %v", err)
|
||||||
}
|
}
|
||||||
_, _, err = aliceChannel.RevokeCurrentCommitment()
|
_, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
if err != channeldb.ErrChanBorked {
|
if err != channeldb.ErrChanBorked {
|
||||||
t.Fatalf("append remove chain tail should have failed")
|
t.Fatalf("append remove chain tail should have failed")
|
||||||
}
|
}
|
||||||
@@ -8792,7 +8808,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
|
|||||||
|
|
||||||
// Alice should reply with a revocation.
|
// Alice should reply with a revocation.
|
||||||
// -----rev----->
|
// -----rev----->
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -8817,7 +8833,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
|
|||||||
// Bob revokes his current commitment and sends a revocation
|
// Bob revokes his current commitment and sends a revocation
|
||||||
// to Alice.
|
// to Alice.
|
||||||
// <----rev------
|
// <----rev------
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = newAliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = newAliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -8903,7 +8919,7 @@ func TestChannelLocalUnsignedUpdatesFailure(t *testing.T) {
|
|||||||
// Bob should reply with a revocation and Alice should save the fail as
|
// Bob should reply with a revocation and Alice should save the fail as
|
||||||
// an unsigned local update.
|
// an unsigned local update.
|
||||||
// <----rev-----
|
// <----rev-----
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -8987,7 +9003,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// <----rev-----
|
// <----rev-----
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9014,7 +9030,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// <----rev-----
|
// <----rev-----
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9027,7 +9043,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// -----rev---->
|
// -----rev---->
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fwdPkg, _, _, _, err := newBobChannel.ReceiveRevocation(aliceRevocation)
|
fwdPkg, _, _, _, err := newBobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9119,7 +9135,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||||
|
|
||||||
// <---rev---
|
// <---rev---
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9133,7 +9149,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||||
|
|
||||||
// ---rev--->
|
// ---rev--->
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9154,7 +9170,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||||
|
|
||||||
// ---rev--->
|
// ---rev--->
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9168,7 +9184,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||||
|
|
||||||
// <---rev---
|
// <---rev---
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9192,7 +9208,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||||
|
|
||||||
// <---rev---
|
// <---rev---
|
||||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9207,7 +9223,7 @@ func TestIsChannelClean(t *testing.T) {
|
|||||||
|
|
||||||
// The state should finally be clean after alice sends her revocation.
|
// The state should finally be clean after alice sends her revocation.
|
||||||
// ---rev--->
|
// ---rev--->
|
||||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9346,7 +9362,7 @@ func testGetDustSum(t *testing.T, chantype channeldb.ChannelType) {
|
|||||||
// Bob now sends a revocation for his prior commitment, and this should
|
// Bob now sends a revocation for his prior commitment, and this should
|
||||||
// change Alice's perspective to no longer include the first HTLC as
|
// change Alice's perspective to no longer include the first HTLC as
|
||||||
// dust.
|
// dust.
|
||||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -9359,7 +9375,7 @@ func testGetDustSum(t *testing.T, chantype channeldb.ChannelType) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bobRevocation, _, err := chanB.RevokeCurrentCommitment()
|
bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -518,7 +518,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceRevocation, _, err := chanA.RevokeCurrentCommitment()
|
aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
|||||||
err = remoteChannel.ReceiveNewCommitment(localSig, localHtlcSigs)
|
err = remoteChannel.ReceiveNewCommitment(localSig, localHtlcSigs)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
revMsg, _, err := remoteChannel.RevokeCurrentCommitment()
|
revMsg, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, _, _, _, err = localChannel.ReceiveRevocation(revMsg)
|
_, _, _, _, err = localChannel.ReceiveRevocation(revMsg)
|
||||||
@@ -309,7 +309,7 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
|||||||
err = localChannel.ReceiveNewCommitment(remoteSig, remoteHtlcSigs)
|
err = localChannel.ReceiveNewCommitment(remoteSig, remoteHtlcSigs)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, _, err = localChannel.RevokeCurrentCommitment()
|
_, _, _, err = localChannel.RevokeCurrentCommitment()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Now the local node force closes the channel so that we can inspect
|
// Now the local node force closes the channel so that we can inspect
|
||||||
|
|||||||
@@ -1165,6 +1165,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
|
|||||||
IsForwardedHTLC: s.htlcSwitch.IsForwardedHTLC,
|
IsForwardedHTLC: s.htlcSwitch.IsForwardedHTLC,
|
||||||
Clock: clock.NewDefaultClock(),
|
Clock: clock.NewDefaultClock(),
|
||||||
SubscribeBreachComplete: s.breachArbiter.SubscribeBreachComplete,
|
SubscribeBreachComplete: s.breachArbiter.SubscribeBreachComplete,
|
||||||
|
PutFinalHtlcOutcome: s.chanStateDB.PutOnchainFinalHtlcOutcome, // nolint: lll
|
||||||
}, dbs.ChanStateDB)
|
}, dbs.ChanStateDB)
|
||||||
|
|
||||||
// Select the configuration and furnding parameters for Bitcoin or
|
// Select the configuration and furnding parameters for Bitcoin or
|
||||||
|
|||||||
Reference in new issue
Block a user