@@ -49,8 +49,9 @@ use crate::chain::ChainSource;
4949use crate :: config:: {
5050 default_user_config, may_announce_channel, AnnounceError , AsyncPaymentsRole ,
5151 BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , HRNResolverConfig ,
52- TorConfig , DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
53- DEFAULT_MAX_PROBE_AMOUNT_MSAT , DEFAULT_MIN_PROBE_AMOUNT_MSAT ,
52+ ResolvedForwardedPaymentBucketConfig , TorConfig , DEFAULT_ESPLORA_SERVER_URL ,
53+ DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL , DEFAULT_MAX_PROBE_AMOUNT_MSAT ,
54+ DEFAULT_MIN_PROBE_AMOUNT_MSAT ,
5455} ;
5556use crate :: connection:: ConnectionManager ;
5657use crate :: entropy:: NodeEntropy ;
@@ -60,12 +61,19 @@ use crate::gossip::GossipSource;
6061use crate :: io:: sqlite_store:: SqliteStore ;
6162use crate :: io:: utils:: {
6263 open_or_migrate_fs_store, read_all_objects, read_event_queue,
63- read_external_pathfinding_scores_from_cache, read_network_graph, read_node_metrics,
64- read_output_sweeper, read_peer_info, read_scorer,
64+ read_external_pathfinding_scores_from_cache, read_forwarded_payment_bucket_size,
65+ read_network_graph, read_node_metrics, read_output_sweeper, read_peer_info, read_scorer,
66+ write_forwarded_payment_bucket_size,
6567} ;
6668use crate :: io:: vss_store:: VssStoreBuilder ;
6769use crate :: io:: {
68- self , PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE , PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
70+ self , CHANNEL_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
71+ CHANNEL_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
72+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
73+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
74+ FORWARDED_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
75+ FORWARDED_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
76+ PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE , PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
6977 PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
7078 PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
7179} ;
@@ -82,7 +90,8 @@ use crate::probing::{
8290use crate :: runtime:: { Runtime , RuntimeSpawner } ;
8391use crate :: tx_broadcaster:: TransactionBroadcaster ;
8492use crate :: types:: {
85- AsyncPersister , ChainMonitor , ChannelManager , DynStore , DynStoreRef , DynStoreWrapper ,
93+ AsyncPersister , ChainMonitor , ChannelForwardingStatsStore , ChannelManager ,
94+ ChannelPairForwardingStatsStore , DynStore , DynStoreRef , DynStoreWrapper , ForwardedPaymentStore ,
8695 GossipSync , Graph , HRNResolver , KeysManager , MessageRouter , OnionMessenger , PaymentStore ,
8796 PeerManager , PendingPaymentStore ,
8897} ;
@@ -174,6 +183,10 @@ pub enum BuildError {
174183 InvalidTorProxyAddress ,
175184 /// The provided alias is invalid.
176185 InvalidNodeAlias ,
186+ /// The forwarded-payment bucket length is zero or too large to represent in seconds.
187+ InvalidForwardedPaymentBucketLength ,
188+ /// The forwarded-payment bucket length differs from the value previously persisted.
189+ ForwardedPaymentBucketLengthMismatch ,
177190 /// An attempt to setup a runtime has failed.
178191 RuntimeSetupFailed ,
179192 /// We failed to read data from the [`KVStore`].
@@ -236,6 +249,12 @@ impl fmt::Display for BuildError {
236249 Self :: LoggerSetupFailed => write ! ( f, "Failed to setup the logger." ) ,
237250 Self :: ChainSourceSetupFailed => write ! ( f, "Failed to setup the chain source." ) ,
238251 Self :: InvalidNodeAlias => write ! ( f, "Given node alias is invalid." ) ,
252+ Self :: InvalidForwardedPaymentBucketLength => {
253+ write ! ( f, "Forwarded-payment bucket length is invalid." )
254+ } ,
255+ Self :: ForwardedPaymentBucketLengthMismatch => {
256+ write ! ( f, "Forwarded-payment bucket length does not match persisted data." )
257+ } ,
239258 Self :: NetworkMismatch => {
240259 write ! ( f, "Given network does not match the node's previously configured network." )
241260 } ,
@@ -1408,6 +1427,12 @@ fn build_with_store_internal(
14081427) -> Result < Node , BuildError > {
14091428 optionally_install_rustls_cryptoprovider ( ) ;
14101429
1430+ let configured_forwarded_payment_bucket_size_secs =
1431+ config. forwarded_payment_tracking_mode . bucket_size_secs ( ) . map_err ( |_| {
1432+ log_error ! ( logger, "Forwarded-payment bucket length is zero or too large" ) ;
1433+ BuildError :: InvalidForwardedPaymentBucketLength
1434+ } ) ?;
1435+
14111436 if let Err ( err) = may_announce_channel ( & config) {
14121437 if config. announcement_addresses . is_some ( ) {
14131438 log_error ! ( logger, "Announcement addresses were set but some required configuration options for node announcement are missing: {}" , err) ;
@@ -1439,24 +1464,72 @@ fn build_with_store_internal(
14391464
14401465 let kv_store_ref = Arc :: clone ( & kv_store) ;
14411466 let logger_ref = Arc :: clone ( & logger) ;
1442- let ( payment_store_res, node_metris_res, pending_payment_store_res) =
1443- runtime. block_on ( async move {
1444- tokio:: join!(
1445- read_all_objects(
1446- & * kv_store_ref,
1447- PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1448- PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1449- Arc :: clone( & logger_ref) ,
1450- ) ,
1451- read_node_metrics( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1452- read_all_objects(
1453- & * kv_store_ref,
1454- PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1455- PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1456- Arc :: clone( & logger_ref) ,
1457- )
1467+ let (
1468+ payment_store_res,
1469+ forwarded_payment_store_res,
1470+ channel_forwarding_stats_res,
1471+ channel_pair_forwarding_stats_res,
1472+ forwarded_payment_bucket_size_res,
1473+ node_metris_res,
1474+ pending_payment_store_res,
1475+ ) = runtime. block_on ( async move {
1476+ tokio:: join!(
1477+ read_all_objects(
1478+ & * kv_store_ref,
1479+ PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1480+ PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1481+ Arc :: clone( & logger_ref) ,
1482+ ) ,
1483+ read_all_objects(
1484+ & * kv_store_ref,
1485+ FORWARDED_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1486+ FORWARDED_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1487+ Arc :: clone( & logger_ref) ,
1488+ ) ,
1489+ read_all_objects(
1490+ & * kv_store_ref,
1491+ CHANNEL_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
1492+ CHANNEL_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
1493+ Arc :: clone( & logger_ref) ,
1494+ ) ,
1495+ read_all_objects(
1496+ & * kv_store_ref,
1497+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
1498+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
1499+ Arc :: clone( & logger_ref) ,
1500+ ) ,
1501+ read_forwarded_payment_bucket_size( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1502+ read_node_metrics( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1503+ read_all_objects(
1504+ & * kv_store_ref,
1505+ PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1506+ PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1507+ Arc :: clone( & logger_ref) ,
14581508 )
1459- } ) ;
1509+ )
1510+ } ) ;
1511+
1512+ let persisted_forwarded_payment_bucket_size_secs = match forwarded_payment_bucket_size_res {
1513+ Ok ( bucket_size_secs) => Some ( bucket_size_secs) ,
1514+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => None ,
1515+ Err ( e) => {
1516+ log_error ! ( logger, "Failed to read forwarded-payment bucket size: {}" , e) ;
1517+ return Err ( BuildError :: ReadFailed ) ;
1518+ } ,
1519+ } ;
1520+ let forwarded_payment_bucket_config = ResolvedForwardedPaymentBucketConfig :: resolve (
1521+ configured_forwarded_payment_bucket_size_secs,
1522+ persisted_forwarded_payment_bucket_size_secs,
1523+ )
1524+ . map_err ( |_| {
1525+ log_error ! (
1526+ logger,
1527+ "Configured forwarded-payment bucket size {:?} does not match persisted size {:?}" ,
1528+ configured_forwarded_payment_bucket_size_secs,
1529+ persisted_forwarded_payment_bucket_size_secs
1530+ ) ;
1531+ BuildError :: ForwardedPaymentBucketLengthMismatch
1532+ } ) ?;
14601533
14611534 // Initialize the status fields.
14621535 let node_metrics = match node_metris_res {
@@ -1485,6 +1558,48 @@ fn build_with_store_internal(
14851558 } ,
14861559 } ;
14871560
1561+ let forwarded_payment_store = match forwarded_payment_store_res {
1562+ Ok ( forwarded_payments) => Arc :: new ( ForwardedPaymentStore :: new (
1563+ forwarded_payments,
1564+ FORWARDED_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1565+ FORWARDED_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1566+ Arc :: clone ( & kv_store) ,
1567+ Arc :: clone ( & logger) ,
1568+ ) ) ,
1569+ Err ( e) => {
1570+ log_error ! ( logger, "Failed to read forwarded payment data from store: {}" , e) ;
1571+ return Err ( BuildError :: ReadFailed ) ;
1572+ } ,
1573+ } ;
1574+
1575+ let channel_forwarding_stats_store = match channel_forwarding_stats_res {
1576+ Ok ( stats) => Arc :: new ( ChannelForwardingStatsStore :: new (
1577+ stats,
1578+ CHANNEL_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1579+ CHANNEL_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1580+ Arc :: clone ( & kv_store) ,
1581+ Arc :: clone ( & logger) ,
1582+ ) ) ,
1583+ Err ( e) => {
1584+ log_error ! ( logger, "Failed to read channel forwarding stats from store: {}" , e) ;
1585+ return Err ( BuildError :: ReadFailed ) ;
1586+ } ,
1587+ } ;
1588+
1589+ let channel_pair_forwarding_stats_store = match channel_pair_forwarding_stats_res {
1590+ Ok ( stats) => Arc :: new ( ChannelPairForwardingStatsStore :: new (
1591+ stats,
1592+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1593+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1594+ Arc :: clone ( & kv_store) ,
1595+ Arc :: clone ( & logger) ,
1596+ ) ) ,
1597+ Err ( e) => {
1598+ log_error ! ( logger, "Failed to read channel pair forwarding stats from store: {}" , e) ;
1599+ return Err ( BuildError :: ReadFailed ) ;
1600+ } ,
1601+ } ;
1602+
14881603 let ( chain_source, chain_tip_opt) = match chain_data_source_config {
14891604 Some ( ChainDataSourceConfig :: Esplora { server_url, headers, sync_config } ) => {
14901605 let sync_config = sync_config. unwrap_or ( EsploraSyncConfig :: default ( ) ) ;
@@ -2306,6 +2421,15 @@ fn build_with_store_internal(
23062421 } )
23072422 } ) ;
23082423
2424+ if let Some ( bucket_size_secs) = forwarded_payment_bucket_config. new_bucket_size_secs ( ) {
2425+ runtime
2426+ . block_on ( write_forwarded_payment_bucket_size ( & * kv_store, bucket_size_secs) )
2427+ . map_err ( |e| {
2428+ log_error ! ( logger, "Failed to persist forwarded-payment bucket size: {}" , e) ;
2429+ BuildError :: WriteFailed
2430+ } ) ?;
2431+ }
2432+
23092433 Ok ( Node {
23102434 runtime,
23112435 stop_sender,
@@ -2333,6 +2457,10 @@ fn build_with_store_internal(
23332457 scorer,
23342458 peer_store,
23352459 payment_store,
2460+ forwarded_payment_store,
2461+ channel_forwarding_stats_store,
2462+ channel_pair_forwarding_stats_store,
2463+ forwarded_payment_bucket_size_secs : forwarded_payment_bucket_config. bucket_size_secs ( ) ,
23362464 lnurl_auth,
23372465 is_running,
23382466 node_metrics,
0 commit comments