1- use crate :: { hex_utils, types:: DynStore } ;
1+ use crate :: { hex_utils, rate_limiter :: RateLimiter , types:: DynStore } ;
22use bitcoin:: hashes:: { sha256, Hash } ;
33use lightning:: { offers:: static_invoice:: StaticInvoice , util:: ser:: Writeable } ;
4- use std:: sync:: Arc ;
4+ use std:: {
5+ sync:: { Arc , Mutex } ,
6+ time:: Duration ,
7+ } ;
58
69pub ( crate ) struct StaticInvoiceStore {
710 kv_store : Arc < DynStore > ,
11+ rate_limiter : Mutex < RateLimiter > ,
812}
913
1014impl StaticInvoiceStore {
1115 // Static invoices are stored at "static_invoices/<sha256(recipient_id)>/<invoice_slot>".
1216 //
1317 // Example:
14- // static_invoices/039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81/0000
18+ // static_invoices/039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81/001f
1519 const PRIMARY_NAMESPACE : & str = "static_invoices" ;
1620
1721 pub ( crate ) fn new ( kv_store : Arc < DynStore > ) -> Self {
18- Self { kv_store }
22+ Self { kv_store, rate_limiter : Mutex :: new ( RateLimiter :: new ( Duration :: from_millis ( 100 ) ) ) }
23+ }
24+
25+ fn check_rate_limit ( & self , recipient_id : & [ u8 ] ) -> Result < ( ) , lightning:: io:: Error > {
26+ let mut limiter = self . rate_limiter . lock ( ) . unwrap ( ) ;
27+ if !limiter. allow ( recipient_id) {
28+ Err ( lightning:: io:: Error :: new ( lightning:: io:: ErrorKind :: Other , "Rate limit exceeded" ) )
29+ } else {
30+ Ok ( ( ) )
31+ }
1932 }
2033
2134 pub ( crate ) async fn handle_static_invoice_requested (
2235 & self , recipient_id : Vec < u8 > , invoice_slot : u16 ,
2336 ) -> Result < Option < StaticInvoice > , lightning:: io:: Error > {
37+ self . check_rate_limit ( & recipient_id) ?;
38+
2439 let ( secondary_namespace, key) = Self :: get_storage_location ( invoice_slot, recipient_id) ;
2540
2641 self . kv_store . read ( Self :: PRIMARY_NAMESPACE , & secondary_namespace, & key) . and_then ( |data| {
@@ -36,6 +51,8 @@ impl StaticInvoiceStore {
3651 pub ( crate ) async fn handle_persist_static_invoice (
3752 & self , invoice : StaticInvoice , invoice_slot : u16 , recipient_id : Vec < u8 > ,
3853 ) -> Result < ( ) , lightning:: io:: Error > {
54+ self . check_rate_limit ( & recipient_id) ?;
55+
3956 let ( secondary_namespace, key) = Self :: get_storage_location ( invoice_slot, recipient_id) ;
4057
4158 let mut buf = Vec :: new ( ) ;
0 commit comments