Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runes: document parameter usage, and let them be ints. #6295

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/lightning-commando-rune.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ being run:
* method: the command being run, e.g. "method=withdraw".
* rate: the rate limit, per minute, e.g. "rate=60".
* pnum: the number of parameters. e.g. "pnum<2".
* pnameX: the parameter named X. e.g. "pnamedestination=1RustyRX2oai4EYYDpQGWvEL62BBGqN9T".
* pnameX: the parameter named X (with any punctuation like `_` removed). e.g. "pnamedestination=1RustyRX2oai4EYYDpQGWvEL62BBGqN9T".
* parrN: the N'th parameter. e.g. "parr0=1RustyRX2oai4EYYDpQGWvEL62BBGqN9T".

RESTRICTION FORMAT
Expand Down
12 changes: 12 additions & 0 deletions plugins/commando.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,18 @@ static const char *check_condition(const tal_t *ctx,
if (!ptok)
return rune_alt_single_missing(ctx, alt);

/* Pass through valid integers as integers. */
if (ptok->type == JSMN_PRIMITIVE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool this is much nicer than my suggestion./

s64 val;

if (json_to_s64(cinfo->buf, ptok, &val)) {
plugin_log(plugin, LOG_DBG, "It's an int %"PRId64, val);
return rune_alt_single_int(ctx, alt, val);
}

/* Otherwise, treat it as a string (< and > will fail with
* "is not an integer field") */
}
return rune_alt_single_str(ctx, alt,
cinfo->buf + ptok->start,
ptok->end - ptok->start);
Expand Down
53 changes: 53 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2991,6 +2991,58 @@ def test_commando_listrunes(node_factory):
assert not_our_rune['our_rune'] is False


def test_commando_rune_pay_amount(node_factory):
l1, l2 = node_factory.line_graph(2)

# This doesn't really work, since amount_msat is illegal if invoice
# includes an amount, and runes aren't smart enough to decode bolt11!
rune = l1.rpc.commando_rune(restrictions=[['method=pay'],
['pnameamountmsat<10000']])['rune']
inv1 = l2.rpc.invoice(amount_msat=12300, label='inv1', description='description1')['bolt11']
inv2 = l2.rpc.invoice(amount_msat='any', label='inv2', description='description2')['bolt11']

# Rune requires amount_msat!
with pytest.raises(RpcError, match='Not authorized:'):
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params={'bolt11': inv1})

# As a named parameter!
with pytest.raises(RpcError, match='Not authorized:'):
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params=[inv1])

# Can't get around it this way!
with pytest.raises(RpcError, match='Not authorized:'):
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params=[inv2, 12000])

# Nor this way, using a string!
with pytest.raises(RpcError, match='Not authorized:'):
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params={'bolt11': inv2, 'amount_msat': '10000sat'})

# Too much!
with pytest.raises(RpcError, match='Not authorized:'):
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params={'bolt11': inv2, 'amount_msat': 12000})

# This works
l2.rpc.commando(peer_id=l1.info['id'],
rune=rune,
method='pay',
params={'bolt11': inv2, 'amount_msat': 9999})


def test_commando_blacklist(node_factory):
l1, l2 = node_factory.get_nodes(2)

Expand Down Expand Up @@ -3072,6 +3124,7 @@ def test_commando_blacklist(node_factory):
assert blacklisted_rune is True


@pytest.mark.slow_test
def test_commando_stress(node_factory, executor):
"""Stress test to slam commando with many large queries"""
nodes = node_factory.get_nodes(5)
Expand Down