diff options
| author | Christian Grothoff <christian@grothoff.org> | 2022-07-30 22:54:21 +0200 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2022-07-30 22:54:21 +0200 | 
| commit | 150917694a4dc3709319fc9586e502eb4b05151f (patch) | |
| tree | 2b4882089bdf4c190b410a1c0f8516c901c766f8 | |
| parent | 544fbd4fe9f536b5933467d3f1adc65a3f1b772d (diff) | |
finish taler-exchange-drain implementation
| -rw-r--r-- | src/exchange/taler-exchange-aggregator.c | 6 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-drain.c | 180 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd.c | 6 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 38 | 
4 files changed, 213 insertions, 17 deletions
| diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 9568f011..3d30ccd0 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -234,12 +234,12 @@ shutdown_task (void *cls)  /** - * Parse the configuration for wirewatch. + * Parse the configuration for aggregator.   *   * @return #GNUNET_OK on success   */  static enum GNUNET_GenericReturnValue -parse_wirewatch_config (void) +parse_aggregator_config (void)  {    if (GNUNET_OK !=        GNUNET_CONFIGURATION_get_value_string (cfg, @@ -811,7 +811,7 @@ run (void *cls,    (void) cfgfile;    cfg = c; -  if (GNUNET_OK != parse_wirewatch_config ()) +  if (GNUNET_OK != parse_aggregator_config ())    {      cfg = NULL;      global_ret = EXIT_NOTCONFIGURED; diff --git a/src/exchange/taler-exchange-drain.c b/src/exchange/taler-exchange-drain.c index 71656412..d409487c 100644 --- a/src/exchange/taler-exchange-drain.c +++ b/src/exchange/taler-exchange-drain.c @@ -40,11 +40,21 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;  static struct TALER_EXCHANGEDB_Plugin *db_plugin;  /** + * Our master public key. + */ +static struct TALER_MasterPublicKeyP master_pub; + +/**   * Next task to run, if any.   */  static struct GNUNET_SCHEDULER_Task *task;  /** + * Base URL of this exchange. + */ +static char *exchange_base_url; + +/**   * Value to return from main(). 0 on success, non-zero on errors.   */  static int global_ret; @@ -82,6 +92,47 @@ shutdown_task (void *cls)  static enum GNUNET_GenericReturnValue  parse_drain_config (void)  { +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_get_value_string (cfg, +                                             "exchange", +                                             "BASE_URL", +                                             &exchange_base_url)) +  { +    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +                               "exchange", +                               "BASE_URL"); +    return GNUNET_SYSERR; +  } + +  { +    char *master_public_key_str; + +    if (GNUNET_OK != +        GNUNET_CONFIGURATION_get_value_string (cfg, +                                               "exchange", +                                               "MASTER_PUBLIC_KEY", +                                               &master_public_key_str)) +    { +      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, +                                 "exchange", +                                 "MASTER_PUBLIC_KEY"); +      return GNUNET_SYSERR; +    } +    if (GNUNET_OK != +        GNUNET_CRYPTO_eddsa_public_key_from_string (master_public_key_str, +                                                    strlen ( +                                                      master_public_key_str), +                                                    &master_pub.eddsa_pub)) +    { +      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +                                 "exchange", +                                 "MASTER_PUBLIC_KEY", +                                 "invalid base32 encoding for a master public key"); +      GNUNET_free (master_public_key_str); +      return GNUNET_SYSERR; +    } +    GNUNET_free (master_public_key_str); +  }    if (NULL ==        (db_plugin = TALER_EXCHANGEDB_plugin_load (cfg)))    { @@ -134,6 +185,13 @@ static void  run_drain (void *cls)  {    enum GNUNET_DB_QueryStatus qs; +  uint64_t serial; +  struct TALER_WireTransferIdentifierRawP wtid; +  char *account_section; +  char *payto_uri; +  struct GNUNET_TIME_Timestamp request_timestamp; +  struct TALER_Amount amount; +  struct TALER_MasterSignatureP master_sig;    (void) cls;    task = NULL; @@ -147,11 +205,14 @@ run_drain (void *cls)      GNUNET_SCHEDULER_shutdown ();      return;    } -#if 0 -  qs = db_plugin->profit_drains_get_pending (db_plugin->cls); -#else -  qs = -1; -#endif +  qs = db_plugin->profit_drains_get_pending (db_plugin->cls, +                                             &serial, +                                             &wtid, +                                             &account_section, +                                             &payto_uri, +                                             &request_timestamp, +                                             &amount, +                                             &master_sig);    switch (qs)    {    case GNUNET_DB_STATUS_HARD_ERROR: @@ -161,7 +222,6 @@ run_drain (void *cls)      GNUNET_SCHEDULER_shutdown ();      return;    case GNUNET_DB_STATUS_SOFT_ERROR: -    /* try again */      db_plugin->rollback (db_plugin->cls);      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                  "Serialization failure on simple SELECT!?\n"); @@ -169,7 +229,7 @@ run_drain (void *cls)      GNUNET_SCHEDULER_shutdown ();      return;    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: -    /* no more profit drains, go sleep a bit! */ +    /* no profit drains, finished */      db_plugin->rollback (db_plugin->cls);      GNUNET_assert (NULL == task);      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, @@ -180,11 +240,107 @@ run_drain (void *cls)      /* continued below */      break;    } -  // FIXME: check signature (again!) -  // FIMXE: display for human check -  // FIXME: insert into pre-wire -  // FIXME: mark as done -  // FIXME: commit transaction + report success + exit +  /* Check signature (again, this is a critical operation!) */ +  if (GNUNET_OK != +      TALER_exchange_offline_profit_drain_verify ( +        &wtid, +        request_timestamp, +        &amount, +        account_section, +        payto_uri, +        &master_pub, +        &master_sig)) +  { +    GNUNET_break (0); +    global_ret = EXIT_FAILURE; +    db_plugin->rollback (db_plugin->cls); +    GNUNET_assert (NULL == task); +    GNUNET_SCHEDULER_shutdown (); +    return; +  } + +  /* Display data for manual human check */ +  fprintf (stdout, +           "Critical operation. MANUAL CHECK REQUIRED.\n"); +  fprintf (stdout, +           "We will wire %s to `%s'\n based on instructions from %s.\n", +           TALER_amount2s (&amount), +           payto_uri, +           GNUNET_TIME_timestamp2s (request_timestamp)); +  fprintf (stdout, +           "Press ENTER to confirm, CTRL-D to abort.\n"); +  while (1) +  { +    int key; + +    key = getchar (); +    if (EOF == key) +    { +      fprintf (stdout, +               "Transfer aborted.\n" +               "Re-run 'taler-exchange-drain' to try it again.\n" +               "Contact Taler Systems SA to cancel it for good.\n" +               "Exiting.\n"); +      db_plugin->rollback (db_plugin->cls); +      GNUNET_assert (NULL == task); +      GNUNET_SCHEDULER_shutdown (); +      global_ret = EXIT_FAILURE; +      return; +    } +    if ('\n' == key) +      break; +  } + +  /* Note: account_section ignored for now, we +     might want to use it here in the future... */ +  (void) account_section; +  { +    char *method; +    void *buf; +    size_t buf_size; + +    TALER_BANK_prepare_transfer (payto_uri, +                                 &amount, +                                 exchange_base_url, +                                 &wtid, +                                 &buf, +                                 &buf_size); +    method = TALER_payto_get_method (payto_uri); +    qs = db_plugin->wire_prepare_data_insert (db_plugin->cls, +                                              method, +                                              buf, +                                              buf_size); +    GNUNET_free (method); +    GNUNET_free (buf); +  } +  qs = db_plugin->profit_drains_set_finished (db_plugin->cls, +                                              serial); +  switch (qs) +  { +  case GNUNET_DB_STATUS_HARD_ERROR: +    db_plugin->rollback (db_plugin->cls); +    GNUNET_break (0); +    global_ret = EXIT_FAILURE; +    GNUNET_SCHEDULER_shutdown (); +    return; +  case GNUNET_DB_STATUS_SOFT_ERROR: +    db_plugin->rollback (db_plugin->cls); +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Failed: database serialization issue\n"); +    global_ret = EXIT_FAILURE; +    GNUNET_SCHEDULER_shutdown (); +    return; +  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: +    db_plugin->rollback (db_plugin->cls); +    GNUNET_assert (NULL == task); +    GNUNET_break (0); +    GNUNET_SCHEDULER_shutdown (); +    return; +  default: +    /* continued below */ +    break; +  } +  /* commit transaction + report success + exit */    if (0 >= commit_or_warn ())      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,                  "Profit drain triggered. Exiting.\n"); diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 2d659058..14cc8c1c 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -1836,8 +1836,10 @@ exchange_serve_process_config (void)                                                      &TEH_master_public_key.                                                      eddsa_pub))      { -      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                  "Invalid master public key given in exchange configuration."); +      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, +                                 "exchange", +                                 "MASTER_PUBLIC_KEY", +                                 "invalid base32 encoding for a master public key");        GNUNET_free (master_public_key_str);        return GNUNET_SYSERR;      } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 7f31752d..2ffa8486 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -5545,6 +5545,44 @@ struct TALER_EXCHANGEDB_Plugin                           const struct TALER_MasterSignatureP *master_sig); +  /** +   * Get profit drain operation ready to execute. +   * +   * @param cls the @e cls of this struct with the plugin-specific state +   * @param[out] serial set to serial ID of the entry +   * @param[out] wtid set set to wire transfer ID to use +   * @param[out] account_section set to  account to drain +   * @param[out] payto_uri set to account to wire funds to +   * @param[out] request_timestamp set to time of the signature +   * @param[out] amount set to amount to wire +   * @param[out] master_sig set to signature affirming the operation +   * @return transaction status code +   */ +  enum GNUNET_DB_QueryStatus +  (*profit_drains_get_pending)( +    void *cls, +    uint64_t *serial, +    struct TALER_WireTransferIdentifierRawP *wtid, +    char **account_section, +    char **payto_uri, +    struct GNUNET_TIME_Timestamp *request_timestamp, +    struct TALER_Amount *amount, +    struct TALER_MasterSignatureP *master_sig); + + +  /** +   * Set profit drain operation to finished. +   * +   * @param cls the @e cls of this struct with the plugin-specific state +   * @param serial serial ID of the entry to mark finished +   * @return transaction status code +   */ +  enum GNUNET_DB_QueryStatus +  (*profit_drains_set_finished)( +    void *cls, +    uint64_t serial); + +  };  #endif /* _TALER_EXCHANGE_DB_H */ | 
