diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 65f4bb909..5f0aa53d1 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -201,14 +201,15 @@ static bool closing_fee_is_acceptable(struct lightningd *ld, fee = calc_tx_fee(channel->funding_sats, tx); last_fee = calc_tx_fee(channel->funding_sats, channel->last_tx); - log_debug(channel->log, "Their actual closing tx fee is %s" - " vs previous %s", - type_to_string(tmpctx, struct amount_sat, &fee), - type_to_string(tmpctx, struct amount_sat, &last_fee)); - /* Weight once we add in sigs. */ weight = bitcoin_tx_weight(tx) + bitcoin_tx_input_sig_weight() * 2; + log_debug(channel->log, "Their actual closing tx fee is %s" + " vs previous %s: weight is %"PRIu64, + type_to_string(tmpctx, struct amount_sat, &fee), + type_to_string(tmpctx, struct amount_sat, &last_fee), + weight); + /* If we don't have a feerate estimate, this gives feerate_floor */ min_feerate = feerate_min(ld, &feerate_unknown); diff --git a/tests/test_closing.py b/tests/test_closing.py index f5993a7b2..80dc81df0 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -3653,3 +3653,32 @@ def test_close_twice(node_factory, executor): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) assert fut.result(TIMEOUT)['type'] == 'mutual' assert fut2.result(TIMEOUT)['type'] == 'mutual' + + +@pytest.mark.xfail(strict=True) +def test_close_weight_estimate(node_factory, bitcoind): + """closingd uses the expected closing tx weight to constrain fees; make sure that lightningd agrees + once it has the actual agreed tx""" + l1, l2 = node_factory.line_graph(2) + l1.rpc.close(l2.info['id']) + + # Closingd gives this estimate before it begins + log = l1.daemon.wait_for_log('Expected closing weight = ') + expected_weight = int(re.match('.*Expected closing weight = ([0-9]*),.*', log).group(1)) + + # This is the actual weight: in theory this could use their + # actual sig, and thus vary, but we don't do that. + log = l1.daemon.wait_for_log('Their actual closing tx fee is') + actual_weight = int(re.match('.*: weight is ([0-9]*).*', log).group(1)) + + assert actual_weight == expected_weight + + log = l1.daemon.wait_for_log('sendrawtransaction: ') + tx = re.match('.*sendrawtransaction: ([0-9a-f]*).*', log).group(1) + + # This could actually be a bit shorter: 1 in 256 chance we get + # lucky with a sig and it's shorter. We have 2 sigs, so that's + # 1 in 128. Unlikely to do better than 2 bytes off though! + signed_weight = int(bitcoind.rpc.decoderawtransaction(tx)['weight']) + assert signed_weight <= actual_weight + assert signed_weight >= actual_weight - 2