1010
1111pub ( crate ) mod logging;
1212
13+ use electrsd:: corepc_client:: client_sync:: Auth ;
1314use logging:: TestLogWriter ;
1415
16+ use ldk_node:: bitcoin:: secp256k1:: PublicKey ;
1517use ldk_node:: config:: { Config , ElectrumSyncConfig , EsploraSyncConfig } ;
1618use ldk_node:: io:: sqlite_store:: SqliteStore ;
1719use ldk_node:: payment:: { PaymentDirection , PaymentKind , PaymentStatus } ;
1820use ldk_node:: {
1921 Builder , CustomTlvRecord , Event , LightningBalance , Node , NodeError , PendingSweepBalance ,
22+ UserChannelId ,
2023} ;
2124
2225use lightning:: ln:: msgs:: SocketAddress ;
2326use lightning:: routing:: gossip:: NodeAlias ;
2427use lightning:: util:: persist:: KVStore ;
2528use lightning:: util:: test_utils:: TestStore ;
2629
27- use lightning_invoice:: { Bolt11InvoiceDescription , Description } ;
30+ use lightning_invoice:: { Bolt11Invoice , Bolt11InvoiceDescription , Description } ;
2831use lightning_types:: payment:: { PaymentHash , PaymentPreimage } ;
2932
3033use lightning_persister:: fs_store:: FilesystemStore ;
@@ -38,6 +41,7 @@ use bitcoin::{
3841use electrsd:: corepc_node:: Client as BitcoindClient ;
3942use electrsd:: corepc_node:: Node as BitcoinD ;
4043use electrsd:: { corepc_node, ElectrsD } ;
44+ use electrum_client:: Client as ElectrumClient ;
4145use electrum_client:: ElectrumApi ;
4246
4347use rand:: distributions:: Alphanumeric ;
@@ -47,6 +51,7 @@ use serde_json::{json, Value};
4751use std:: collections:: { HashMap , HashSet } ;
4852use std:: env;
4953use std:: path:: PathBuf ;
54+ use std:: str:: FromStr ;
5055use std:: sync:: { Arc , RwLock } ;
5156use std:: time:: Duration ;
5257
@@ -1324,3 +1329,144 @@ impl KVStore for TestSyncStore {
13241329 self . do_list ( primary_namespace, secondary_namespace)
13251330 }
13261331}
1332+
1333+ pub trait ExternalLightningNode {
1334+ fn get_node_info ( & mut self ) -> ( PublicKey , SocketAddress ) ;
1335+ fn create_invoice ( & mut self , amount_msat : u64 , description : String ) -> String ;
1336+ fn pay_invoice ( & mut self , invoice : & str ) ;
1337+ fn check_receive_payment ( & mut self , quantity_invoices : usize ) ;
1338+ fn description_invoice ( & mut self ) -> String {
1339+ "externalNodeTest" . to_string ( )
1340+ }
1341+ /// only needed for implementations that require a short delay to update routes/balances after receiving funds (e.g. LND).
1342+ fn can_send_payment ( & mut self , _: String , _: u64 ) -> bool {
1343+ // Default implementation, can be overridden
1344+ true
1345+ }
1346+ }
1347+
1348+ fn init_setup_test_external_node ( ) -> ( Node , BitcoindClient , ElectrumClient ) {
1349+ // Setup bitcoind / electrs clients
1350+ let bitcoind_client = BitcoindClient :: new_with_auth (
1351+ "http://127.0.0.1:18443" ,
1352+ Auth :: UserPass ( "user" . to_string ( ) , "pass" . to_string ( ) ) ,
1353+ )
1354+ . unwrap ( ) ;
1355+ let electrs_client = ElectrumClient :: new ( "tcp://127.0.0.1:50001" ) . unwrap ( ) ;
1356+
1357+ // Give electrs a kick.
1358+ generate_blocks_and_wait ( & bitcoind_client, & electrs_client, 1 ) ;
1359+
1360+ // Setup LDK Node
1361+ let config = random_config ( true ) ;
1362+ let mut builder = Builder :: from_config ( config. node_config ) ;
1363+ builder. set_chain_source_esplora ( "http://127.0.0.1:3002" . to_string ( ) , None ) ;
1364+
1365+ let node = builder. build ( ) . unwrap ( ) ;
1366+ node. start ( ) . unwrap ( ) ;
1367+
1368+ // Premine some funds and distribute
1369+ let address = node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
1370+ let premine_amount = Amount :: from_sat ( 5_000_000 ) ;
1371+ premine_and_distribute_funds ( & bitcoind_client, & electrs_client, vec ! [ address] , premine_amount) ;
1372+
1373+ ( node, bitcoind_client, electrs_client)
1374+ }
1375+
1376+ fn open_channel_by_node_id < E : ElectrumApi > (
1377+ bitcoind : & BitcoindClient , electrs : & E , node : & Node , external_node_id : PublicKey ,
1378+ external_node_address : SocketAddress , funding_amount_sat : u64 , push_msat : Option < u64 > ,
1379+ ) -> UserChannelId {
1380+ node. sync_wallets ( ) . unwrap ( ) ;
1381+
1382+ // Open the channel
1383+ node. open_announced_channel (
1384+ external_node_id,
1385+ external_node_address,
1386+ funding_amount_sat,
1387+ push_msat,
1388+ None ,
1389+ )
1390+ . unwrap ( ) ;
1391+
1392+ let funding_txo = expect_channel_pending_event ! ( node, external_node_id) ;
1393+ wait_for_tx ( electrs, funding_txo. txid ) ;
1394+ generate_blocks_and_wait ( bitcoind, electrs, 6 ) ;
1395+ node. sync_wallets ( ) . unwrap ( ) ;
1396+ let user_channel_id = expect_channel_ready_event ! ( node, external_node_id) ;
1397+ user_channel_id
1398+ }
1399+
1400+ fn ldk_send_payment_to_external_node < E : ExternalLightningNode > (
1401+ node : & Node , external_node : & mut E , amount_msat : u64 ,
1402+ ) {
1403+ let description = external_node. description_invoice ( ) ;
1404+ let invoice_string = external_node. create_invoice ( amount_msat, description) ;
1405+ let invoice = Bolt11Invoice :: from_str ( & invoice_string) . unwrap ( ) ;
1406+ node. bolt11_payment ( ) . send ( & invoice, None ) . unwrap ( ) ;
1407+ }
1408+
1409+ fn ldk_check_send_payment_succeeds < E : ExternalLightningNode > (
1410+ node : & Node , external_node : & mut E , quantity_invoices : usize ,
1411+ ) {
1412+ expect_event ! ( node, PaymentSuccessful ) ;
1413+ external_node. check_receive_payment ( quantity_invoices)
1414+ }
1415+
1416+ fn ldk_receive_payment_from_external_node < E : ExternalLightningNode > (
1417+ node : & Node , external_node : & mut E , amount_msat : u64 ,
1418+ ) {
1419+ let description = external_node. description_invoice ( ) ;
1420+ let invoice_description =
1421+ Bolt11InvoiceDescription :: Direct ( Description :: new ( description) . unwrap ( ) ) ;
1422+ let ldk_invoice =
1423+ node. bolt11_payment ( ) . receive ( amount_msat, & invoice_description, 3600 ) . unwrap ( ) ;
1424+ external_node. pay_invoice ( & ldk_invoice. to_string ( ) ) ;
1425+
1426+ expect_event ! ( node, PaymentReceived ) ;
1427+ }
1428+
1429+ pub ( crate ) fn do_ldk_opens_channel_with_external_node < E : ExternalLightningNode > (
1430+ external_node : & mut E ,
1431+ ) {
1432+ // Initialize LDK node and clients
1433+ let ( node, bitcoind_client, electrs_client) = init_setup_test_external_node ( ) ;
1434+
1435+ // setup external node info
1436+ let ( external_node_id, external_node_address) = external_node. get_node_info ( ) ;
1437+
1438+ println ! (
1439+ "Opening channel with external node: {} at {}" ,
1440+ external_node_id, external_node_address
1441+ ) ;
1442+ // Open the channel
1443+ let funding_amount_sat = 2_000_000 ;
1444+ let push_msat = Some ( 500_000_000 ) ;
1445+ let user_channel_id = open_channel_by_node_id (
1446+ & bitcoind_client,
1447+ & electrs_client,
1448+ & node,
1449+ external_node_id,
1450+ external_node_address,
1451+ funding_amount_sat,
1452+ push_msat,
1453+ ) ;
1454+
1455+ println ! ( "Sending payment to external node" ) ;
1456+ // Send a payment to the external node
1457+ let invoice_amount_sat = 100_000_000 ;
1458+ ldk_send_payment_to_external_node ( & node, external_node, invoice_amount_sat) ;
1459+ ldk_check_send_payment_succeeds ( & node, external_node, 1 ) ;
1460+
1461+ println ! ( "Sending payment to ldk" ) ;
1462+ // Send a payment to LDK
1463+ let amount_msat = 9_000_000 ;
1464+ assert ! ( external_node. can_send_payment( node. node_id( ) . to_string( ) , amount_msat) ) ;
1465+ ldk_receive_payment_from_external_node ( & node, external_node, amount_msat) ;
1466+
1467+ println ! ( "Closing channel with external node" ) ;
1468+ // Close the channel
1469+ node. close_channel ( & user_channel_id, external_node_id) . unwrap ( ) ;
1470+ expect_event ! ( node, ChannelClosed ) ;
1471+ node. stop ( ) . unwrap ( ) ;
1472+ }
0 commit comments