Skip to content

Commit

Permalink
options: make anchors enabled by default, ignore experimental-anchors.
Browse files Browse the repository at this point in the history
We still want to test non-anchor channels, as we still support them, but
we've made it non-experimental.  To test non-anchor channels, we
use dev-force-features: -23.

Changelog-Added: Protocol: `option_anchors_zero_fee_htlc_tx` enabled, no longer experimental.
Changelog-Changed: Config: `experimental-anchors` now does nothing (it's enabled by default).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>


Header from folded patch 'fixup!_options__make_anchors_enabled_by_default,_ignore_experimental-anchors.patch':

fixup! options: make anchors enabled by default, ignore experimental-anchors.
  • Loading branch information
rustyrussell committed Feb 7, 2024
1 parent 0a2f03a commit 689e596
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 128 deletions.
23 changes: 21 additions & 2 deletions contrib/pyln-testing/pyln/testing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,10 +939,10 @@ def fundbalancedchannel(self, remote_node, total_capacity=FUNDAMOUNT, announce=T
else:
total_capacity = int(total_capacity)

self.fundwallet(total_capacity + 10000)
self.fundwallet(total_capacity + 35000)

if remote_node.config('experimental-dual-fund'):
remote_node.fundwallet(total_capacity + 10000)
remote_node.fundwallet(total_capacity + 35000)
# We cut the total_capacity in half, since the peer's
# expected to contribute that same amount
chan_capacity = total_capacity // 2
Expand Down Expand Up @@ -1274,6 +1274,25 @@ def mock_estimatesmartfee(r):
}
self.daemon.rpcproxy.mock_rpc('estimatesmartfee', mock_estimatesmartfee)

def mock_getmempoolinfo(r):
return {
'id': r['id'],
'error': None,
'result': {
'mempoolminfee': Decimal(feerates[4] * 4) / 10**8,
'minrelaytxfee': Decimal(feerates[4] * 4) / 10**8,
},
}

# Did they want to set minfee as well?
if len(feerates) > 4:
assert len(feerates) == 5
self.daemon.rpcproxy.mock_rpc('getmempoolinfo', mock_getmempoolinfo)

if wait_for_effect:
wait_for(lambda:
self.rpc.feerates(style='perkb')['perkb']['floor'] == feerates[4] * 4)

# Technically, this waits until it's called, not until it's processed.
# We wait until all four levels have been called.
if wait_for_effect:
Expand Down
10 changes: 0 additions & 10 deletions doc/lightningd-config.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,6 @@ specified multuple times. (Added in v23.08).
* **min-emergency-msat**=*msat*

This is the amount of funds to keep in the wallet to close anchor channels (which don't carry their own transaction fees). It defaults to 25000sat, and is only maintained if there are any anchor channels (or, when opening an anchor channel). This amount may be insufficient for multiple closes at once, however.


### Cleanup control options:

Expand Down Expand Up @@ -793,15 +792,6 @@ protocol to update channel types. At the moment, we only support setting
this option.


* **experimental-anchors**

Specifying this option turns on the `option_anchors_zero_fee_htlc_tx`
feature, meaning we can open anchor-based channels. This will become
the default for new channels in future, after more testing. Anchor-based
channels use larger commitment transactions, with the trade-off that they
don't have to use a worst-case fee, but can bump the commitment transaction
if it's needed. Note that this means that we need to keep
some funds aside: see `min-emergency-msat`.

BUGS
----
Expand Down
2 changes: 1 addition & 1 deletion lightningd/hsm_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ struct ext_key *hsm_init(struct lightningd *ld)
if (feature_offered(ld->our_features->bits[INIT_FEATURE],
OPT_ANCHORS_ZERO_FEE_HTLC_TX)
&& !hsm_capable(ld, WIRE_HSMD_SIGN_ANCHORSPEND)) {
fatal("--experimental-anchors needs HSM capable of signing anchors!");
fatal("anchors needs HSM capable of signing anchors!");
}

if (feature_offered(ld->our_features->bits[INIT_FEATURE],
Expand Down
7 changes: 5 additions & 2 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -906,11 +906,14 @@ static struct feature_set *default_features(const tal_t *ctx)
OPTIONAL_FEATURE(OPT_ZEROCONF),
OPTIONAL_FEATURE(OPT_CHANNEL_TYPE),
OPTIONAL_FEATURE(OPT_ROUTE_BLINDING),
/* Removed later for elements */
OPTIONAL_FEATURE(OPT_ANCHORS_ZERO_FEE_HTLC_TX),
};

for (size_t i = 0; i < ARRAY_SIZE(features); i++) {
struct feature_set *f
= feature_set_for_feature(NULL, features[i]);
struct feature_set *f;

f = feature_set_for_feature(NULL, features[i]);
if (!ret)
ret = tal_steal(ctx, f);
else
Expand Down
15 changes: 9 additions & 6 deletions lightningd/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -1258,10 +1258,7 @@ static char *opt_set_quiesce(struct lightningd *ld)

static char *opt_set_anchor_zero_fee_htlc_tx(struct lightningd *ld)
{
/* Requires static_remotekey, but we always set that */
feature_set_or(ld->our_features,
take(feature_set_for_feature(NULL,
OPTIONAL_FEATURE(OPT_ANCHORS_ZERO_FEE_HTLC_TX))));
/* FIXME: deprecated_apis! */
return NULL;
}

Expand Down Expand Up @@ -1469,8 +1466,7 @@ static void register_opts(struct lightningd *ld)
" channels.");
opt_register_early_noarg("--experimental-anchors",
opt_set_anchor_zero_fee_htlc_tx, ld,
"EXPERIMENTAL: enable option_anchors_zero_fee_htlc_tx"
" to open zero-fee-anchor channels");
opt_hidden);
clnopt_witharg("--announce-addr-dns", OPT_EARLY|OPT_SHOWBOOL,
opt_set_bool_arg, opt_show_bool,
&ld->announce_dns,
Expand Down Expand Up @@ -1789,6 +1785,13 @@ void handle_early_opts(struct lightningd *ld, int argc, char *argv[])
else
ld->config = mainnet_config;

/* No anchors if we're elements */
if (chainparams->is_elements) {
feature_set_sub(ld->our_features,
feature_set_for_feature(tmpctx,
OPTIONAL_FEATURE(OPT_ANCHORS_ZERO_FEE_HTLC_TX)));
}

/* Set the ln_port given from chainparams */
ld->config.ip_discovery_port = chainparams->ln_port;

Expand Down
3 changes: 1 addition & 2 deletions tests/test_bookkeeper.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,7 @@ def test_bookkeeping_missed_chans_leases(node_factory, bitcoind):
opts = {'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'plugin': str(coin_mvt_plugin),
'disable-plugin': 'bookkeeper',
'experimental-anchors': None}
'disable-plugin': 'bookkeeper'}

l1, l2 = node_factory.get_nodes(2, opts=opts)

Expand Down
90 changes: 43 additions & 47 deletions tests/test_closing.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,10 @@ def feerate_for(target, minimum=0, maximum=10000000):

orate = feerate_for(21000) # closing fee negotiation starts at 21000
prate = feerate_for(20000) # closing fee negotiation starts at 20000
opener, peer = node_factory.line_graph(2, opts=[{'feerates': (orate, orate, orate, orate)},
{'feerates': (prate, prate, prate, prate)}])
opener, peer = node_factory.line_graph(2, opts=[{'feerates': (orate, orate, orate, orate),
'dev-force-features': "-23"},
{'feerates': (prate, prate, prate, prate),
'dev-force-features': "-23"}])

opener_id = opener.info['id']
peer_id = peer.info['id']
Expand Down Expand Up @@ -501,8 +503,8 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams, anchors):
# Feerates identical so we don't get gratuitous commit to update them
opts = {'dev-disable-commit-after': 1,
'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# FIXME: | for dicts was added in Python 3.9 apparently.
l1, l2 = node_factory.line_graph(2, opts=[{**opts, **{'may_fail': True,
Expand Down Expand Up @@ -632,8 +634,8 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams, anchors)

opts = {'dev-disable-commit-after': 3,
'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# First we need to get funds to l2, so suppress after second.
# Feerates identical so we don't get gratuitous commit to update them
Expand Down Expand Up @@ -764,11 +766,9 @@ def test_channel_lease_falls_behind(node_factory, bitcoind):
their blockheight, the lessor fails the channel
'''
opts = [{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'experimental-anchors': None},
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100},
{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'experimental-anchors': None}]
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100}]

l1, l2, = node_factory.get_nodes(2, opts=opts)
amount = 500000
Expand Down Expand Up @@ -805,8 +805,7 @@ def test_channel_lease_post_expiry(node_factory, bitcoind, chainparams):
opts = {'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'may_reconnect': True, 'plugin': coin_mvt_plugin,
'dev-no-reconnect': None,
'experimental-anchors': None}
'dev-no-reconnect': None}

l1, l2, = node_factory.get_nodes(2, opts=opts)

Expand Down Expand Up @@ -909,8 +908,7 @@ def test_channel_lease_unilat_closes(node_factory, bitcoind):
'''
opts = {'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'funder-lease-requests-only': False,
'experimental-anchors': None}
'funder-lease-requests-only': False}

l1, l2, l3 = node_factory.get_nodes(3, opts=opts)
# Allow l2 some warnings
Expand Down Expand Up @@ -1020,12 +1018,10 @@ def test_channel_lease_lessor_cheat(node_factory, bitcoind, chainparams):
opts = [{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'may_reconnect': True, 'allow_warning': True,
'experimental-anchors': None,
'plugin': balance_snaps},
{'funder-policy': 'match', 'funder-policy-mod': 100,
'lease-fee-base-sat': '100sat', 'lease-fee-basis': 100,
'may_reconnect': True, 'allow_broken_log': True,
'experimental-anchors': None,
'plugin': balance_snaps}]

l1, l2, = node_factory.get_nodes(2, opts=opts)
Expand Down Expand Up @@ -1192,21 +1188,25 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
balance_snaps = os.path.join(os.getcwd(), 'tests/plugins/balance_snaps.py')

opts = {'may_reconnect': True,
'dev-no-reconnect': None}
if anchors:
commitfee = 3755
else:
commitfee = 11005
opts = {**opts, 'dev-force-features': "-23"}

l1, l2, l3, l4 = node_factory.line_graph(4,
opts=[{'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC'],
'may_reconnect': True,
'dev-no-reconnect': None},
**opts},
{'plugin': [coin_mvt_plugin, balance_snaps],
'disable-mpp': None,
'dev-no-reconnect': None,
'may_reconnect': True,
**opts,
'allow_broken_log': True},
{'plugin': [coin_mvt_plugin, balance_snaps],
'dev-no-reconnect': None,
'may_reconnect': True,
**opts,
'allow_broken_log': True},
{'dev-no-reconnect': None,
'may_reconnect': True}],
opts],
wait_for_announce=True)

channel_id = first_channel_id(l2, l3)
Expand Down Expand Up @@ -1257,7 +1257,7 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):

# reconnect with l1, which will fulfill the payment
l2.rpc.connect(l1.info['id'], 'localhost', l1.port)
l2.daemon.wait_for_log('got commitsig .*: feerate 11005, blockheight: 0, 0 added, 1 fulfilled, 0 failed, 0 changed')
l2.daemon.wait_for_log('got commitsig .*: feerate {}, blockheight: 0, 0 added, 1 fulfilled, 0 failed, 0 changed'.format(commitfee))

# l2 moves on for closed l3
bitcoind.generate_block(1)
Expand Down Expand Up @@ -1403,9 +1403,9 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams, anchors):
'allow_broken_log': True,
}
]
if anchors:
if anchors is False:
for opt in opts:
opt['experimental-anchors'] = None
opt['dev-force-features'] = "-23"

l1, l2, l3, l4, l5 = node_factory.get_nodes(5, opts=opts)

Expand Down Expand Up @@ -1586,8 +1586,8 @@ def test_penalty_rbf_normal(node_factory, bitcoind, executor, chainparams, ancho
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
to_self_delay = 10
opts = {'dev-disable-commit-after': 1}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# l1 is the thief, which causes our honest upstanding lightningd
# code to break, so l1 can fail.
Expand Down Expand Up @@ -1938,8 +1938,8 @@ def test_onchain_timeout(node_factory, bitcoind, executor, chainparams, anchors)
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')

opts = {'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# HTLC 1->2, 1 fails just after it's irrevocably committed
disconnects = ['+WIRE_REVOKE_AND_ACK*3', 'permfail']
Expand Down Expand Up @@ -2063,8 +2063,8 @@ def test_onchain_middleman_simple(node_factory, bitcoind, chainparams, anchors):
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')

opts = {'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# HTLC 1->2->3, 1->2 goes down after 2 gets preimage from 3.
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
Expand Down Expand Up @@ -2198,8 +2198,8 @@ def test_onchain_middleman_their_unilateral_in(node_factory, bitcoind, chainpara
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')

opts = {'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"
l1_disconnects = ['=WIRE_UPDATE_FULFILL_HTLC', 'permfail']
l2_disconnects = ['-WIRE_UPDATE_FULFILL_HTLC']

Expand Down Expand Up @@ -2328,8 +2328,8 @@ def test_onchain_their_unilateral_out(node_factory, bitcoind, chainparams, ancho
# We track channel balances, to verify that accounting is ok.
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
opts = {'plugin': coin_mvt_plugin}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

disconnects = ['-WIRE_UPDATE_FAIL_HTLC', 'permfail']

Expand Down Expand Up @@ -3364,8 +3364,8 @@ def test_closing_higherfee(node_factory, bitcoind, executor, anchors):
opts = {'may_reconnect': True,
'dev-no-reconnect': None,
'feerates': (7500, 7500, 7500, 7500)}
if anchors:
opts['experimental-anchors'] = None
if anchors is False:
opts['dev-force-features'] = "-23"

# We change the feerate before it starts negotiating close, so it aims
# for *higher* than last commit tx.
Expand Down Expand Up @@ -3739,10 +3739,8 @@ def test_closing_anchorspend_htlc_tx_rbf(node_factory, bitcoind):
# We want an outstanding HTLC for l1, so it uses anchor to push.
# Set feerates to lowball for now.
l1, l2 = node_factory.line_graph(2, opts=[{'feerates': (1000,) * 4,
'experimental-anchors': None,
'min-emergency-msat': 546000},
{'feerates': (1000,) * 4,
'experimental-anchors': None,
'disconnect': ['-WIRE_UPDATE_FAIL_HTLC']}])
assert 'anchors_zero_fee_htlc_tx/even' in only_one(l1.rpc.listpeerchannels()['channels'])['channel_type']['names']

Expand Down Expand Up @@ -3821,9 +3819,9 @@ def test_closing_anchorspend_htlc_tx_rbf(node_factory, bitcoind):
def test_htlc_no_force_close(node_factory, bitcoind, anchors):
"""l2<->l3 force closes while an HTLC is in flight from l1, but l2 can't timeout because the feerate has spiked. It should do so anyway."""
opts = [{}, {}, {'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC']}]
if anchors:
if anchors is False:
for opt in opts:
opt['experimental-anchors'] = None
opt['dev-force-features'] = "-23"

l1, l2, l3 = node_factory.line_graph(3, opts=opts)

Expand Down Expand Up @@ -3933,10 +3931,8 @@ def test_closing_minfee(node_factory, bitcoind):
def test_peer_anchor_push(node_factory, bitcoind, executor, chainparams):
"""Test that we use anchor on peer's commit to CPFP tx"""
l1, l2, l3 = node_factory.line_graph(3, opts=[{},
{'experimental-anchors': None,
'min-emergency-msat': 546000},
{'experimental-anchors': None,
'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC']}],
{'min-emergency-msat': 546000},
{'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC']}],
wait_for_announce=True)

# We splinter l2's funds so it's forced to use more than one UTXO to push.
Expand Down
Loading

0 comments on commit 689e596

Please sign in to comment.