@@ -546,6 +546,11 @@ impl Simulation {
546546 }
547547
548548 for payment_flow in self . activity . iter ( ) {
549+ if payment_flow. amount_msat . value ( ) == 0 {
550+ return Err ( LightningError :: ValidationError (
551+ "We do not allow defined activity amount_msat with zero values" . to_string ( ) ,
552+ ) ) ;
553+ }
549554 // We need every source node that is configured to execute some activity to be included in our set of
550555 // nodes so that we can execute events on it.
551556 self . nodes
@@ -1423,10 +1428,18 @@ async fn track_payment_result(
14231428
14241429#[ cfg( test) ]
14251430mod tests {
1426- use crate :: { get_payment_delay, test_utils, MutRng , PaymentGenerationError , PaymentGenerator } ;
1431+ use crate :: {
1432+ get_payment_delay, test_utils, LightningError , LightningNode , MutRng , NodeInfo ,
1433+ PaymentGenerationError , PaymentGenerator , Simulation ,
1434+ } ;
1435+ use async_trait:: async_trait;
1436+ use bitcoin:: secp256k1:: PublicKey ;
14271437 use mockall:: mock;
1438+ use std:: collections:: HashMap ;
14281439 use std:: fmt;
1440+ use std:: sync:: Arc ;
14291441 use std:: time:: Duration ;
1442+ use tokio:: sync:: Mutex ;
14301443
14311444 #[ test]
14321445 fn create_seeded_mut_rng ( ) {
@@ -1469,6 +1482,27 @@ mod tests {
14691482 }
14701483 }
14711484
1485+ mock ! {
1486+ pub LightningNode { }
1487+ #[ async_trait]
1488+ impl crate :: LightningNode for LightningNode {
1489+ fn get_info( & self ) -> & NodeInfo ;
1490+ async fn get_network( & mut self ) -> Result <bitcoin:: Network , LightningError >;
1491+ async fn send_payment(
1492+ & mut self ,
1493+ dest: bitcoin:: secp256k1:: PublicKey ,
1494+ amount_msat: u64 ,
1495+ ) -> Result <lightning:: ln:: PaymentHash , LightningError >;
1496+ async fn track_payment(
1497+ & mut self ,
1498+ hash: & lightning:: ln:: PaymentHash ,
1499+ shutdown: triggered:: Listener ,
1500+ ) -> Result <crate :: PaymentResult , LightningError >;
1501+ async fn get_node_info( & mut self , node_id: & PublicKey ) -> Result <NodeInfo , LightningError >;
1502+ async fn list_channels( & mut self ) -> Result <Vec <u64 >, LightningError >;
1503+ }
1504+ }
1505+
14721506 #[ test]
14731507 fn test_no_payment_delay ( ) {
14741508 let node = test_utils:: create_nodes ( 1 , 100_000 )
@@ -1523,4 +1557,33 @@ mod tests {
15231557 payment_interval
15241558 ) ;
15251559 }
1560+
1561+ #[ tokio:: test]
1562+ async fn test_validate_zero_amount_no_valid ( ) {
1563+ let nodes = test_utils:: create_nodes ( 2 , 100_000 ) ;
1564+ let mut node_1 = nodes. first ( ) . unwrap ( ) . 0 . clone ( ) ;
1565+ let mut node_2 = nodes. get ( 1 ) . unwrap ( ) . 0 . clone ( ) ;
1566+ node_1. features . set_keysend_optional ( ) ;
1567+ node_2. features . set_keysend_optional ( ) ;
1568+
1569+ let mock_node_1 = MockLightningNode :: new ( ) ;
1570+ let mock_node_2 = MockLightningNode :: new ( ) ;
1571+ let mut clients: HashMap < PublicKey , Arc < Mutex < dyn LightningNode > > > = HashMap :: new ( ) ;
1572+ clients. insert ( node_1. pubkey , Arc :: new ( Mutex :: new ( mock_node_1) ) ) ;
1573+ clients. insert ( node_2. pubkey , Arc :: new ( Mutex :: new ( mock_node_2) ) ) ;
1574+ let activity_definition = crate :: ActivityDefinition {
1575+ source : node_1,
1576+ destination : node_2,
1577+ start_secs : None ,
1578+ count : None ,
1579+ interval_secs : crate :: ValueOrRange :: Value ( 0 ) ,
1580+ amount_msat : crate :: ValueOrRange :: Value ( 0 ) ,
1581+ } ;
1582+ let simulation = Simulation :: new (
1583+ crate :: SimulationCfg :: new ( Some ( 0 ) , 0 , 0.0 , None , None ) ,
1584+ clients,
1585+ vec ! [ activity_definition] ,
1586+ ) ;
1587+ assert ! ( simulation. validate_activity( ) . await . is_err( ) ) ;
1588+ }
15261589}
0 commit comments