diff --git a/contractcourt/htlc_outgoing_contest_resolver.go b/contractcourt/htlc_outgoing_contest_resolver.go index ceb87afab..41ef2516a 100644 --- a/contractcourt/htlc_outgoing_contest_resolver.go +++ b/contractcourt/htlc_outgoing_contest_resolver.go @@ -112,20 +112,18 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) { return nil, errResolverShuttingDown } - // If the current height is >= expiry-1, then a timeout + // If the current height is >= expiry, then a timeout // path spend will be valid to be included in the next // block, and we can immediately return the resolver. // - // TODO(joostjager): Statement above may not be valid. - // For CLTV locks, the expiry value is the last - // _invalid_ block. The likely reason that this does not - // create a problem, is that utxonursery is checking the - // expiry again (in the proper way). - // - // Source: - // https://github.com/btcsuite/btcd/blob/991d32e72fe84d5fbf9c47cd604d793a0cd3a072/blockchain/validate.go#L154 + // NOTE: when broadcasting this transaction, btcd will + // check the timelock in `CheckTransactionStandard`, + // which requires `expiry < currentHeight+1`. If the + // check doesn't pass, error `transaction is not + // finalized` will be returned and the broadcast will + // fail. newHeight := uint32(newBlock.Height) - if newHeight >= h.htlcResolution.Expiry-1 { + if newHeight >= h.htlcResolution.Expiry { log.Infof("%T(%v): HTLC has expired "+ "(height=%v, expiry=%v), transforming "+ "into timeout resolver", h, diff --git a/contractcourt/htlc_outgoing_contest_resolver_test.go b/contractcourt/htlc_outgoing_contest_resolver_test.go index 684812d48..751f8b971 100644 --- a/contractcourt/htlc_outgoing_contest_resolver_test.go +++ b/contractcourt/htlc_outgoing_contest_resolver_test.go @@ -33,7 +33,7 @@ func TestHtlcOutgoingResolverTimeout(t *testing.T) { // Notify arrival of the block after which the timeout path of the htlc // unlocks. - ctx.notifyEpoch(outgoingContestHtlcExpiry - 1) + ctx.notifyEpoch(outgoingContestHtlcExpiry) // Assert that the resolver finishes without error and transforms in a // timeout resolver.