@@ -1758,14 +1758,99 @@ static const struct plugin_notification notifications[] = {
17581758 },
17591759};
17601760
1761+ /* xpay doesn't have maxfeepercent or exemptfee, so we convert them to
1762+ * an absolute restriction here. If we can't, fail and let pay handle
1763+ * it. */
1764+ static bool calc_maxfee (struct command * cmd ,
1765+ const char * * maxfeestr ,
1766+ const char * buf ,
1767+ const jsmntok_t * invstringtok ,
1768+ const jsmntok_t * amount_msattok ,
1769+ const jsmntok_t * exemptfeetok ,
1770+ const jsmntok_t * maxfeepercenttok )
1771+ {
1772+ u64 maxfeepercent_ppm ;
1773+ struct amount_msat amount , maxfee , exemptfee ;
1774+
1775+ if (!exemptfeetok && !maxfeepercenttok )
1776+ return true;
1777+
1778+ /* Can't have both */
1779+ if (* maxfeestr )
1780+ return false;
1781+
1782+ /* If they specify amount easy, otherwise take from invoice */
1783+ if (amount_msattok ) {
1784+ if (!parse_amount_msat (& amount , buf + amount_msattok -> start ,
1785+ amount_msattok -> end - amount_msattok -> start ))
1786+ return false;
1787+ } else {
1788+ const struct bolt11 * b11 ;
1789+ char * fail ;
1790+ const char * invstr ;
1791+
1792+ /* We need to know total amount to calc fee */
1793+ if (!invstringtok )
1794+ return false;
1795+
1796+ invstr = json_strdup (tmpctx , buf , invstringtok );
1797+ b11 = bolt11_decode (tmpctx , invstr , NULL , NULL , NULL , & fail );
1798+ if (b11 != NULL ) {
1799+ if (b11 -> msat == NULL )
1800+ return false;
1801+ amount = * b11 -> msat ;
1802+ } else {
1803+ const struct tlv_invoice * b12 ;
1804+ b12 = invoice_decode (tmpctx , invstr , strlen (invstr ),
1805+ NULL , NULL , & fail );
1806+ if (b12 == NULL || b12 -> invoice_amount == NULL )
1807+ return false;
1808+ amount = amount_msat (* b12 -> invoice_amount );
1809+ }
1810+ }
1811+
1812+ if (maxfeepercenttok ) {
1813+ if (!json_to_millionths (buf ,
1814+ maxfeepercenttok ,
1815+ & maxfeepercent_ppm ))
1816+ return false;
1817+ } else
1818+ maxfeepercent_ppm = 500000 ;
1819+
1820+ if (!amount_msat_fee (& maxfee , amount , 0 , maxfeepercent_ppm / 100 ))
1821+ return false;
1822+
1823+ if (exemptfeetok ) {
1824+ if (!parse_amount_msat (& exemptfee , buf + exemptfeetok -> start ,
1825+ exemptfeetok -> end - exemptfeetok -> start ))
1826+ return false;
1827+ } else
1828+ exemptfee = AMOUNT_MSAT (5000 );
1829+
1830+ if (amount_msat_less (maxfee , exemptfee ))
1831+ maxfee = exemptfee ;
1832+
1833+ * maxfeestr = fmt_amount_msat (cmd , maxfee );
1834+ plugin_log (cmd -> plugin , LOG_DBG ,
1835+ "Converted maxfeepercent=%.*s, exemptfee=%.*s to maxfee %s" ,
1836+ maxfeepercenttok ? json_tok_full_len (maxfeepercenttok ) : 5 ,
1837+ maxfeepercenttok ? json_tok_full (buf , maxfeepercenttok ) : "UNSET" ,
1838+ exemptfeetok ? json_tok_full_len (exemptfeetok ) : 5 ,
1839+ exemptfeetok ? json_tok_full (buf , exemptfeetok ) : "UNSET" ,
1840+ * maxfeestr );
1841+
1842+ return true;
1843+ }
1844+
17611845static struct command_result * handle_rpc_command (struct command * cmd ,
17621846 const char * buf ,
17631847 const jsmntok_t * params )
17641848{
17651849 struct xpay * xpay = xpay_of (cmd -> plugin );
17661850 const jsmntok_t * rpc_tok , * method_tok , * params_tok , * id_tok ,
1767- * bolt11 = NULL , * amount_msat = NULL , * maxfee = NULL ,
1851+ * bolt11 = NULL , * amount_msat = NULL ,
17681852 * partial_msat = NULL , * retry_for = NULL ;
1853+ const char * maxfee = NULL ;
17691854 struct json_stream * response ;
17701855
17711856 if (!xpay -> take_over_pay )
@@ -1795,7 +1880,7 @@ static struct command_result *handle_rpc_command(struct command *cmd,
17951880 if (params_tok -> size == 2 )
17961881 amount_msat = json_next (bolt11 );
17971882 } else if (params_tok -> type == JSMN_OBJECT ) {
1798- const jsmntok_t * t ;
1883+ const jsmntok_t * t , * maxfeepercent = NULL , * exemptfee = NULL ;
17991884 size_t i ;
18001885
18011886 json_for_each_obj (i , t , params_tok ) {
@@ -1806,9 +1891,13 @@ static struct command_result *handle_rpc_command(struct command *cmd,
18061891 else if (json_tok_streq (buf , t , "retry_for" ))
18071892 retry_for = t + 1 ;
18081893 else if (json_tok_streq (buf , t , "maxfee" ))
1809- maxfee = t + 1 ;
1894+ maxfee = json_strdup ( cmd , buf , t + 1 ) ;
18101895 else if (json_tok_streq (buf , t , "partial_msat" ))
18111896 partial_msat = t + 1 ;
1897+ else if (json_tok_streq (buf , t , "maxfeepercent" ))
1898+ maxfeepercent = t + 1 ;
1899+ else if (json_tok_streq (buf , t , "exemptfee" ))
1900+ exemptfee = t + 1 ;
18121901 else {
18131902 plugin_log (cmd -> plugin , LOG_INFORM ,
18141903 "Not redirecting pay (unknown arg %.*s)" ,
@@ -1822,6 +1911,14 @@ static struct command_result *handle_rpc_command(struct command *cmd,
18221911 "Not redirecting pay (missing bolt11 parameter)" );
18231912 goto dont_redirect ;
18241913 }
1914+ /* If this returns NULL, we let pay handle the weird case */
1915+ if (!calc_maxfee (cmd , & maxfee , buf ,
1916+ bolt11 , amount_msat ,
1917+ exemptfee , maxfeepercent )) {
1918+ plugin_log (cmd -> plugin , LOG_INFORM ,
1919+ "Not redirecting pay (weird maxfee params)" );
1920+ goto dont_redirect ;
1921+ }
18251922 } else {
18261923 plugin_log (cmd -> plugin , LOG_INFORM ,
18271924 "Not redirecting pay (unexpected params type)" );
@@ -1840,8 +1937,10 @@ static struct command_result *handle_rpc_command(struct command *cmd,
18401937 json_add_tok (response , "amount_msat" , amount_msat , buf );
18411938 if (retry_for )
18421939 json_add_tok (response , "retry_for" , retry_for , buf );
1940+ /* Even if this was a number token, handing it as a string is
1941+ * allowed by parse_msat */
18431942 if (maxfee )
1844- json_add_tok (response , "maxfee" , maxfee , buf );
1943+ json_add_string (response , "maxfee" , maxfee );
18451944 if (partial_msat )
18461945 json_add_tok (response , "partial_msat" , partial_msat , buf );
18471946 json_object_end (response );
0 commit comments