sync

Backup service to store encrypted wallet databases (experimental)
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_block_delete.c (10718B)


      1 /*
      2   This file is part of SYNC
      3   Copyright (C) 2014-2026 Taler Systems SA
      4 
      5   SYNC is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 3, or
      8   (at your option) any later version.
      9 
     10   SYNC is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with SYNC; see the file COPYING.  If not, see
     17   <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file testing/testing_api_cmd_block_delete.c
     21  * @brief command to delete a block from the sync backend service.
     22  * @author Iván Ávalos
     23  */
     24 #include "platform.h"
     25 #include "sync/sync_service.h"
     26 #include "sync/sync_testing_lib.h"
     27 #include <taler/taler_util.h>
     28 #include <taler/taler_signatures.h>
     29 #include <taler/taler_testing_lib.h>
     30 #include <gnunet/gnunet_curl_lib.h>
     31 #include "testing_api_cmd_block_common.h"
     32 
     33 
     34 /**
     35  * State for a "block delete" CMD.
     36  */
     37 struct BlockDeleteState
     38 {
     39 
     40   /**
     41    * URL of the sync backend.
     42    */
     43   const char *sync_url;
     44 
     45   /**
     46    * Reference to a command that provides account keys,
     47    * block nonce and block hash.
     48    */
     49   const char *account_reference;
     50 
     51   /**
     52    * Eddsa private key.
     53    */
     54   struct SYNC_AccountPrivateKeyP sync_priv;
     55 
     56   /**
     57    * Eddsa public key.
     58    */
     59   struct SYNC_AccountPublicKeyP sync_pub;
     60 
     61   /**
     62    * Nonce of the block to delete.
     63    */
     64   struct SYNC_BlockNonce nonce;
     65 
     66   /**
     67    * Prev nonce (zero if first block).
     68    */
     69   struct SYNC_BlockNonce prev_nonce;
     70 
     71   /**
     72    * Next nonce (zero if last block).
     73    */
     74   struct SYNC_BlockNonce next_nonce;
     75 
     76   /**
     77    * Hash of the block to delete.
     78    */
     79   struct GNUNET_HashCode block_hash;
     80 
     81   /**
     82    * Expected HTTP status code.
     83    */
     84   unsigned int http_status;
     85 
     86   /**
     87    * The interpreter state.
     88    */
     89   struct TALER_TESTING_Interpreter *is;
     90 
     91   /**
     92    * Handle for the library block delete operation.
     93    */
     94   struct SYNC_BlockOperation *bop;
     95 
     96   /**
     97    * Handle for the library block list operation (first phase).
     98    */
     99   struct SYNC_BlockListOperation *blop;
    100 
    101   /**
    102    * Number of entries in @e object_uids and @e object_incs.
    103    */
    104   unsigned int refs_len;
    105 
    106   /**
    107    * Array of object UIDs referenced by this block (array of
    108    * @e refs_len, up to #MAX_BLOCK_OBJECT_REFS).
    109    */
    110   struct SYNC_ObjectUID object_uids[MAX_BLOCK_OBJECT_REFS];
    111 
    112   /**
    113    * Array of reference count adjustments (array of @e refs_len,
    114    * up to #MAX_BLOCK_OBJECT_REFS).
    115    */
    116   int16_t object_incs[MAX_BLOCK_OBJECT_REFS];
    117 
    118   /**
    119    * Entry of the preceding neighbour (for its relink signature).
    120    */
    121   struct SYNC_BlockListEntry prev_entry;
    122 
    123   /**
    124    * True if @e prev_entry is set.
    125    */
    126   bool have_prev_entry;
    127 
    128   /**
    129    * Entry of the succeeding neighbour (for its relink signature).
    130    */
    131   struct SYNC_BlockListEntry next_entry;
    132 
    133   /**
    134    * True if @e next_entry is set.
    135    */
    136   bool have_next_entry;
    137 
    138 };
    139 
    140 
    141 /**
    142  * Function called when we're done processing the
    143  * block delete.
    144  *
    145  * @param cls the `struct BlockDeleteState`
    146  * @param ud details about the delete operation
    147  */
    148 static void
    149 block_delete_finished (void *cls,
    150                        const struct SYNC_BlockOperationDetails *ud)
    151 {
    152   struct BlockDeleteState *bds = cls;
    153 
    154   bds->bop = NULL;
    155   if (ud->http_status != bds->http_status)
    156   {
    157     TALER_TESTING_unexpected_status (bds->is,
    158                                      ud->http_status,
    159                                      bds->http_status);
    160     return;
    161   }
    162   TALER_TESTING_interpreter_next (bds->is);
    163 }
    164 
    165 
    166 /**
    167  * Function called when we're done processing the
    168  * block list that precedes the delete.
    169  *
    170  * @param cls the `struct BlockDeleteState`
    171  * @param ld details about the list operation
    172  */
    173 static void
    174 block_delete_list_finished (void *cls,
    175                             const struct SYNC_BlockListDetails *ld)
    176 {
    177   struct BlockDeleteState *bds = cls;
    178 
    179   bds->blop = NULL;
    180   if (MHD_HTTP_OK != ld->http_status)
    181   {
    182     GNUNET_break_op (0);
    183     TALER_TESTING_interpreter_fail (bds->is);
    184     return;
    185   }
    186 
    187   /* Find the block to delete and its neighbours in the list */
    188   {
    189     const struct SYNC_BlockListEntry *prev = NULL;
    190     const struct SYNC_BlockListEntry *next = NULL;
    191 
    192     for (unsigned int i = 0; i < ld->num_entries; i++)
    193     {
    194       const struct SYNC_BlockListEntry *e = &ld->entries[i];
    195 
    196       if ( (0 == GNUNET_memcmp (&e->nonce,
    197                                 &bds->prev_nonce)) ||
    198            (0 == GNUNET_memcmp (&e->nonce,
    199                                 &bds->next_nonce)) )
    200       {
    201         if (0 == GNUNET_memcmp (&e->nonce,
    202                                 &bds->prev_nonce))
    203           prev = e;
    204         else
    205           next = e;
    206       }
    207     }
    208 
    209     if (NULL != prev)
    210     {
    211       bds->prev_entry = *prev;
    212       bds->have_prev_entry = true;
    213     }
    214     if (NULL != next)
    215     {
    216       bds->next_entry = *next;
    217       bds->have_next_entry = true;
    218     }
    219   }
    220 
    221   {
    222     struct SYNC_BlockOperationArgs args = {
    223       .nonce = &bds->nonce,
    224       .prev_nonce = GNUNET_is_zero (&bds->prev_nonce)
    225                     ? NULL
    226                     : &bds->prev_nonce,
    227       .next_nonce = GNUNET_is_zero (&bds->next_nonce)
    228                     ? NULL
    229                     : &bds->next_nonce,
    230       .block_hash = &bds->block_hash,
    231       .refs_len = bds->refs_len,
    232       .object_uids = bds->object_uids,
    233       .object_incs = bds->object_incs,
    234       .prev_entry = bds->have_prev_entry
    235                     ? &bds->prev_entry
    236                     : NULL,
    237       .next_entry = bds->have_next_entry
    238                     ? &bds->next_entry
    239                     : NULL,
    240     };
    241 
    242     bds->bop = SYNC_block_delete (
    243       TALER_TESTING_interpreter_get_context (bds->is),
    244       bds->sync_url,
    245       &bds->sync_priv,
    246       &args,
    247       &block_delete_finished,
    248       bds);
    249     if (NULL == bds->bop)
    250     {
    251       GNUNET_break (0);
    252       TALER_TESTING_interpreter_fail (bds->is);
    253     }
    254   }
    255 }
    256 
    257 
    258 /**
    259  * Run a "block delete" CMD.
    260  *
    261  * @param cls closure.
    262  * @param cmd command currently being run.
    263  * @param is interpreter state.
    264  */
    265 static void
    266 block_delete_run (void *cls,
    267                   const struct TALER_TESTING_Command *cmd,
    268                   struct TALER_TESTING_Interpreter *is)
    269 {
    270   struct BlockDeleteState *bds = cls;
    271 
    272   (void) cmd;
    273   bds->is = is;
    274 
    275   {
    276     const struct TALER_TESTING_Command *ref;
    277 
    278     ref = TALER_TESTING_interpreter_lookup_command (is,
    279                                                     bds->account_reference);
    280     if (NULL == ref)
    281     {
    282       GNUNET_break (0);
    283       goto fail;
    284     }
    285     {
    286       const struct SYNC_AccountPrivateKeyP *priv;
    287       const struct SYNC_AccountPublicKeyP *pub;
    288 
    289       if ( (GNUNET_OK !=
    290             TALER_TESTING_get_trait_sync_account_priv (ref,
    291                                                        &priv)) ||
    292            (GNUNET_OK !=
    293             TALER_TESTING_get_trait_sync_account_pub (ref,
    294                                                       &pub)) )
    295       {
    296         GNUNET_break (0);
    297         goto fail;
    298       }
    299       bds->sync_priv = *priv;
    300       bds->sync_pub = *pub;
    301     }
    302     {
    303       const struct SYNC_BlockNonce *nonce;
    304 
    305       if (GNUNET_OK !=
    306           TALER_TESTING_get_trait_block_nonce (ref,
    307                                                &nonce))
    308       {
    309         GNUNET_break (0);
    310         goto fail;
    311       }
    312       bds->nonce = *nonce;
    313     }
    314     {
    315       const struct SYNC_BlockNonce *pn;
    316 
    317       if (GNUNET_OK ==
    318           TALER_TESTING_get_trait_prev_nonce (ref,
    319                                               &pn))
    320       {
    321         bds->prev_nonce = *pn;
    322       }
    323     }
    324     {
    325       const struct SYNC_BlockNonce *nn;
    326 
    327       if (GNUNET_OK ==
    328           TALER_TESTING_get_trait_next_nonce (ref,
    329                                               &nn))
    330       {
    331         bds->next_nonce = *nn;
    332       }
    333     }
    334     {
    335       const struct GNUNET_HashCode *hash;
    336 
    337       if (GNUNET_OK !=
    338           TALER_TESTING_get_trait_curr_hash (ref,
    339                                              &hash))
    340       {
    341         GNUNET_break (0);
    342         goto fail;
    343       }
    344       bds->block_hash = *hash;
    345     }
    346   }
    347 
    348   /* Phase 1: fetch the linked list to learn the current state of the
    349      block and its neighbours before deleting (their entries are needed
    350      for the relink signatures). */
    351   bds->blop = SYNC_block_list (
    352     TALER_TESTING_interpreter_get_context (is),
    353     bds->sync_url,
    354     &bds->sync_pub,
    355     10000,
    356     NULL,
    357     &block_delete_list_finished,
    358     bds);
    359   if (NULL == bds->blop)
    360     goto fail;
    361 
    362   return;
    363 
    364 fail:
    365   GNUNET_break (0);
    366   TALER_TESTING_interpreter_fail (is);
    367 }
    368 
    369 
    370 /**
    371  * Free the state of a "block delete" CMD, and possibly
    372  * cancel it if it did not complete.
    373  *
    374  * @param cls closure.
    375  * @param cmd command being freed.
    376  */
    377 static void
    378 block_delete_cleanup (void *cls,
    379                       const struct TALER_TESTING_Command *cmd)
    380 {
    381   struct BlockDeleteState *bds = cls;
    382 
    383   if (NULL != bds->bop)
    384   {
    385     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    386                 "Command '%s' did not complete (block delete)\n",
    387                 cmd->label);
    388     SYNC_block_operation_cancel (bds->bop);
    389     bds->bop = NULL;
    390   }
    391   if (NULL != bds->blop)
    392   {
    393     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    394                 "Command '%s' did not complete (block list)\n",
    395                 cmd->label);
    396     SYNC_block_list_cancel (bds->blop);
    397     bds->blop = NULL;
    398   }
    399   GNUNET_free (bds);
    400 }
    401 
    402 
    403 struct TALER_TESTING_Command
    404 SYNC_TESTING_cmd_block_delete (const char *label,
    405                                const char *sync_url,
    406                                const char *account_reference,
    407                                unsigned int http_status,
    408                                unsigned int refs_len,
    409                                const struct SYNC_ObjectUID *object_uids,
    410                                const int16_t *object_incs)
    411 {
    412   struct BlockDeleteState *bds;
    413 
    414   GNUNET_assert (refs_len <= MAX_BLOCK_OBJECT_REFS);
    415   bds = GNUNET_new (struct BlockDeleteState);
    416   bds->sync_url = sync_url;
    417   bds->account_reference = account_reference;
    418   bds->http_status = http_status;
    419   bds->refs_len = refs_len;
    420   if (0 < refs_len)
    421   {
    422     GNUNET_memcpy (bds->object_uids,
    423                    object_uids,
    424                    refs_len * sizeof (struct SYNC_ObjectUID));
    425     GNUNET_memcpy (bds->object_incs,
    426                    object_incs,
    427                    refs_len * sizeof (int16_t));
    428   }
    429   {
    430     struct TALER_TESTING_Command cmd = {
    431       .cls = bds,
    432       .label = label,
    433       .run = &block_delete_run,
    434       .cleanup = &block_delete_cleanup,
    435     };
    436 
    437     return cmd;
    438   }
    439 }
    440 
    441 
    442 /* end of testing_api_cmd_block_delete.c */