mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-18 13:27:56 +01:00
htlcswitch: keep final htlc outcome
This commit is contained in:
parent
b85cda2a1d
commit
28256b7ea8
@ -16,6 +16,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
@ -135,6 +136,26 @@ var (
|
||||
// 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.
|
||||
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 (
|
||||
@ -618,6 +639,20 @@ func (c ChannelStatus) String() string {
|
||||
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
|
||||
// with a remote node. An open channel supports several options for on-disk
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
// database transaction.
|
||||
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
|
||||
// occur. This method its to be called when we revoke our prior commitment
|
||||
// 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,
|
||||
unsignedAckedUpdates []LogUpdate) error {
|
||||
unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
|
||||
|
||||
c.Lock()
|
||||
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
|
||||
// manner.
|
||||
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 {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
|
||||
@ -1822,17 +1883,35 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
||||
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 {
|
||||
// Filter for updates that are not on our local
|
||||
// commitment.
|
||||
// Gather updates that are not on our local commitment.
|
||||
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
|
||||
err = serializeLogUpdates(&b3, validUpdates)
|
||||
err = serializeLogUpdates(&b3, unsignedUpdates)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to serialize log updates: %v", err)
|
||||
}
|
||||
@ -1843,12 +1922,57 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LocalCommitment = *newCommitment
|
||||
finalHtlcs[id] = settled
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -2681,6 +2805,36 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
|
||||
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
|
||||
// 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
|
||||
|
@ -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")
|
||||
|
||||
// Assert that update is correctly written to the database.
|
||||
@ -1457,3 +1457,41 @@ func TestKeyLocatorEncoding(t *testing.T) {
|
||||
// version are equal.
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
// A callback which cleans up the created temporary directories is also
|
||||
// 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
|
||||
// of this restored channel.
|
||||
channel := nodeChans[0]
|
||||
err = channel.UpdateCommitment(nil, nil)
|
||||
_, err = channel.UpdateCommitment(nil, nil)
|
||||
if err != ErrNoRestoredChannelMutation {
|
||||
t.Fatalf("able to mutate restored channel")
|
||||
}
|
||||
|
@ -2451,7 +2451,7 @@ func forceStateTransition(chanA, chanB *lnwallet.LightningChannel) error {
|
||||
return err
|
||||
}
|
||||
|
||||
bobRevocation, _, err := chanB.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2468,7 +2468,7 @@ func forceStateTransition(chanA, chanB *lnwallet.LightningChannel) error {
|
||||
return err
|
||||
}
|
||||
|
||||
aliceRevocation, _, err := chanA.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -187,6 +187,11 @@ type ChainArbitratorConfig struct {
|
||||
// complete.
|
||||
SubscribeBreachComplete func(op *wire.OutPoint, c chan struct{}) (
|
||||
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
|
||||
|
@ -1460,6 +1460,10 @@ const (
|
||||
// other party time it out, or eventually learn of the pre-image, in
|
||||
// which case we'll claim on chain.
|
||||
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.
|
||||
@ -1483,6 +1487,9 @@ func (c ChainAction) String() string {
|
||||
case HtlcIncomingWatchAction:
|
||||
return "HtlcIncomingWatchAction"
|
||||
|
||||
case HtlcIncomingDustFinalAction:
|
||||
return "HtlcIncomingDustFinalAction"
|
||||
|
||||
default:
|
||||
return "<unknown action>"
|
||||
}
|
||||
@ -1698,6 +1705,10 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32,
|
||||
"needed for incoming dust htlc=%x",
|
||||
c.cfg.ChanPoint, htlc.RHash[:])
|
||||
|
||||
actionMap[HtlcIncomingDustFinalAction] = append(
|
||||
actionMap[HtlcIncomingDustFinalAction], htlc,
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@ -2213,6 +2224,27 @@ func (c *ChannelArbitrator) prepContractResolutions(
|
||||
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
|
||||
// launch a resolver to watch for the pre-image (and settle
|
||||
// backwards), or just timeout.
|
||||
|
@ -206,6 +206,8 @@ type chanArbTestCtx struct {
|
||||
|
||||
breachSubscribed chan struct{}
|
||||
breachResolutionChan chan struct{}
|
||||
|
||||
finalHtlcs map[uint64]bool
|
||||
}
|
||||
|
||||
func (c *chanArbTestCtx) CleanUp() {
|
||||
@ -306,6 +308,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
|
||||
|
||||
chanArbCtx := &chanArbTestCtx{
|
||||
breachSubscribed: make(chan struct{}),
|
||||
finalHtlcs: make(map[uint64]bool),
|
||||
}
|
||||
|
||||
chanPoint := wire.OutPoint{}
|
||||
@ -360,6 +363,13 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
|
||||
},
|
||||
Clock: clock.NewDefaultClock(),
|
||||
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
|
||||
@ -966,6 +976,12 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) {
|
||||
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
|
||||
// arbLog so it carries over the same on-disk state.
|
||||
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
|
||||
// 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.
|
||||
h.resolved = true
|
||||
|
||||
if err := h.processFinalHtlcFail(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We write a report to disk that indicates we could not decode
|
||||
// the htlc.
|
||||
resReport := h.report().resolverReport(
|
||||
@ -129,6 +145,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
h.htlcExpiry, currentHeight)
|
||||
h.resolved = true
|
||||
|
||||
if err := h.processFinalHtlcFail(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Finally, get our report and checkpoint our resolver with a
|
||||
// timeout outcome report.
|
||||
report := h.report().resolverReport(
|
||||
@ -201,6 +221,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
|
||||
h.resolved = true
|
||||
|
||||
if err := h.processFinalHtlcFail(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Checkpoint our resolver with an abandoned outcome
|
||||
// because we take no further action on this htlc.
|
||||
report := h.report().resolverReport(
|
||||
@ -343,6 +367,10 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
|
||||
h.htlcExpiry, currentHeight)
|
||||
h.resolved = true
|
||||
|
||||
if err := h.processFinalHtlcFail(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
report := h.report().resolverReport(
|
||||
nil,
|
||||
channeldb.ResolverTypeIncomingHtlc,
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -298,14 +299,15 @@ func (o *mockOnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte) (
|
||||
}
|
||||
|
||||
type incomingResolverTestContext struct {
|
||||
registry *mockRegistry
|
||||
witnessBeacon *mockWitnessBeacon
|
||||
resolver *htlcIncomingContestResolver
|
||||
notifier *mock.ChainNotifier
|
||||
onionProcessor *mockOnionProcessor
|
||||
resolveErr chan error
|
||||
nextResolver ContractResolver
|
||||
t *testing.T
|
||||
registry *mockRegistry
|
||||
witnessBeacon *mockWitnessBeacon
|
||||
resolver *htlcIncomingContestResolver
|
||||
notifier *mock.ChainNotifier
|
||||
onionProcessor *mockOnionProcessor
|
||||
resolveErr chan error
|
||||
nextResolver ContractResolver
|
||||
finalHtlcOutcomeStored bool
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
c := &incomingResolverTestContext{
|
||||
registry: registry,
|
||||
witnessBeacon: witnessBeacon,
|
||||
notifier: notifier,
|
||||
onionProcessor: onionProcessor,
|
||||
t: t,
|
||||
}
|
||||
|
||||
chainCfg := ChannelArbitratorConfig{
|
||||
ChainArbitratorConfig: ChainArbitratorConfig{
|
||||
Notifier: notifier,
|
||||
PreimageDB: witnessBeacon,
|
||||
Registry: registry,
|
||||
OnionProcessor: onionProcessor,
|
||||
PutFinalHtlcOutcome: func(chanId lnwire.ShortChannelID,
|
||||
htlcId uint64, settled bool) error {
|
||||
|
||||
c.finalHtlcOutcomeStored = true
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
PutResolverReport: func(_ kvdb.RwTx,
|
||||
_ *channeldb.ResolverReport) error {
|
||||
@ -346,7 +363,8 @@ func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolver
|
||||
return nil
|
||||
},
|
||||
}
|
||||
resolver := &htlcIncomingContestResolver{
|
||||
|
||||
c.resolver = &htlcIncomingContestResolver{
|
||||
htlcSuccessResolver: &htlcSuccessResolver{
|
||||
contractResolverKit: *newContractResolverKit(cfg),
|
||||
htlcResolution: lnwallet.IncomingHtlcResolution{},
|
||||
@ -359,14 +377,7 @@ func newIncomingResolverTestContext(t *testing.T, isExit bool) *incomingResolver
|
||||
htlcExpiry: testHtlcExpiry,
|
||||
}
|
||||
|
||||
return &incomingResolverTestContext{
|
||||
registry: registry,
|
||||
witnessBeacon: witnessBeacon,
|
||||
resolver: resolver,
|
||||
notifier: notifier,
|
||||
onionProcessor: onionProcessor,
|
||||
t: t,
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (i *incomingResolverTestContext) resolve() {
|
||||
@ -400,6 +411,10 @@ func (i *incomingResolverTestContext) waitForResult(expectSuccessRes bool) {
|
||||
if i.nextResolver != nil {
|
||||
i.t.Fatal("expected no next resolver")
|
||||
}
|
||||
|
||||
require.True(i.t, i.finalHtlcOutcomeStored,
|
||||
"expected final htlc outcome to be stored")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -469,6 +469,14 @@ func (h *htlcSuccessResolver) resolveRemoteCommitOutput() (
|
||||
func (h *htlcSuccessResolver) checkpointClaim(spendTx *chainhash.Hash,
|
||||
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.
|
||||
amt := btcutil.Amount(h.htlcResolution.SweepSignDesc.Output.Value)
|
||||
reports := []*channeldb.ResolverReport{
|
||||
|
@ -31,6 +31,8 @@ type htlcResolverTestContext struct {
|
||||
resolverResultChan chan resolveResult
|
||||
resolutionChan chan ResolutionMsg
|
||||
|
||||
finalHtlcOutcomeStored bool
|
||||
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
@ -75,6 +77,13 @@ func newHtlcResolverTestContext(t *testing.T,
|
||||
testCtx.resolutionChan <- msgs[0]
|
||||
return nil
|
||||
},
|
||||
PutFinalHtlcOutcome: func(chanId lnwire.ShortChannelID,
|
||||
htlcId uint64, settled bool) error {
|
||||
|
||||
testCtx.finalHtlcOutcomeStored = true
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
PutResolverReport: func(_ kvdb.RwTx,
|
||||
report *channeldb.ResolverReport) error {
|
||||
@ -186,6 +195,7 @@ func TestHtlcSuccessSingleStage(t *testing.T) {
|
||||
reports: []*channeldb.ResolverReport{
|
||||
claim,
|
||||
},
|
||||
finalHtlcStored: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -269,6 +279,7 @@ func TestHtlcSuccessSecondStageResolution(t *testing.T) {
|
||||
secondStage,
|
||||
firstStage,
|
||||
},
|
||||
finalHtlcStored: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -450,6 +461,7 @@ func TestHtlcSuccessSecondStageResolutionSweeper(t *testing.T) {
|
||||
secondStage,
|
||||
firstStage,
|
||||
},
|
||||
finalHtlcStored: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -465,9 +477,10 @@ type checkpoint struct {
|
||||
preCheckpoint func(*htlcResolverTestContext, bool) error
|
||||
|
||||
// data we expect the resolver to be checkpointed with next.
|
||||
incubating bool
|
||||
resolved bool
|
||||
reports []*channeldb.ResolverReport
|
||||
incubating bool
|
||||
resolved bool
|
||||
reports []*channeldb.ResolverReport
|
||||
finalHtlcStored bool
|
||||
}
|
||||
|
||||
// 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.
|
||||
b := bytes.Buffer{}
|
||||
if err := resolver.Encode(&b); err != nil {
|
||||
|
@ -1920,7 +1920,8 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
|
||||
// As we've just accepted a new state, we'll now
|
||||
// immediately send the remote peer a revocation for our prior
|
||||
// state.
|
||||
nextRevocation, currentHtlcs, err := l.channel.RevokeCurrentCommitment()
|
||||
nextRevocation, currentHtlcs, _, err :=
|
||||
l.channel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
l.log.Errorf("unable to revoke commitment: %v", err)
|
||||
return
|
||||
|
@ -179,7 +179,7 @@ func (l *linkTestContext) receiveCommitSigAlice(expHtlcs int) *lnwire.CommitSig
|
||||
func (l *linkTestContext) sendRevAndAckBobToAlice() {
|
||||
l.t.Helper()
|
||||
|
||||
rev, _, err := l.bobChannel.RevokeCurrentCommitment()
|
||||
rev, _, _, err := l.bobChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
l.t.Fatalf("unable to revoke commitment: %v", err)
|
||||
}
|
||||
|
@ -1958,7 +1958,7 @@ func handleStateUpdate(link *channelLink,
|
||||
return err
|
||||
}
|
||||
|
||||
remoteRev, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
remoteRev, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2062,7 +2062,7 @@ func updateState(batchTick chan time.Time, link *channelLink,
|
||||
}
|
||||
|
||||
// Lastly, send a revocation back to the link.
|
||||
remoteRev, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
remoteRev, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
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
|
||||
// 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")
|
||||
|
||||
_, _, _, _, err = alice.channel.ReceiveRevocation(rev)
|
||||
|
@ -4779,15 +4779,17 @@ func (lc *LightningChannel) PendingLocalUpdateCount() uint64 {
|
||||
// chain is advanced by a single commitment. This now lowest unrevoked
|
||||
// commitment becomes our currently accepted state within the channel. This
|
||||
// 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
|
||||
// locked into our commitment transaction.
|
||||
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []channeldb.HTLC, error) {
|
||||
// transaction and the htlcs the were resolved. This return value allows callers
|
||||
// to act once an HTLC has been locked into our commitment transaction.
|
||||
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck,
|
||||
[]channeldb.HTLC, map[uint64]bool, error) {
|
||||
|
||||
lc.Lock()
|
||||
defer lc.Unlock()
|
||||
|
||||
revocationMsg, err := lc.generateRevocation(lc.currentHeight)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
lc.log.Tracef("revoking height=%v, now at height=%v",
|
||||
@ -4808,11 +4810,11 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []c
|
||||
// is committed locally.
|
||||
unsignedAckedUpdates := lc.getUnsignedAckedUpdates()
|
||||
|
||||
err = lc.channelState.UpdateCommitment(
|
||||
finalHtlcs, err := lc.channelState.UpdateCommitment(
|
||||
newCommitment, unsignedAckedUpdates,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
lc.log.Tracef("state transition accepted: "+
|
||||
@ -4825,7 +4827,7 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck, []c
|
||||
&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
|
||||
|
@ -104,7 +104,7 @@ func testAddSettleWorkflow(t *testing.T, tweakless bool) {
|
||||
|
||||
// Bob revokes his prior commitment given to him by Alice, since he now
|
||||
// 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")
|
||||
|
||||
// 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")
|
||||
|
||||
// Alice then generates a revocation for bob.
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke alice channel")
|
||||
|
||||
// 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)
|
||||
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")
|
||||
aliceSig2, aliceHtlcSigs2, _, err := aliceChannel.SignNextCommitment()
|
||||
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)
|
||||
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")
|
||||
|
||||
// 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)
|
||||
require.NoError(t, err, "alice unable to process bob's revocation")
|
||||
if len(fwdPkg.Adds) != 0 {
|
||||
@ -393,7 +402,7 @@ func TestChannelZeroAddLocalHeight(t *testing.T) {
|
||||
|
||||
// Alice should reply with a revocation.
|
||||
// -----rev----->
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
@ -570,7 +579,7 @@ func testCommitHTLCSigTieBreak(t *testing.T, restart bool) {
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
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")
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
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
|
||||
// fee update for him.
|
||||
_, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
_, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to generate bob revocation")
|
||||
|
||||
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
|
||||
// fee update for him.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to generate bob revocation")
|
||||
|
||||
if chainfee.SatPerKWeight(
|
||||
@ -2413,7 +2422,7 @@ func TestUpdateFeeSenderCommits(t *testing.T) {
|
||||
|
||||
// Alice can revoke the old commitment, which will lock in the fee
|
||||
// update.
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke alice channel")
|
||||
|
||||
if chainfee.SatPerKWeight(
|
||||
@ -2480,7 +2489,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
// Alice can revoke the prior commitment she had, this will ack
|
||||
// everything received before last commitment signature, but in this
|
||||
// case that is nothing.
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to generate bob revocation")
|
||||
|
||||
// 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
|
||||
// received, including the HTLC and fee update. This will lock in the
|
||||
// fee update for bob.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke alice channel")
|
||||
|
||||
if chainfee.SatPerKWeight(
|
||||
@ -2542,7 +2551,7 @@ func TestUpdateFeeReceiverCommits(t *testing.T) {
|
||||
|
||||
// After Alice now revokes her old commitment, the fee update should
|
||||
// lock in.
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to generate bob revocation")
|
||||
|
||||
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
|
||||
// fee update for him.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to generate bob revocation")
|
||||
|
||||
if chainfee.SatPerKWeight(
|
||||
@ -2680,7 +2689,7 @@ func TestUpdateFeeMultipleUpdates(t *testing.T) {
|
||||
|
||||
// Alice can revoke the old commitment, which will lock in the fee
|
||||
// update.
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke alice channel")
|
||||
|
||||
if chainfee.SatPerKWeight(
|
||||
@ -3074,7 +3083,7 @@ func TestChanSyncOweCommitment(t *testing.T) {
|
||||
// adding one of her own.
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
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")
|
||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
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")
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
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
|
||||
// transaction. Bob still owes Alice a signature to also settle
|
||||
// the htlc on her local commitment transaction.
|
||||
bobRevoke, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevoke, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to revoke commitment: %v", err)
|
||||
}
|
||||
@ -3264,7 +3273,7 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aliceRevoke, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevoke, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -3330,7 +3339,7 @@ func TestChanSyncOweRevocation(t *testing.T) {
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
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")
|
||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
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
|
||||
// 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")
|
||||
|
||||
// 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
|
||||
// reach Alice before the connection dies.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke bob commitment")
|
||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
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")
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
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
|
||||
// update before sending a new CommitSig. This will lead to Alice's
|
||||
// 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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
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
|
||||
// it (and before he scan send his CommitSig message), then connection
|
||||
// dies.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke bob commitment")
|
||||
|
||||
// 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,
|
||||
)
|
||||
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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err, "bob unable to recv revocation")
|
||||
@ -4132,7 +4141,7 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
||||
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
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")
|
||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
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")
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err, "bob unable to recv revocation")
|
||||
@ -4330,7 +4339,7 @@ func TestFeeUpdateOldDiskFormat(t *testing.T) {
|
||||
// transition.
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
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")
|
||||
bobSig, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
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")
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
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")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err, "bob unable to recv revocation")
|
||||
@ -5013,7 +5022,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5043,7 +5052,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5087,7 +5096,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5130,11 +5139,18 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
err = aliceChannel.ReceiveFailHTLC(htlc2.ID, []byte("bad"))
|
||||
require.NoError(t, err, "unable to recv htlc cancel")
|
||||
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, finalHtlcs, err := bobChannel.
|
||||
RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
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
|
||||
// that the Fail has been locked in an can be forwarded.
|
||||
_, adds, settleFails, _, err := aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
@ -5179,7 +5195,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5210,7 +5226,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5240,7 +5256,7 @@ func TestLockedInHtlcForwardingSkipAfterRestart(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -5852,13 +5868,13 @@ func TestMaxAsynchronousHtlcs(t *testing.T) {
|
||||
require.NoError(t, err, "unable to receive new commitment")
|
||||
|
||||
// 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")
|
||||
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err, "unable to receive revocation")
|
||||
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke revocation")
|
||||
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
@ -6549,7 +6565,7 @@ func TestChannelRestoreUpdateLogs(t *testing.T) {
|
||||
// Bob receives this commitment signature, and revokes his old state.
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
// 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)
|
||||
restoreAndAssert(t, aliceChannel, 1, 0, 0, 0)
|
||||
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
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
|
||||
// in on both sides. She should compact the logs, removing the HTLC and
|
||||
// the corresponding Fail from the local update log.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
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.
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
// 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)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
// 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)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
// 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.
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
// 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.
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
require.NoError(t, err, "unable to receive commitment")
|
||||
_, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
_, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err, "unable to revoke commitment")
|
||||
|
||||
aliceChannel = restoreAndAssertCommitHeights(
|
||||
@ -7173,7 +7189,7 @@ func TestForceCloseBorkedState(t *testing.T) {
|
||||
require.NoError(t, err, "unable to sign commit")
|
||||
err = bobChannel.ReceiveNewCommitment(aliceSigs, aliceHtlcSigs)
|
||||
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")
|
||||
bobSigs, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||
require.NoError(t, err, "unable to sign commit")
|
||||
@ -7213,7 +7229,7 @@ func TestForceCloseBorkedState(t *testing.T) {
|
||||
if err != channeldb.ErrChanBorked {
|
||||
t.Fatalf("sign commitment should have failed: %v", err)
|
||||
}
|
||||
_, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
_, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
if err != channeldb.ErrChanBorked {
|
||||
t.Fatalf("append remove chain tail should have failed")
|
||||
}
|
||||
@ -8792,7 +8808,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
|
||||
|
||||
// Alice should reply with a revocation.
|
||||
// -----rev----->
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -8817,7 +8833,7 @@ func TestChannelUnsignedAckedFailure(t *testing.T) {
|
||||
// Bob revokes his current commitment and sends a revocation
|
||||
// to Alice.
|
||||
// <----rev------
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = newAliceChannel.ReceiveRevocation(bobRevocation)
|
||||
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
|
||||
// an unsigned local update.
|
||||
// <----rev-----
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -8987,7 +9003,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// <----rev-----
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9014,7 +9030,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// <----rev-----
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9027,7 +9043,7 @@ func TestChannelSignedAckRegression(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// -----rev---->
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
fwdPkg, _, _, _, err := newBobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9119,7 +9135,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||
|
||||
// <---rev---
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9133,7 +9149,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||
|
||||
// ---rev--->
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9154,7 +9170,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||
|
||||
// ---rev--->
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9168,7 +9184,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||
|
||||
// <---rev---
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9192,7 +9208,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
assertCleanOrDirty(false, aliceChannel, bobChannel, t)
|
||||
|
||||
// <---rev---
|
||||
bobRevocation, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err = bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9207,7 +9223,7 @@ func TestIsChannelClean(t *testing.T) {
|
||||
|
||||
// The state should finally be clean after alice sends her revocation.
|
||||
// ---rev--->
|
||||
aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err = aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
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
|
||||
// change Alice's perspective to no longer include the first HTLC as
|
||||
// dust.
|
||||
bobRevocation, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevocation)
|
||||
require.NoError(t, err)
|
||||
@ -9359,7 +9375,7 @@ func testGetDustSum(t *testing.T, chantype channeldb.ChannelType) {
|
||||
require.NoError(t, err)
|
||||
err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs)
|
||||
require.NoError(t, err)
|
||||
aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := aliceChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
|
||||
require.NoError(t, err)
|
||||
|
@ -502,7 +502,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
||||
return err
|
||||
}
|
||||
|
||||
bobRevocation, _, err := chanB.RevokeCurrentCommitment()
|
||||
bobRevocation, _, _, err := chanB.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -518,7 +518,7 @@ func ForceStateTransition(chanA, chanB *LightningChannel) error {
|
||||
return err
|
||||
}
|
||||
|
||||
aliceRevocation, _, err := chanA.RevokeCurrentCommitment()
|
||||
aliceRevocation, _, _, err := chanA.RevokeCurrentCommitment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
||||
err = remoteChannel.ReceiveNewCommitment(localSig, localHtlcSigs)
|
||||
require.NoError(t, err)
|
||||
|
||||
revMsg, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
revMsg, _, _, err := remoteChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, _, _, err = localChannel.ReceiveRevocation(revMsg)
|
||||
@ -309,7 +309,7 @@ func testVectors(t *testing.T, chanType channeldb.ChannelType, test testCase) {
|
||||
err = localChannel.ReceiveNewCommitment(remoteSig, remoteHtlcSigs)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = localChannel.RevokeCurrentCommitment()
|
||||
_, _, _, err = localChannel.RevokeCurrentCommitment()
|
||||
require.NoError(t, err)
|
||||
|
||||
// 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,
|
||||
Clock: clock.NewDefaultClock(),
|
||||
SubscribeBreachComplete: s.breachArbiter.SubscribeBreachComplete,
|
||||
PutFinalHtlcOutcome: s.chanStateDB.PutOnchainFinalHtlcOutcome, // nolint: lll
|
||||
}, dbs.ChanStateDB)
|
||||
|
||||
// Select the configuration and furnding parameters for Bitcoin or
|
||||
|
Loading…
Reference in New Issue
Block a user