diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/auditor/taler-helper-auditor-coins.c | 48 | ||||
| -rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 172 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 98 | 
3 files changed, 311 insertions, 7 deletions
| diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c index c7589957..161ae40b 100644 --- a/src/auditor/taler-helper-auditor-coins.c +++ b/src/auditor/taler-helper-auditor-coins.c @@ -2216,6 +2216,30 @@ check_denomination (  /** + * Function called with details about purse deposits that have been made, with + * the goal of auditing the deposit's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param deposit deposit details + * @param denom_pub denomination public key of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +static enum GNUNET_GenericReturnValue +purse_deposit_cb ( +  void *cls, +  uint64_t rowid, +  const struct TALER_EXCHANGEDB_PurseDeposit *deposit, +  const struct TALER_DenominationPublicKey *denom_pub) +{ +  struct CoinContext *cc = cls; + +  GNUNET_break (0); // FIXME: not implemented! +  return GNUNET_SYSERR; +} + + +/**   * Analyze the exchange's processing of coins.   *   * @param cls closure @@ -2259,12 +2283,13 @@ analyze_coins (void *cls)    {      ppc_start = ppc;      GNUNET_log (GNUNET_ERROR_TYPE_INFO, -                "Resuming coin audit at %llu/%llu/%llu/%llu/%llu\n", +                "Resuming coin audit at %llu/%llu/%llu/%llu/%llu/%llu\n",                  (unsigned long long) ppc.last_deposit_serial_id,                  (unsigned long long) ppc.last_melt_serial_id,                  (unsigned long long) ppc.last_refund_serial_id,                  (unsigned long long) ppc.last_withdraw_serial_id, -                (unsigned long long) ppc.last_recoup_refresh_serial_id); +                (unsigned long long) ppc.last_recoup_refresh_serial_id, +                (unsigned long long) ppc.last_purse_deposits_serial_id);    }    /* setup 'cc' */ @@ -2368,6 +2393,20 @@ analyze_coins (void *cls)    if (0 > cc.qs)      return cc.qs; +  /* process purse_deposits */ +  if (0 > +      (qs = TALER_ARL_edb->select_purse_deposits_above_serial_id ( +         TALER_ARL_edb->cls, +         ppc.last_purse_deposits_serial_id, +         &purse_deposit_cb, +         &cc))) +  { +    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); +    return qs; +  } +  if (0 > cc.qs) +    return cc.qs; +    /* sync 'cc' back to disk */    cc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;    GNUNET_CONTAINER_multihashmap_iterate (cc.denom_summaries, @@ -2421,12 +2460,13 @@ analyze_coins (void *cls)      return qs;    }    GNUNET_log (GNUNET_ERROR_TYPE_INFO, -              "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu\n", +              "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu/%llu\n",                (unsigned long long) ppc.last_deposit_serial_id,                (unsigned long long) ppc.last_melt_serial_id,                (unsigned long long) ppc.last_refund_serial_id,                (unsigned long long) ppc.last_withdraw_serial_id, -              (unsigned long long) ppc.last_recoup_refresh_serial_id); +              (unsigned long long) ppc.last_recoup_refresh_serial_id, +              (unsigned long long) ppc.last_purse_deposits_serial_id);    return qs;  } diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 355508d4..86e72f6a 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1482,10 +1482,32 @@ prepare_statements (struct PostgresClosure *pg)        "    JOIN known_coins kc USING (coin_pub)"        "    JOIN denominations denom USING (denominations_serial)"        " WHERE (" -      "  (deposit_serial_id>=$1)" // FIXME: also select by shard!? +      "  (deposit_serial_id>=$1)"        " )"        " ORDER BY deposit_serial_id ASC;",        1), +    /* Fetch purse deposits with rowid '\geq' the given parameter */ +    GNUNET_PQ_make_prepare ( +      "audit_get_purse_deposits_incr", +      "SELECT" +      " amount_with_fee_val" +      ",amount_with_fee_frac" +      ",purse_pub" +      ",coin_sig" +      ",partner_base_url" +      ",denom.denom_pub" +      ",kc.coin_pub" +      ",kc.age_commitment_hash" +      ",purse_deposit_serial_id" +      " FROM purse_deposits" +      " LEFT JOIN partners USING (partner_serial_id)" +      "    JOIN known_coins kc USING (coin_pub)" +      "    JOIN denominations denom USING (denominations_serial)" +      " WHERE (" +      "  (purse_deposit_serial_id>=$1)" +      " )" +      " ORDER BY purse_deposit_serial_id ASC;", +      1),      /* Fetch an existing deposit request.         Used in #postgres_lookup_transfer_by_deposit(). */      GNUNET_PQ_make_prepare ( @@ -10131,7 +10153,7 @@ struct DepositSerialContext    /**     * Status code, set to #GNUNET_SYSERR on hard errors.     */ -  int status; +  enum GNUNET_GenericReturnValue status;  }; @@ -10193,7 +10215,7 @@ deposit_serial_helper_cb (void *cls,                                      &rowid),        GNUNET_PQ_result_spec_end      }; -    int ret; +    enum GNUNET_GenericReturnValue ret;      memset (&deposit,              0, @@ -10262,6 +10284,148 @@ postgres_select_deposits_above_serial_id (  /** + * Closure for #purse_deposit_serial_helper_cb(). + */ +struct PurseDepositSerialContext +{ + +  /** +   * Callback to call. +   */ +  TALER_EXCHANGEDB_PurseDepositCallback cb; + +  /** +   * Closure for @e cb. +   */ +  void *cb_cls; + +  /** +   * Plugin context. +   */ +  struct PostgresClosure *pg; + +  /** +   * Status code, set to #GNUNET_SYSERR on hard errors. +   */ +  enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct DepositSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_deposit_serial_helper_cb (void *cls, +                                PGresult *result, +                                unsigned int num_results) +{ +  struct PurseDepositSerialContext *dsc = cls; +  struct PostgresClosure *pg = dsc->pg; + +  for (unsigned int i = 0; i<num_results; i++) +  { +    struct TALER_EXCHANGEDB_PurseDeposit deposit = { +      .exchange_base_url = NULL +    }; +    struct TALER_DenominationPublicKey denom_pub; +    uint64_t rowid; +    struct GNUNET_PQ_ResultSpec rs[] = { +      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", +                                   &deposit.amount), +      TALER_PQ_RESULT_SPEC_AMOUNT ("deposit_fee", +                                   &deposit.deposit_fee), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_string ("partner_base_url", +                                      &deposit.exchange_base_url), +        NULL), +      TALER_PQ_result_spec_denom_pub ("denom_pub", +                                      &denom_pub), +      GNUNET_PQ_result_spec_auto_from_type ("purse_pub", +                                            &deposit.purse_pub), +      GNUNET_PQ_result_spec_auto_from_type ("coin_sig", +                                            &deposit.coin_sig), +      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", +                                            &deposit.coin_pub), +      GNUNET_PQ_result_spec_allow_null ( +        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", +                                              &deposit.h_age_commitment), +        &deposit.no_age_commitment), +      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", +                                    &rowid), +      GNUNET_PQ_result_spec_end +    }; +    enum GNUNET_GenericReturnValue ret; + +    memset (&deposit, +            0, +            sizeof (deposit)); +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      dsc->status = GNUNET_SYSERR; +      return; +    } +    ret = dsc->cb (dsc->cb_cls, +                   rowid, +                   &deposit, +                   &denom_pub); +    GNUNET_PQ_cleanup_result (rs); +    if (GNUNET_OK != ret) +      break; +  } +} + + +/** + * Select deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ +static enum GNUNET_DB_QueryStatus +postgres_select_purse_deposits_above_serial_id ( +  void *cls, +  uint64_t serial_id, +  TALER_EXCHANGEDB_PurseDepositCallback cb, +  void *cb_cls) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_uint64 (&serial_id), +    GNUNET_PQ_query_param_end +  }; +  struct PurseDepositSerialContext dsc = { +    .cb = cb, +    .cb_cls = cb_cls, +    .pg = pg, +    .status = GNUNET_OK +  }; +  enum GNUNET_DB_QueryStatus qs; + +  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, +                                             "audit_get_purse_deposits_incr", +                                             params, +                                             &purse_deposit_serial_helper_cb, +                                             &dsc); +  if (GNUNET_OK != dsc.status) +    return GNUNET_DB_STATUS_HARD_ERROR; +  return qs; +} + + +/**   * Closure for #refreshs_serial_helper_cb().   */  struct RefreshsSerialContext @@ -14936,6 +15100,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)    plugin->gc = &postgres_gc;    plugin->select_deposits_above_serial_id      = &postgres_select_deposits_above_serial_id; +  plugin->select_purse_deposits_above_serial_id +    = &postgres_select_purse_deposits_above_serial_id;    plugin->select_refreshes_above_serial_id      = &postgres_select_refreshes_above_serial_id;    plugin->select_refunds_above_serial_id diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index a79acd20..e3f27070 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1681,12 +1681,74 @@ struct TALER_EXCHANGEDB_PurseDepositListEntry    struct TALER_CoinSpendSignatureP coin_sig;    /** +   * FIXME-Oec: probably needed here, not yet used +   * anywhere! +   * +   * Hash of the age commitment used to sign the coin, if age restriction was +   * applicable to the denomination.  May be all zeroes if no age restriction +   * applies. +   */ +  struct TALER_AgeCommitmentHash h_age_commitment_FIXME; + +  /**     * Set to true if the coin was refunded.     */    bool refunded;  }; + +/** + * Information about a /purses/$PID/deposit operation. + */ +struct TALER_EXCHANGEDB_PurseDeposit +{ + +  /** +   * Exchange hosting the purse, NULL for this exchange. +   */ +  char *exchange_base_url; + +  /** +   * Public key of the purse. +   */ +  struct TALER_PurseContractPublicKeyP purse_pub; + +  /** +   * Contribution of the coin to the purse, including +   * deposit fee. +   */ +  struct TALER_Amount amount; + +  /** +   * Depositing fee. +   */ +  struct TALER_Amount deposit_fee; + +  /** +   * Signature by the coin affirming the deposit. +   */ +  struct TALER_CoinSpendSignatureP coin_sig; + +  /** +   * Public key of the coin. +   */ +  struct TALER_CoinSpendPublicKeyP coin_pub; + +  /** +   * Hash of the age commitment used to sign the coin, if age restriction was +   * applicable to the denomination.  May be all zeroes if no age restriction +   * applies. +   */ +  struct TALER_AgeCommitmentHash h_age_commitment; + +  /** +   * Set to true if @e h_age_commitment is not available. +   */ +  bool no_age_commitment; + +}; +  /**   * Information about a melt operation.   */ @@ -1916,6 +1978,24 @@ typedef enum GNUNET_GenericReturnValue  /** + * Function called with details about purse deposits that have been made, with + * the goal of auditing the deposit's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param deposit deposit details + * @param denom_pub denomination public key of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDepositCallback)( +  void *cls, +  uint64_t rowid, +  const struct TALER_EXCHANGEDB_PurseDeposit *deposit, +  const struct TALER_DenominationPublicKey *denom_pub); + + +/**   * Function called with details about coins that were melted,   * with the goal of auditing the refresh's execution.   * @@ -3961,6 +4041,24 @@ struct TALER_EXCHANGEDB_Plugin                                       void *cb_cls);    /** +   * Select purse deposits above @a serial_id in monotonically increasing +   * order. +   * +   * @param cls closure +   * @param serial_id highest serial ID to exclude (select strictly larger) +   * @param cb function to call on each result +   * @param cb_cls closure for @a cb +   * @return transaction status code +   */ +  enum GNUNET_DB_QueryStatus +  (*select_purse_deposits_above_serial_id)( +    void *cls, +    uint64_t serial_id, +    TALER_EXCHANGEDB_PurseDepositCallback cb, +    void *cb_cls); + + +  /**     * Select refresh sessions above @a serial_id in monotonically increasing     * order.     * | 
