test_denomination_revocations.c (8254B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file exchangedb/test_denomination_revocations.c 18 * @brief tests for the exchangedb functions whose primary table is 19 * `denomination_revocations` 20 * @author Christian Grothoff 21 * 22 * Covers #TALER_EXCHANGEDB_insert_denomination_revocation() and 23 * #TALER_EXCHANGEDB_get_denomination_revocation(). 24 * 25 * `denomination_revocations` references `denominations`, so a denomination 26 * has to exist first; that is what TDB_denom() is for. The check for the 27 * `recoup_possible` flag of #TALER_EXCHANGEDB_iterate_denominations() lives 28 * here too, since that flag is what the revocation row is *for*. 29 */ 30 #include "test_common.h" 31 #include "exchange-database/insert_denomination_revocation.h" 32 #include "exchange-database/get_denomination_revocation.h" 33 #include "exchange-database/iterate_denominations.h" 34 35 36 /** 37 * Closure for #recoup_cb(). 38 */ 39 struct RecoupContext 40 { 41 /** 42 * Denomination we are looking for. 43 */ 44 const struct TALER_DenominationHashP *h_denom_pub; 45 46 /** 47 * How many times did we see it? 48 */ 49 unsigned int matched; 50 51 /** 52 * Recoup flag reported for it. 53 */ 54 bool recoup_possible; 55 }; 56 57 58 /** 59 * Callback for #TALER_EXCHANGEDB_iterate_denominations(). 60 * 61 * @param cls a `struct RecoupContext *` 62 * @param denom_pub public key of the denomination 63 * @param h_denom_pub hash of @a denom_pub 64 * @param meta meta data of the denomination 65 * @param master_sig master signature over the denomination 66 * @param recoup_possible true if the denomination was revoked 67 */ 68 static void 69 recoup_cb (void *cls, 70 const struct TALER_DenominationPublicKey *denom_pub, 71 const struct TALER_DenominationHashP *h_denom_pub, 72 const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, 73 const struct TALER_MasterSignatureP *master_sig, 74 bool recoup_possible) 75 { 76 struct RecoupContext *ctx = cls; 77 78 (void) denom_pub; 79 (void) meta; 80 (void) master_sig; 81 if (0 != GNUNET_memcmp (h_denom_pub, 82 ctx->h_denom_pub)) 83 return; 84 ctx->matched++; 85 ctx->recoup_possible = recoup_possible; 86 } 87 88 89 /** 90 * A denomination that does not exist cannot be revoked, and is reported as 91 * not revoked. 92 * 93 * @param pg the database context 94 * @return 0 on success 95 */ 96 static int 97 check_unknown_denomination (struct TALER_EXCHANGEDB_PostgresContext *pg) 98 { 99 struct TALER_DenominationHashP h_denom_pub; 100 struct TALER_MasterSignatureP master_sig; 101 struct TALER_MasterSignatureP got; 102 uint64_t rowid; 103 104 TDB_FILL (h_denom_pub, 105 1); 106 TDB_FILL (master_sig, 107 1); 108 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 109 TALER_EXCHANGEDB_get_denomination_revocation (pg, 110 &h_denom_pub, 111 &got, 112 &rowid)); 113 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 114 TALER_EXCHANGEDB_insert_denomination_revocation (pg, 115 &h_denom_pub, 116 &master_sig)); 117 FAILIF (0 != TDB_count (pg, 118 "FROM denomination_revocations")); 119 return 0; 120 } 121 122 123 /** 124 * Revoking a denomination records the signature and flips 125 * `recoup_possible`. 126 * 127 * @param pg the database context 128 * @return 0 on success 129 */ 130 static int 131 check_revoke (struct TALER_EXCHANGEDB_PostgresContext *pg) 132 { 133 struct TDB_Denom revoked; 134 struct TDB_Denom intact; 135 struct TALER_MasterSignatureP master_sig; 136 struct TALER_MasterSignatureP got; 137 struct RecoupContext ctx; 138 uint64_t rowid = 0; 139 140 TDB_denom (pg, 141 10, 142 "5", 143 "0.1", 144 &revoked); 145 TDB_denom (pg, 146 11, 147 "5", 148 "0.1", 149 &intact); 150 TDB_FILL (master_sig, 151 42); 152 153 /* before the revocation, recoup is not possible */ 154 memset (&ctx, 155 0, 156 sizeof (ctx)); 157 ctx.h_denom_pub = &revoked.h_denom_pub; 158 FAILIF_C (0 >= 159 TALER_EXCHANGEDB_iterate_denominations (pg, 160 &recoup_cb, 161 &ctx), 162 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 163 FAILIF_C (1 != ctx.matched, 164 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 165 FAILIF_C (ctx.recoup_possible, 166 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 167 168 FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 169 TALER_EXCHANGEDB_insert_denomination_revocation ( 170 pg, 171 &revoked.h_denom_pub, 172 &master_sig), 173 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 174 memset (&got, 175 0, 176 sizeof (got)); 177 FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 178 TALER_EXCHANGEDB_get_denomination_revocation ( 179 pg, 180 &revoked.h_denom_pub, 181 &got, 182 &rowid), 183 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 184 FAILIF_C (0 != GNUNET_memcmp (&got, 185 &master_sig), 186 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 187 FAILIF_C (0 == rowid, 188 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 189 190 /* now recoup is possible for the revoked denomination... */ 191 memset (&ctx, 192 0, 193 sizeof (ctx)); 194 ctx.h_denom_pub = &revoked.h_denom_pub; 195 FAILIF_C (0 >= 196 TALER_EXCHANGEDB_iterate_denominations (pg, 197 &recoup_cb, 198 &ctx), 199 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 200 FAILIF_C (1 != ctx.matched, 201 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 202 FAILIF_C (! ctx.recoup_possible, 203 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 204 205 /* ...and only for that one */ 206 memset (&ctx, 207 0, 208 sizeof (ctx)); 209 ctx.h_denom_pub = &intact.h_denom_pub; 210 FAILIF_C (0 >= 211 TALER_EXCHANGEDB_iterate_denominations (pg, 212 &recoup_cb, 213 &ctx), 214 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 215 FAILIF_C (1 != ctx.matched, 216 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 217 FAILIF_C (ctx.recoup_possible, 218 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 219 FAILIF_C (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 220 TALER_EXCHANGEDB_get_denomination_revocation ( 221 pg, 222 &intact.h_denom_pub, 223 &got, 224 &rowid), 225 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 226 FAILIF_C (1 != TDB_count (pg, 227 "FROM denomination_revocations"), 228 TDB_denom_free (&revoked); TDB_denom_free (&intact)); 229 TDB_denom_free (&revoked); 230 TDB_denom_free (&intact); 231 return 0; 232 } 233 234 235 /** 236 * The checks to run, in order. 237 */ 238 static const struct TDB_Test tests[] = { 239 { "denomination-revocations-unknown-denomination", 240 &check_unknown_denomination }, 241 { "denomination-revocations-revoke", 242 &check_revoke }, 243 { NULL, NULL } 244 }; 245 246 247 int 248 main (int argc, 249 char *const *argv) 250 { 251 return TDB_main (argc, 252 argv, 253 "test-denomination-revocations", 254 "Tests for the exchangedb `denomination_revocations' table", 255 tests); 256 } 257 258 259 /* end of test_denomination_revocations.c */