contractcourt: return htlcResolution when currentHeight has reached expiry

Only create the sweep tx when the height has reached, otherwise we will
get a broadcast error. Previously it wasn't caught by itest due to the
blocks were mined very fast, so the lock time was always reached.
This commit is contained in:
yyforyongyu 2022-10-13 07:01:03 +08:00
parent 2285bfdf9f
commit 5ed37166ef
No known key found for this signature in database
GPG key ID: 9BCD95C4FF296868
2 changed files with 9 additions and 11 deletions

View file

@ -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,

View file

@ -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.