mpp: Add the presplit MPP modifier

Changelog-Added: The MPP presplit modifier splits large payments into 10k satoshi parts to maximize chances of performing the payment and to obfuscate the overall amount being sent.
This commit is contained in:
Christian Decker 2020-07-03 17:24:46 +02:00
parent 3f399d15cb
commit b813974e13
2 changed files with 31 additions and 1 deletions

View file

@ -1841,6 +1841,7 @@ struct payment_modifier *paymod_mods[] = {
&directpay_pay_mod,
&shadowroute_pay_mod,
&exemptfee_pay_mod,
&presplit_pay_mod,
&routehints_pay_mod,
&waitblockheight_pay_mod,
&retry_pay_mod,
@ -1861,6 +1862,7 @@ static struct command_result *json_paymod(struct command *cmd,
const char *label;
unsigned int *retryfor;
u64 *riskfactor_millionths;
struct shadow_route_data *shadow_route;
#if DEVELOPER
bool *use_shadow;
#endif
@ -1949,8 +1951,12 @@ static struct command_result *json_paymod(struct command *cmd,
p->constraints.cltv_budget = *maxdelay;
payment_mod_exemptfee_get_data(p)->amount = *exemptfee;
shadow_route = payment_mod_shadowroute_get_data(p);
/* This is an MPP enabled pay command, disable amount fuzzing. */
shadow_route->fuzz_amount = false;
#if DEVELOPER
payment_mod_shadowroute_get_data(p)->use_shadow = *use_shadow;
shadow_route->use_shadow = *use_shadow;
#endif
p->label = tal_steal(p, label);
payment_start(p);

View file

@ -3055,3 +3055,27 @@ def test_pay_peer(node_factory):
# Next one should take the alternative, but it should still work
inv = l2.rpc.invoice(amt.millisatoshis, "final", "final")['bolt11']
l1.rpc.dev_pay(inv, use_shadow=False)
def test_mpp_presplit(node_factory):
"""Make a rather large payment of 5*10ksat and see it being split.
"""
MPP_TARGET_SIZE = 10**7 # Taken from libpluin-pay.c
amt = 5 * MPP_TARGET_SIZE
# Assert that the amount we're going to send is indeed larger than our
# split size.
assert(MPP_TARGET_SIZE < amt)
l1, l2, l3 = node_factory.line_graph(
3, fundamount=10**8, wait_for_announce=True,
opts={'wumbo': None}
)
inv = l3.rpc.invoice(amt, 'lbl', 'desc')['bolt11']
p = l1.rpc.pay(inv)
assert(p['parts'] >= 5)
inv = l3.rpc.listinvoices()['invoices'][0]
assert(inv['msatoshi'] == inv['msatoshi_received'])