@@ -67,6 +67,9 @@ struct chanbackup {
6767 /* Global secret object to keep the derived encryption key for the SCB */
6868 struct secret secret ;
6969
70+ /* We store the timestamp of the latest peer storage that we have. */
71+ u32 latest_timestamp ;
72+
7073 /* Cache of backups for each peer we know about */
7174 struct backup_map * backups ;
7275
@@ -819,14 +822,49 @@ static struct command_result *datastore_failed(struct command *cmd,
819822 return command_hook_success (cmd );
820823}
821824
825+ /* Compares the data between the stored scb and latest recvd scb,
826+ * stores the most recent one only. */
827+ static struct command_result * store_latest_scb (struct command * cmd ,
828+ struct chanbackup * cb ,
829+ const u8 * received_scb )
830+ {
831+ size_t recvd_scb_len = tal_bytelen (received_scb );
832+ u64 version ;
833+ struct modern_scb_chan * * scb_tlvs ;
834+ u32 timestamp_new ;
835+ bool is_converted ;
836+
837+ if (!read_static_chan_backup (cmd , received_scb , & version , & timestamp_new , & scb_tlvs , & is_converted )) {
838+ plugin_log (cmd -> plugin , LOG_BROKEN , "Ignoring invalid peer storage: %s" ,
839+ tal_hex (tmpctx , received_scb ));
840+ return command_hook_success (cmd );
841+ }
842+
843+ if (timestamp_new < cb -> latest_timestamp ) {
844+ plugin_log (cmd -> plugin , LOG_DBG , "Ignoring old Peer Storage" );
845+ return command_hook_success (cmd );
846+ }
847+
848+ cb -> latest_timestamp = timestamp_new ;
849+
850+ return jsonrpc_set_datastore_binary (cmd ,
851+ mkdatastorekey (tmpctx , "chanbackup" , "latestscb" ),
852+ received_scb , recvd_scb_len ,
853+ "create-or-replace" ,
854+ datastore_success ,
855+ datastore_failed ,
856+ "Saving latestscb" );
857+
858+ }
859+
822860static struct command_result * handle_your_peer_storage (struct command * cmd ,
823861 const char * buf ,
824862 const jsmntok_t * params )
825863{
826864 struct node_id node_id ;
827865 u8 * payload , * payload_deserialise ;
828866 const char * err ;
829- const struct chanbackup * cb = chanbackup (cmd -> plugin );
867+ struct chanbackup * cb = chanbackup (cmd -> plugin );
830868
831869 err = json_scan (cmd , buf , params ,
832870 "{payload:%,peer_id:%}" ,
@@ -906,16 +944,7 @@ static struct command_result *handle_your_peer_storage(struct command *cmd,
906944 NULL , 0 ) != 0 )
907945 return failed_peer_restore (cmd , & node_id ,
908946 "Peer altered our data" );
909-
910-
911- return jsonrpc_set_datastore_binary (cmd ,
912- mkdatastorekey (tmpctx , "chanbackup" , "latestscb" ),
913- decoded_bkp ,
914- tal_bytelen (decoded_bkp ),
915- "create-or-replace" ,
916- datastore_success ,
917- datastore_failed ,
918- "Saving latestscb" );
947+ return store_latest_scb (cmd , cb , decoded_bkp );
919948 } else {
920949 /* Any other message we ignore */
921950 return command_hook_success (cmd );
@@ -1092,6 +1121,7 @@ static const char *init(struct command *init_cmd,
10921121 const char * info = "scb secret" ;
10931122 u8 * info_hex = tal_dup_arr (tmpctx , u8 , (u8 * )info , strlen (info ), 0 );
10941123 u8 * features ;
1124+ u8 * latestscb ;
10951125
10961126 /* Figure out if they specified --experimental-peer-storage */
10971127 rpc_scan (init_cmd , "getinfo" ,
@@ -1115,6 +1145,18 @@ static const char *init(struct command *init_cmd,
11151145 tal_bytelen (info_hex )))),
11161146 "{secret:%}" , JSON_SCAN (json_to_secret , & cb -> secret ));
11171147
1148+ /* Caching timestamp of latestscb that we have stored. This
1149+ * would be useful for upgrading `chanbackup/latestscb`. */
1150+ cb -> latest_timestamp = 0 ;
1151+ if (rpc_scan_datastore_hex (tmpctx , init_cmd ,
1152+ mkdatastorekey (tmpctx , "chanbackup" , "latestscb" ),
1153+ JSON_SCAN_TAL (tmpctx , json_tok_bin_from_hex , & latestscb )) == NULL ) {
1154+ u64 version ;
1155+ struct modern_scb_chan * * scb_tlvs ;
1156+ bool is_converted ;
1157+ read_static_chan_backup (init_cmd , latestscb , & version , & cb -> latest_timestamp , & scb_tlvs , & is_converted );
1158+ }
1159+
11181160 setup_backup_map (init_cmd , cb );
11191161 plugin_set_data (init_cmd -> plugin , cb );
11201162 plugin_log (init_cmd -> plugin , LOG_DBG , "Chanbackup Initialised!" );
0 commit comments