@@ -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 } ,
@@ -1409,6 +1428,12 @@ fn build_with_store_internal(
14091428) -> Result < Node , BuildError > {
14101429 optionally_install_rustls_cryptoprovider ( ) ;
14111430
1431+ let configured_forwarded_payment_bucket_size_secs =
1432+ config. forwarded_payment_tracking_mode . bucket_size_secs ( ) . map_err ( |_| {
1433+ log_error ! ( logger, "Forwarded-payment bucket length is zero or too large" ) ;
1434+ BuildError :: InvalidForwardedPaymentBucketLength
1435+ } ) ?;
1436+
14121437 if let Err ( err) = may_announce_channel ( & config) {
14131438 if config. announcement_addresses . is_some ( ) {
14141439 log_error ! ( logger, "Announcement addresses were set but some required configuration options for node announcement are missing: {}" , err) ;
@@ -1440,24 +1465,72 @@ fn build_with_store_internal(
14401465
14411466 let kv_store_ref = Arc :: clone ( & kv_store) ;
14421467 let logger_ref = Arc :: clone ( & logger) ;
1443- let ( payment_store_res, node_metris_res, pending_payment_store_res) =
1444- runtime. block_on ( async move {
1445- tokio:: join!(
1446- read_all_objects(
1447- & * kv_store_ref,
1448- PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1449- PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1450- Arc :: clone( & logger_ref) ,
1451- ) ,
1452- read_node_metrics( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1453- read_all_objects(
1454- & * kv_store_ref,
1455- PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1456- PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1457- Arc :: clone( & logger_ref) ,
1458- )
1468+ let (
1469+ payment_store_res,
1470+ forwarded_payment_store_res,
1471+ channel_forwarding_stats_res,
1472+ channel_pair_forwarding_stats_res,
1473+ forwarded_payment_bucket_size_res,
1474+ node_metris_res,
1475+ pending_payment_store_res,
1476+ ) = runtime. block_on ( async move {
1477+ tokio:: join!(
1478+ read_all_objects(
1479+ & * kv_store_ref,
1480+ PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1481+ PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1482+ Arc :: clone( & logger_ref) ,
1483+ ) ,
1484+ read_all_objects(
1485+ & * kv_store_ref,
1486+ FORWARDED_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1487+ FORWARDED_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1488+ Arc :: clone( & logger_ref) ,
1489+ ) ,
1490+ read_all_objects(
1491+ & * kv_store_ref,
1492+ CHANNEL_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
1493+ CHANNEL_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
1494+ Arc :: clone( & logger_ref) ,
1495+ ) ,
1496+ read_all_objects(
1497+ & * kv_store_ref,
1498+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE ,
1499+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE ,
1500+ Arc :: clone( & logger_ref) ,
1501+ ) ,
1502+ read_forwarded_payment_bucket_size( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1503+ read_node_metrics( & * kv_store_ref, Arc :: clone( & logger_ref) ) ,
1504+ read_all_objects(
1505+ & * kv_store_ref,
1506+ PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE ,
1507+ PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
1508+ Arc :: clone( & logger_ref) ,
14591509 )
1460- } ) ;
1510+ )
1511+ } ) ;
1512+
1513+ let persisted_forwarded_payment_bucket_size_secs = match forwarded_payment_bucket_size_res {
1514+ Ok ( bucket_size_secs) => Some ( bucket_size_secs) ,
1515+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => None ,
1516+ Err ( e) => {
1517+ log_error ! ( logger, "Failed to read forwarded-payment bucket size: {}" , e) ;
1518+ return Err ( BuildError :: ReadFailed ) ;
1519+ } ,
1520+ } ;
1521+ let forwarded_payment_bucket_config = ResolvedForwardedPaymentBucketConfig :: resolve (
1522+ configured_forwarded_payment_bucket_size_secs,
1523+ persisted_forwarded_payment_bucket_size_secs,
1524+ )
1525+ . map_err ( |_| {
1526+ log_error ! (
1527+ logger,
1528+ "Configured forwarded-payment bucket size {:?} does not match persisted size {:?}" ,
1529+ configured_forwarded_payment_bucket_size_secs,
1530+ persisted_forwarded_payment_bucket_size_secs
1531+ ) ;
1532+ BuildError :: ForwardedPaymentBucketLengthMismatch
1533+ } ) ?;
14611534
14621535 // Initialize the status fields.
14631536 let node_metrics = match node_metris_res {
@@ -1486,6 +1559,48 @@ fn build_with_store_internal(
14861559 } ,
14871560 } ;
14881561
1562+ let forwarded_payment_store = match forwarded_payment_store_res {
1563+ Ok ( forwarded_payments) => Arc :: new ( ForwardedPaymentStore :: new (
1564+ forwarded_payments,
1565+ FORWARDED_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1566+ FORWARDED_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1567+ Arc :: clone ( & kv_store) ,
1568+ Arc :: clone ( & logger) ,
1569+ ) ) ,
1570+ Err ( e) => {
1571+ log_error ! ( logger, "Failed to read forwarded payment data from store: {}" , e) ;
1572+ return Err ( BuildError :: ReadFailed ) ;
1573+ } ,
1574+ } ;
1575+
1576+ let channel_forwarding_stats_store = match channel_forwarding_stats_res {
1577+ Ok ( stats) => Arc :: new ( ChannelForwardingStatsStore :: new (
1578+ stats,
1579+ CHANNEL_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1580+ CHANNEL_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1581+ Arc :: clone ( & kv_store) ,
1582+ Arc :: clone ( & logger) ,
1583+ ) ) ,
1584+ Err ( e) => {
1585+ log_error ! ( logger, "Failed to read channel forwarding stats from store: {}" , e) ;
1586+ return Err ( BuildError :: ReadFailed ) ;
1587+ } ,
1588+ } ;
1589+
1590+ let channel_pair_forwarding_stats_store = match channel_pair_forwarding_stats_res {
1591+ Ok ( stats) => Arc :: new ( ChannelPairForwardingStatsStore :: new (
1592+ stats,
1593+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_PRIMARY_NAMESPACE . to_string ( ) ,
1594+ CHANNEL_PAIR_FORWARDING_STATS_PERSISTENCE_SECONDARY_NAMESPACE . to_string ( ) ,
1595+ Arc :: clone ( & kv_store) ,
1596+ Arc :: clone ( & logger) ,
1597+ ) ) ,
1598+ Err ( e) => {
1599+ log_error ! ( logger, "Failed to read channel pair forwarding stats from store: {}" , e) ;
1600+ return Err ( BuildError :: ReadFailed ) ;
1601+ } ,
1602+ } ;
1603+
14891604 let ( chain_source, chain_tip_opt) = match chain_data_source_config {
14901605 Some ( ChainDataSourceConfig :: Esplora { server_url, headers, sync_config } ) => {
14911606 let sync_config = sync_config. unwrap_or ( EsploraSyncConfig :: default ( ) ) ;
@@ -2307,6 +2422,15 @@ fn build_with_store_internal(
23072422 } )
23082423 } ) ;
23092424
2425+ if let Some ( bucket_size_secs) = forwarded_payment_bucket_config. new_bucket_size_secs ( ) {
2426+ runtime
2427+ . block_on ( write_forwarded_payment_bucket_size ( & * kv_store, bucket_size_secs) )
2428+ . map_err ( |e| {
2429+ log_error ! ( logger, "Failed to persist forwarded-payment bucket size: {}" , e) ;
2430+ BuildError :: WriteFailed
2431+ } ) ?;
2432+ }
2433+
23102434 Ok ( Node {
23112435 runtime,
23122436 stop_sender,
@@ -2334,6 +2458,10 @@ fn build_with_store_internal(
23342458 scorer,
23352459 peer_store,
23362460 payment_store,
2461+ forwarded_payment_store,
2462+ channel_forwarding_stats_store,
2463+ channel_pair_forwarding_stats_store,
2464+ forwarded_payment_bucket_size_secs : forwarded_payment_bucket_config. bucket_size_secs ( ) ,
23372465 lnurl_auth,
23382466 is_running,
23392467 node_metrics,
0 commit comments