11#include "config.h"
22#include <ccan/array_size/array_size.h>
3+ #include <ccan/bitmap/bitmap.h>
34#include <ccan/json_escape/json_escape.h>
45#include <ccan/rune/rune.h>
56#include <ccan/tal/str/str.h>
1920#include <lightningd/runes.h>
2021#include <wallet/wallet.h>
2122
23+ /* "640k should be enough for anybody!" */
24+ #define MAX_BLACKLIST_NUM 100000000
25+
2226static const u64 sec_per_nsec = 1000000000 ;
2327
2428struct cond_info {
@@ -36,7 +40,7 @@ struct runes {
3640 struct lightningd * ld ;
3741 struct rune * master ;
3842 u64 next_unique_id ;
39- struct rune_blacklist * blacklist ;
43+ BITMAP_DECLARE ( blist_bitmap , MAX_BLACKLIST_NUM ) ;
4044};
4145
4246enum invoice_field {
@@ -179,12 +183,41 @@ struct runes *runes_early_init(struct lightningd *ld)
179183 return runes ;
180184}
181185
186+ static void blacklist_to_bitmap (const struct rune_blacklist * blist ,
187+ bitmap * bitmap , size_t nbits )
188+ {
189+ bitmap_zero (bitmap , nbits );
190+ for (size_t i = 0 ; i < tal_count (blist ); i ++ ) {
191+ assert (blist [i ].end < nbits );
192+ bitmap_fill_range (bitmap , blist [i ].start , blist [i ].end + 1 );
193+ }
194+ }
195+
196+ static struct rune_blacklist * bitmap_to_blacklist (tal_t * ctx ,
197+ const bitmap * bitmap , size_t nbits )
198+ {
199+ struct rune_blacklist * blist = tal_arr (ctx , struct rune_blacklist , 0 );
200+ size_t i = 0 ;
201+
202+ while ((i = bitmap_ffs (bitmap , i , nbits )) != nbits ) {
203+ struct rune_blacklist b ;
204+ b .start = b .end = i ;
205+ while (b .end < nbits && bitmap_test_bit (bitmap , b .end + 1 ))
206+ b .end ++ ;
207+ tal_arr_expand (& blist , b );
208+ i = b .end + 1 ;
209+ }
210+ return blist ;
211+ }
212+
182213void runes_finish_init (struct runes * runes )
183214{
184215 struct lightningd * ld = runes -> ld ;
216+ struct rune_blacklist * blist ;
185217
186218 runes -> next_unique_id = wallet_get_rune_next_unique_id (runes , ld -> wallet );
187- runes -> blacklist = wallet_get_runes_blacklist (runes , ld -> wallet );
219+ blist = wallet_get_runes_blacklist (tmpctx , ld -> wallet );
220+ blacklist_to_bitmap (blist , runes -> blist_bitmap , MAX_BLACKLIST_NUM );
188221}
189222
190223struct rune_and_string {
@@ -301,12 +334,7 @@ static bool is_rune_blacklisted(const struct runes *runes, const struct rune *ru
301334 return false;
302335 }
303336 uid = rune_unique_id (rune );
304- for (size_t i = 0 ; i < tal_count (runes -> blacklist ); i ++ ) {
305- if (runes -> blacklist [i ].start <= uid && runes -> blacklist [i ].end >= uid ) {
306- return true;
307- }
308- }
309- return false;
337+ return uid < MAX_BLACKLIST_NUM && bitmap_test_bit (runes -> blist_bitmap , uid );
310338}
311339
312340static void join_strings (char * * base , const char * connector , char * append )
@@ -595,32 +623,16 @@ static const struct json_command invokerune_command = {
595623};
596624AUTODATA (json_command , & invokerune_command );
597625
598- static void blacklist_merge (struct rune_blacklist * blacklist ,
599- const struct rune_blacklist * entry )
600- {
601- if (entry -> start < blacklist -> start ) {
602- blacklist -> start = entry -> start ;
603- }
604- if (entry -> end > blacklist -> end ) {
605- blacklist -> end = entry -> end ;
606- }
607- }
608-
609- static bool blacklist_before (const struct rune_blacklist * first ,
610- const struct rune_blacklist * second )
611- {
612- // Is it before with a gap
613- return (first -> end + 1 ) < second -> start ;
614- }
615-
616- static struct command_result * list_blacklist (struct command * cmd )
626+ static struct command_result * list_blacklist (struct command * cmd ,
627+ const struct rune_blacklist * blist )
617628{
618629 struct json_stream * js = json_stream_success (cmd );
630+
619631 json_array_start (js , "blacklist" );
620- for (size_t i = 0 ; i < tal_count (cmd -> ld -> runes -> blacklist ); i ++ ) {
632+ for (size_t i = 0 ; i < tal_count (blist ); i ++ ) {
621633 json_object_start (js , NULL );
622- json_add_u64 (js , "start" , cmd -> ld -> runes -> blacklist [i ].start );
623- json_add_u64 (js , "end" , cmd -> ld -> runes -> blacklist [i ].end );
634+ json_add_u64 (js , "start" , blist [i ].start );
635+ json_add_u64 (js , "end" , blist [i ].end );
624636 json_object_end (js );
625637 }
626638 json_array_end (js );
@@ -633,7 +645,7 @@ static struct command_result *json_blacklistrune(struct command *cmd,
633645 const jsmntok_t * params )
634646{
635647 u64 * start , * end ;
636- struct rune_blacklist * entry , * newblacklist ;
648+ struct rune_blacklist * blist ;
637649
638650 if (!param_check (cmd , buffer , params ,
639651 p_opt ("start" , param_u64 , & start ), p_opt ("end" , param_u64 , & end ), NULL ))
@@ -643,53 +655,30 @@ static struct command_result *json_blacklistrune(struct command *cmd,
643655 return command_fail (cmd , JSONRPC2_INVALID_PARAMS , "Can not specify end without start" );
644656 }
645657
658+ if (!end ) {
659+ end = start ;
660+ }
661+
662+ if (* end >= MAX_BLACKLIST_NUM ) {
663+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS , "Cannot blacklist beyond %u" , MAX_BLACKLIST_NUM );
664+ }
665+
646666 if (command_check_only (cmd ))
647667 return command_check_done (cmd );
648668
649669 if (!start ) {
650- return list_blacklist (cmd );
670+ blist = bitmap_to_blacklist (cmd , cmd -> ld -> runes -> blist_bitmap , MAX_BLACKLIST_NUM );
671+ return list_blacklist (cmd , blist );
651672 }
652- if (!end ) {
653- end = start ;
654- }
655- entry = tal (cmd , struct rune_blacklist );
656- entry -> start = * start ;
657- entry -> end = * end ;
658673
659- newblacklist = tal_arr (cmd -> ld -> runes , struct rune_blacklist , 0 );
674+ /* Include end */
675+ bitmap_fill_range (cmd -> ld -> runes -> blist_bitmap , * start , (* end )+ 1 );
660676
661- for (size_t i = 0 ; i < tal_count (cmd -> ld -> runes -> blacklist ); i ++ ) {
662- /* if new entry if already merged just copy the old list */
663- if (entry == NULL ) {
664- tal_arr_expand (& newblacklist , cmd -> ld -> runes -> blacklist [i ]);
665- continue ;
666- }
667- /* old list has not reached the entry yet, so we are just copying it */
668- if (blacklist_before (& (cmd -> ld -> runes -> blacklist )[i ], entry )) {
669- tal_arr_expand (& newblacklist , cmd -> ld -> runes -> blacklist [i ]);
670- continue ;
671- }
672- /* old list has passed the entry, time to put the entry in */
673- if (blacklist_before (entry , & (cmd -> ld -> runes -> blacklist )[i ])) {
674- tal_arr_expand (& newblacklist , * entry );
675- tal_arr_expand (& newblacklist , cmd -> ld -> runes -> blacklist [i ]);
676- wallet_insert_blacklist (cmd -> ld -> wallet , entry );
677- // mark entry as copied
678- entry = NULL ;
679- continue ;
680- }
681- /* old list overlaps combined into the entry we are adding */
682- blacklist_merge (entry , & (cmd -> ld -> runes -> blacklist )[i ]);
683- wallet_delete_blacklist (cmd -> ld -> wallet , & (cmd -> ld -> runes -> blacklist )[i ]);
684- }
685- if (entry != NULL ) {
686- tal_arr_expand (& newblacklist , * entry );
687- wallet_insert_blacklist (cmd -> ld -> wallet , entry );
688- }
677+ /* Convert to list once, use for db and for list_blacklist */
678+ blist = bitmap_to_blacklist (cmd , cmd -> ld -> runes -> blist_bitmap , MAX_BLACKLIST_NUM );
679+ wallet_set_blacklist (cmd -> ld -> wallet , blist );
689680
690- tal_free (cmd -> ld -> runes -> blacklist );
691- cmd -> ld -> runes -> blacklist = newblacklist ;
692- return list_blacklist (cmd );
681+ return list_blacklist (cmd , blist );
693682}
694683
695684static const struct json_command blacklistrune_command = {
0 commit comments