sync

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

testing_api_cmd_block_append.c (7733B)


      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_append.c
     21  * @brief command to append a block to the sync backend service.
     22  * @author Iván Ávalos
     23  */
     24 #include "testing_api_cmd_block_common.h"
     25 #include <stdbool.h>
     26 
     27 
     28 /**
     29  * Process a reference for a retry upload: inherit keys, nonce
     30  * (if not explicitly set), and old_data_hash from the ref's
     31  * prev_hash trait.
     32  *
     33  * @param[in,out] bus state to populate
     34  * @param ref reference command to inherit from
     35  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
     36  */
     37 static enum GNUNET_GenericReturnValue
     38 append_retry_process_ref (
     39   struct BlockUploadState *bus,
     40   const struct TALER_TESTING_Command *ref)
     41 {
     42   if (GNUNET_OK !=
     43       SYNC_TESTING_inherit_account_keys_ (bus,
     44                                           ref))
     45     return GNUNET_SYSERR;
     46 
     47   /* Inherit block nonce if not explicitly set */
     48   if (GNUNET_is_zero (&bus->nonce))
     49   {
     50     const struct SYNC_BlockNonce *nonce;
     51 
     52     if (GNUNET_OK ==
     53         TALER_TESTING_get_trait_block_nonce (ref,
     54                                              &nonce))
     55       bus->nonce = *nonce;
     56   }
     57 
     58   /* Inherit old_data_hash from prev_hash for retry */
     59   if (GNUNET_is_zero (&bus->old_data_hash))
     60   {
     61     const struct GNUNET_HashCode *h;
     62 
     63     if (GNUNET_OK ==
     64         TALER_TESTING_get_trait_prev_hash (ref,
     65                                            &h))
     66       bus->old_data_hash = *h;
     67   }
     68 
     69   return GNUNET_OK;
     70 }
     71 
     72 
     73 /**
     74  * Process a reference for an append-after: inherit keys, set
     75  * prev_nonce from the ref's block_nonce (to chain the new block after
     76  * the referenced one), and collect the tail's data for its relink
     77  * signature.
     78  *
     79  * @param[in,out] bus state to populate
     80  * @param ref reference command to inherit from
     81  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
     82  */
     83 static enum GNUNET_GenericReturnValue
     84 append_after_process_ref (
     85   struct BlockUploadState *bus,
     86   const struct TALER_TESTING_Command *ref)
     87 {
     88   const struct SYNC_BlockNonce *nonce;
     89   const struct SYNC_BlockNonce *pn;
     90   const struct GNUNET_HashCode *h;
     91   const struct GNUNET_HashCode *rh;
     92 
     93   if (GNUNET_OK !=
     94       SYNC_TESTING_inherit_account_keys_ (bus,
     95                                           ref))
     96     return GNUNET_SYSERR;
     97   /* Set prev_nonce to chain after the referenced block.  If ref has
     98      no nonce trait, prev_nonce stays zero (meaning no predecessor —
     99      allowed by the API) */
    100   if (GNUNET_OK ==
    101       TALER_TESTING_get_trait_block_nonce (ref,
    102                                            &nonce))
    103     bus->prev_nonce = *nonce;
    104 
    105   /* The tail's data for its relink signature */
    106   if (GNUNET_OK ==
    107       TALER_TESTING_get_trait_curr_hash (ref,
    108                                          &h))
    109   {
    110     bus->prev_entry.nonce = bus->prev_nonce;
    111     bus->prev_entry.hash = *h;
    112     bus->have_relink_target = true;
    113   }
    114   if (GNUNET_OK ==
    115       TALER_TESTING_get_trait_block_refs_hash (ref,
    116                                                &rh))
    117     bus->prev_entry.refs_hash = *rh;
    118   if (GNUNET_OK ==
    119       TALER_TESTING_get_trait_prev_nonce (ref,
    120                                           &pn))
    121   {
    122     bus->prev_entry.prev_nonce = *pn;
    123     bus->prev_entry.have_prev_nonce = ! GNUNET_is_zero (pn);
    124   }
    125 
    126   return GNUNET_OK;
    127 }
    128 
    129 
    130 /**
    131  * Start a block append operation.
    132  *
    133  * @param ctx for HTTP client request processing
    134  * @param sync_url base URL of the Sync server
    135  * @param sync_priv private key of the account
    136  * @param nonce nonce identifying the block
    137  * @param prev_nonce nonce of the preceding block, or NULL
    138  * @param next_nonce unused, appends are always at the tail
    139  * @param old_data_hash unused, appends have no previous data
    140  * @param block_data_size number of bytes in @a block_data
    141  * @param block_data the block data
    142  * @param refs_len number of entries in @a object_uids and @a object_incs
    143  * @param object_uids array of object UIDs referenced by this block
    144  * @param object_incs array of reference count adjustments
    145  * @param prev_entry the tail's entry, for its relink signature, or NULL
    146  * @param cb function to call with the result
    147  * @param cb_cls closure for @a cb
    148  * @return handle for the operation
    149  */
    150 static struct SYNC_BlockOperation *
    151 append_start_upload (
    152   struct GNUNET_CURL_Context *ctx,
    153   const char *sync_url,
    154   const struct SYNC_AccountPrivateKeyP *sync_priv,
    155   const struct SYNC_BlockNonce *nonce,
    156   const struct SYNC_BlockNonce *prev_nonce,
    157   const struct SYNC_BlockNonce *next_nonce,
    158   const struct GNUNET_HashCode *old_data_hash,
    159   size_t block_data_size,
    160   const void *block_data,
    161   size_t refs_len,
    162   const struct SYNC_ObjectUID *object_uids,
    163   const int16_t *object_incs,
    164   const struct SYNC_BlockListEntry *prev_entry,
    165   SYNC_BlockOperationCallback cb,
    166   void *cb_cls)
    167 {
    168   struct SYNC_BlockOperationArgs args = {
    169     .nonce = nonce,
    170     .prev_nonce = prev_nonce,
    171     .next_nonce = NULL,
    172     .old_data_hash = NULL,
    173     .block_data_size = block_data_size,
    174     .block_data = block_data,
    175     .refs_len = refs_len,
    176     .object_uids = object_uids,
    177     .object_incs = object_incs,
    178     .prev_entry = prev_entry,
    179   };
    180 
    181   (void) next_nonce;
    182   (void) old_data_hash;
    183   return SYNC_block_append (ctx,
    184                             sync_url,
    185                             sync_priv,
    186                             &args,
    187                             cb,
    188                             cb_cls);
    189 }
    190 
    191 
    192 struct TALER_TESTING_Command
    193 SYNC_TESTING_cmd_block_append (const char *label,
    194                                const char *sync_url,
    195                                const char *upload_reference,
    196                                const struct SYNC_BlockNonce *nonce,
    197                                unsigned int http_status,
    198                                const void *block_data,
    199                                size_t block_data_size,
    200                                bool retry_upload,
    201                                unsigned int refs_len,
    202                                const struct SYNC_ObjectUID *object_uids,
    203                                const int16_t *object_incs)
    204 {
    205   struct BlockUploadState *bus;
    206 
    207   GNUNET_assert (refs_len <= MAX_BLOCK_OBJECT_REFS);
    208   bus = GNUNET_new (struct BlockUploadState);
    209   bus->sync_url = sync_url;
    210   bus->upload_reference = upload_reference;
    211   if (NULL != nonce)
    212     bus->nonce = *nonce;
    213   bus->http_status = http_status;
    214   bus->block_data = block_data;
    215   bus->block_data_size = block_data_size;
    216   bus->refs_len = refs_len;
    217   if (0 < refs_len)
    218   {
    219     GNUNET_memcpy (bus->object_uids,
    220                    object_uids,
    221                    refs_len * sizeof (struct SYNC_ObjectUID));
    222     GNUNET_memcpy (bus->object_incs,
    223                    object_incs,
    224                    refs_len * sizeof (int16_t));
    225   }
    226   bus->process_ref = retry_upload
    227     ? &append_retry_process_ref
    228     : &append_after_process_ref;
    229   bus->start_upload = &append_start_upload;
    230   {
    231     struct TALER_TESTING_Command cmd = {
    232       .cls = bus,
    233       .label = label,
    234       .run = &SYNC_TESTING_block_upload_run_,
    235       .cleanup = &SYNC_TESTING_block_upload_cleanup_,
    236       .traits = &SYNC_TESTING_block_upload_traits_
    237     };
    238 
    239     return cmd;
    240   }
    241 }