@@ -473,3 +473,51 @@ def test_xpay_preapprove(node_factory):
473473
474474 with pytest .raises (RpcError , match = r"invoice was declined" ):
475475 l1 .rpc .xpay (inv )
476+
477+
478+ @pytest .mark .xfail (strict = True )
479+ def test_xpay_maxfee (node_factory , bitcoind , chainparams ):
480+ """Test which shows that we don't excees maxfee"""
481+ outfile = tempfile .NamedTemporaryFile (prefix = 'gossip-store-' )
482+ subprocess .check_output (['devtools/gossmap-compress' ,
483+ 'decompress' ,
484+ '--node-map=3301=022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59' ,
485+ 'tests/data/gossip-store-2024-09-22.compressed' ,
486+ outfile .name ]).decode ('utf-8' ).splitlines ()
487+ AMOUNT = 100_000_000
488+
489+ # l2 will warn l1 about its invalid gossip: ignore.
490+ # We throttle l1's gossip to avoid massive log spam.
491+ l1 , l2 = node_factory .line_graph (2 ,
492+ # This is in sats, so 1000x amount we send.
493+ fundamount = AMOUNT ,
494+ opts = [{'gossip_store_file' : outfile .name ,
495+ 'subdaemon' : 'channeld:../tests/plugins/channeld_fakenet' ,
496+ 'allow_warning' : True ,
497+ 'dev-throttle-gossip' : None },
498+ {'allow_bad_gossip' : True }])
499+
500+ # l1 needs to know l2's shaseed for the channel so it can make revocations
501+ hsmfile = os .path .join (l2 .daemon .lightning_dir , TEST_NETWORK , "hsm_secret" )
502+ # Needs peer node id and channel dbid (1, it's the first channel), prints out:
503+ # "shaseed: xxxxxxx\n"
504+ shaseed = subprocess .check_output (["tools/hsmtool" , "dumpcommitments" , l1 .info ['id' ], "1" , "0" , hsmfile ]).decode ('utf-8' ).strip ().partition (": " )[2 ]
505+ l1 .rpc .dev_peer_shachain (l2 .info ['id' ], shaseed )
506+
507+ # This one triggers the bug!
508+ n = 59
509+ maxfee = 57966
510+ preimage_hex = bytes ([n + 100 ]).hex () + '00' * 31
511+ hash_hex = sha256 (bytes .fromhex (preimage_hex )).hexdigest ()
512+ inv = subprocess .check_output (["devtools/bolt11-cli" ,
513+ "encode" ,
514+ n .to_bytes (length = 8 , byteorder = sys .byteorder ).hex () + '01' * 24 ,
515+ f"currency={ chainparams ['bip173_prefix' ]} " ,
516+ f"p={ hash_hex } " ,
517+ f"s={ '00' * 32 } " ,
518+ f"d=Paying node { n } with maxfee" ,
519+ f"amount={ AMOUNT } msat" ]).decode ('utf-8' ).strip ()
520+
521+ ret = l1 .rpc .xpay (invstring = inv , maxfee = maxfee )
522+ fee = ret ['amount_sent_msat' ] - ret ['amount_msat' ]
523+ assert fee <= maxfee
0 commit comments