summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-12-06 21:48:31 +0100
committerChristian Grothoff <christian@grothoff.org>2020-12-06 21:54:32 +0100
commit22c9321e67c54c581eca7ad8428267b0b14b9425 (patch)
tree5af2f66c8fb8590a3a3818c2544ae8105e71e7c8
parentfd96e34c785e86423f739036506c9e860e683677 (diff)
downloadexchange-22c9321e67c54c581eca7ad8428267b0b14b9425.tar.gz
exchange-22c9321e67c54c581eca7ad8428267b0b14b9425.tar.bz2
exchange-22c9321e67c54c581eca7ad8428267b0b14b9425.zip
expand exchangedb plugin for new /keys logic
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c61
-rw-r--r--src/exchangedb/exchange-0002.sql15
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c507
-rw-r--r--src/include/taler_exchangedb_plugin.h166
4 files changed, 726 insertions, 23 deletions
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index 2bc23de16..67a5a3fbe 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -229,6 +229,9 @@ struct TEH_KeyStateHandle
*/
struct GNUNET_CONTAINER_MultiPeerMap *signkey_map;
+ // FIXME: need list of auditors here!
+ // FIXME: need list of auditor-denominations here!
+
/**
* Sorted array of responses to /keys (MUST be sorted by cherry-picking date) of
* length @e krd_array_length;
@@ -780,15 +783,35 @@ signkey_info_cb (
* @param auditor_pub the public key of the auditor
* @param auditor_url URL of the REST API of the auditor
* @param auditor_name human readable official name of the auditor
- * @param ... MORE
*/
static void
auditor_info_cb (
void *cls,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const char *auditor_url,
- const char *auditor_name,
- ...)
+ const char *auditor_name)
+{
+ struct TEH_KeyStateHandle *ksh = cls;
+
+ // FIXME: remember...
+}
+
+
+/**
+ * Function called with information about the denominations
+ * audited by the exchange's auditors.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param auditor_pub the public key of an auditor
+ * @param h_denom_pub hash of a denomination key audited by this auditor
+ * @param auditor_sig signature from the auditor affirming this
+ */
+static void
+auditor_denom_cb (
+ void *cls,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_AuditorSignatureP *auditor_sig)
{
struct TEH_KeyStateHandle *ksh = cls;
@@ -828,8 +851,7 @@ build_key_state (struct HelperState *hs)
GNUNET_YES);
ksh->signkey_map = GNUNET_CONTAINER_multihashmap_create (32,
GNUNET_NO /* MUST be NO! */);
-#if TBD
- // NOTE: should ONLY fetch master-signed signkeys, but ALSO those that were revoked!
+ /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */
qs = TEH_plugin->iterate_denominations (TEH_plugin->cls,
&denomination_info_cb,
ksh);
@@ -840,12 +862,10 @@ build_key_state (struct HelperState *hs)
true);
return NULL;
}
-#endif
-#if TBD
- // NOTE: should ONLY fetch non-revoked AND master-signed signkeys!
- qs = TEH_plugin->iterate_signkeys (TEH_plugin->cls,
- &signkey_info_cb,
- ksh);
+ /* NOTE: ONLY fetches non-revoked AND master-signed signkeys! */
+ qs = TEH_plugin->iterate_active_signkeys (TEH_plugin->cls,
+ &signkey_info_cb,
+ ksh);
if (qs < 0)
{
GNUNET_break (0);
@@ -853,11 +873,19 @@ build_key_state (struct HelperState *hs)
true);
return NULL;
}
-#endif
-#if TBD
- qs = TEH_plugin->iterate_auditor_info (TEH_plugin->cls,
- &auditor_info_cb,
- ksh);
+ qs = TEH_plugin->iterate_active_auditors (TEH_plugin->cls,
+ &auditor_info_cb,
+ ksh);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ destroy_key_state (ksh,
+ true);
+ return NULL;
+ }
+ qs = TEH_plugin->iterate_auditor_denominations (TEH_plugin->cls,
+ &auditor_denom_cb,
+ ksh);
if (qs < 0)
{
GNUNET_break (0);
@@ -865,7 +893,6 @@ build_key_state (struct HelperState *hs)
true);
return NULL;
}
-#endif
return ksh;
}
diff --git a/src/exchangedb/exchange-0002.sql b/src/exchangedb/exchange-0002.sql
index c7a315282..601935bf6 100644
--- a/src/exchangedb/exchange-0002.sql
+++ b/src/exchangedb/exchange-0002.sql
@@ -114,20 +114,23 @@ COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
CREATE TABLE IF NOT EXISTS exchange_sign_keys
- (exchange_pub BYTEA PRIMARY KEY
- ,master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)
+ (exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
- ,legal_end INT8 NOT NULL
+ ,valid_from INT8 NOT NULL
+ ,expire_sign INT8 NOT NULL
+ ,expire_legal INT8 NOT NULL
);
COMMENT ON TABLE exchange_sign_keys
IS 'Table with master public key signatures on exchange online signing keys.';
COMMENT ON COLUMN exchange_sign_keys.exchange_pub
IS 'Public online signing key of the exchange.';
-COMMENT ON COLUMN exchange_sign_keys.master_pub
- IS 'Master public key of the exchange that was used for master_sig.';
COMMENT ON COLUMN exchange_sign_keys.master_sig
IS 'Signature affirming the validity of the signing key of purpose TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY.';
-COMMENT ON COLUMN exchange_sign_keys.legal_end
+COMMENT ON COLUMN exchange_sign_keys.valid_from
+ IS 'Time when this online signing key will first be used to sign messages.';
+COMMENT ON COLUMN exchange_sign_keys.expire_sign
+ IS 'Time when this online signing key will no longer be used to sign.';
+COMMENT ON COLUMN exchange_sign_keys.expire_legal
IS 'Time when this online signing key legally expires.';
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 7918f540b..2fcb0d01d 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -314,6 +314,66 @@ postgres_get_session (void *cls)
",denom_pub"
" FROM denominations;",
0),
+ /* Used in #postgres_iterate_denominations() */
+ GNUNET_PQ_make_prepare ("select_denominations",
+ "SELECT"
+ " denominations.master_sig"
+ ",denom_revocations_serial_id IS NOT NULL AS revoked"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin_val" /* value of this denom */
+ ",coin_frac" /* fractional value of this denom */
+ ",fee_withdraw_val"
+ ",fee_withdraw_frac"
+ ",fee_deposit_val"
+ ",fee_deposit_frac"
+ ",fee_refresh_val"
+ ",fee_refresh_frac"
+ ",fee_refund_val"
+ ",fee_refund_frac"
+ ",denom_pub"
+ " FROM denominations"
+ " LEFT JOIN "
+ " denomination_revocations USING (denom_pub_hash);",
+ 0),
+ /* Used in #postgres_iterate_active_signkeys() */
+ GNUNET_PQ_make_prepare ("select_signkeys",
+ "SELECT"
+ " master_sig"
+ ",exchange_pub"
+ ",valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ " FROM exchange_sign_keys esk"
+ " WHERE"
+ " expire_sign > $1"
+ " AND NOT EXISTS "
+ " (SELECT exchange_pub "
+ " FROM signkey_revocations skr"
+ " WHERE esk.exchange_pub = skr.exchange_pub);",
+ 1),
+ /* Used in #postgres_iterate_auditor_denominations() */
+ GNUNET_PQ_make_prepare ("select_auditor_denoms",
+ "SELECT"
+ " auditor_denom_sigs.auditor_pub"
+ ",auditor_denom_sigs.denom_pub_hash"
+ ",auditor_denom_sigs.auditor_sig"
+ " FROM auditor_denom_sigs"
+ " JOIN auditors USING (auditor_pub)"
+ " WHERE auditors.is_active;",
+ 0),
+ /* Used in #postgres_iterate_active_auditors() */
+ GNUNET_PQ_make_prepare ("select_auditors",
+ "SELECT"
+ " auditor_pub"
+ ",auditor_url"
+ ",auditor_name"
+ " FROM auditors"
+ " WHERE"
+ " is_active;",
+ 0),
/* Used in #postgres_get_denomination_info() */
GNUNET_PQ_make_prepare ("denomination_get",
"SELECT"
@@ -1982,6 +2042,448 @@ postgres_iterate_denomination_info (void *cls,
/**
+ * Closure for #dominations_cb_helper()
+ */
+struct DenomsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_DenominationsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct PostgresClosure *pg;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_denominations().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct DenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+dominations_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenomsIteratorContext *dic = cls;
+ struct PostgresClosure *pg = dic->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_HashCode h_denom_pub;
+ uint8_t revoked;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("revoked",
+ &revoked),
+ TALER_PQ_result_spec_absolute_time ("valid_from",
+ &meta.start),
+ TALER_PQ_result_spec_absolute_time ("expire_withdraw",
+ &meta.expire_withdraw),
+ TALER_PQ_result_spec_absolute_time ("expire_deposit",
+ &meta.expire_deposit),
+ TALER_PQ_result_spec_absolute_time ("expire_legal",
+ &meta.expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &meta.value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &meta.fee_withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &meta.fee_deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &meta.fee_refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &meta.fee_refund),
+ GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
+ &denom_pub.rsa_public_key),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
+ &h_denom_pub);
+ dic->cb (dic->cb_cls,
+ &denom_pub,
+ &h_denom_pub,
+ &meta,
+ &master_sig,
+ (0 != revoked));
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+* Function called to invoke @a cb on every known denomination key (revoked
+* and non-revoked) that has been signed by the master key. Runs in its own
+* read-only transaction (hence no session provided).
+*
+*
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_iterate_denominations (void *cls,
+ TALER_EXCHANGEDB_DenominationsCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pc = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct DenomsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pc
+ };
+ struct TALER_EXCHANGEDB_Session *session;
+
+ session = postgres_get_session (pc);
+ if (NULL == session)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_PQ_eval_prepared_multi_select (session->conn,
+ "select_denominations",
+ params,
+ &dominations_cb_helper,
+ &dic);
+}
+
+
+/**
+ * Closure for #signkeys_cb_helper()
+ */
+struct SignkeysIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_ActiveSignkeysCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Helper function for #postgres_active_signkeys().
+ * Calls the callback with each signkey.
+ *
+ * @param cls a `struct SignkeysIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+signkeys_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SignkeysIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_SignkeyMetaData meta;
+ struct TALER_ExchangePublicKeyP exchange_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
+ &exchange_pub),
+ TALER_PQ_result_spec_absolute_time ("valid_from",
+ &meta.start),
+ TALER_PQ_result_spec_absolute_time ("expire_sign",
+ &meta.expire_sign),
+ TALER_PQ_result_spec_absolute_time ("expire_legal",
+ &meta.expire_legal),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &exchange_pub,
+ &meta,
+ &master_sig);
+ }
+}
+
+
+/**
+ * Function called to invoke @a cb on every non-revoked exchange signing key
+ * that has been signed by the master key. Revoked and (for signing!)
+ * expired keys are skipped. Runs in its own read-only transaction (hence no
+ * session provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each signing key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_iterate_active_signkeys (void *cls,
+ TALER_EXCHANGEDB_ActiveSignkeysCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pc = cls;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct SignkeysIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+ struct TALER_EXCHANGEDB_Session *session;
+
+ now = GNUNET_TIME_absolute_get ();
+ session = postgres_get_session (pc);
+ if (NULL == session)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_PQ_eval_prepared_multi_select (session->conn,
+ "select_signkeys",
+ params,
+ &signkeys_cb_helper,
+ &dic);
+}
+
+
+/**
+ * Closure for #auditors_cb_helper()
+ */
+struct AuditorsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_AuditorsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Helper function for #postgres_active_auditors().
+ * Calls the callback with each auditor.
+ *
+ * @param cls a `struct SignkeysIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditors_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AuditorsIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_AuditorPublicKeyP auditor_pub;
+ char *auditor_url;
+ char *auditor_name;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+ &auditor_pub),
+ GNUNET_PQ_result_spec_string ("auditor_url",
+ &auditor_url),
+ GNUNET_PQ_result_spec_string ("auditor_name",
+ &auditor_name),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &auditor_pub,
+ auditor_url,
+ auditor_name);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called to invoke @a cb on every active auditor. Disabled
+ * auditors are skipped. Runs in its own read-only transaction (hence no
+ * session provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_iterate_active_auditors (void *cls,
+ TALER_EXCHANGEDB_AuditorsCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pc = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct AuditorsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+ struct TALER_EXCHANGEDB_Session *session;
+
+ session = postgres_get_session (pc);
+ if (NULL == session)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_PQ_eval_prepared_multi_select (session->conn,
+ "select_auditors",
+ params,
+ &auditors_cb_helper,
+ &dic);
+}
+
+
+/**
+ * Closure for #auditor_denoms_cb_helper()
+ */
+struct AuditorDenomsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_auditor_denominations().
+ * Calls the callback with each auditor and denomination pair.
+ *
+ * @param cls a `struct AuditorDenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditor_denoms_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AuditorDenomsIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_AuditorPublicKeyP auditor_pub;
+ struct GNUNET_HashCode h_denom_pub;
+ struct TALER_AuditorSignatureP auditor_sig;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+ &auditor_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &h_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
+ &auditor_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &auditor_pub,
+ &h_denom_pub,
+ &auditor_sig);
+ }
+}
+
+
+/**
+ * Function called to invoke @a cb on every denomination with an active
+ * auditor. Disabled auditors and denominations without auditor are
+ * skipped. Runs in its own read-only transaction (hence no session
+ * provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_iterate_auditor_denominations (
+ void *cls,
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pc = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct AuditorDenomsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+ struct TALER_EXCHANGEDB_Session *session;
+
+ session = postgres_get_session (pc);
+ if (NULL == session)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return GNUNET_PQ_eval_prepared_multi_select (session->conn,
+ "select_auditor_denoms",
+ params,
+ &auditor_denoms_cb_helper,
+ &dic);
+}
+
+
+/**
* Get the summary of a reserve.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
@@ -8208,6 +8710,11 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->insert_denomination_info = &postgres_insert_denomination_info;
plugin->get_denomination_info = &postgres_get_denomination_info;
plugin->iterate_denomination_info = &postgres_iterate_denomination_info;
+ plugin->iterate_denominations = &postgres_iterate_denominations;
+ plugin->iterate_active_signkeys = &postgres_iterate_active_signkeys;
+ plugin->iterate_active_auditors = &postgres_iterate_active_auditors;
+ plugin->iterate_auditor_denominations =
+ &postgres_iterate_auditor_denominations;
plugin->reserves_get = &postgres_reserves_get;
plugin->reserves_in_insert = &postgres_reserves_in_insert;
plugin->get_latest_reserve_in_reference =
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index b1686ab65..57254787c 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -294,6 +294,105 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
/**
+ * Signature of a function called with information about the exchange's
+ * denomination keys.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param denom_pub public key of the denomination
+ * @param h_denom_pub hash of @a denom_pub
+ * @param meta meta data information about the denomination type (value, expirations, fees)
+ * @param master_sig master signature affirming the validity of this denomination
+ * @param recoup_possible true if the key was revoked and clients can currently recoup
+ * coins of this denomination
+ */
+typedef void
+(*TALER_EXCHANGEDB_DenominationsCallback)(
+ void *cls,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig,
+ bool recoup_possible);
+
+
+/**
+ * Meta data about an exchange online signing key.
+ */
+struct TALER_EXCHANGEDB_SignkeyMetaData
+{
+ /**
+ * Start time of the validity period for this key.
+ */
+ struct GNUNET_TIME_Absolute start;
+
+ /**
+ * The exchange will sign messages with this key between @e start and this time.
+ */
+ struct GNUNET_TIME_Absolute expire_sign;
+
+ /**
+ * When do signatures with this sign key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Exchange is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_sign (by a year or more).
+ */
+ struct GNUNET_TIME_Absolute expire_legal;
+
+};
+
+
+/**
+ * Signature of a function called with information about the exchange's
+ * online signing keys.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param exchange_pub public key of the exchange
+ * @param meta meta data information about the signing type (expirations)
+ * @param master_sig master signature affirming the validity of this denomination
+ */
+typedef void
+(*TALER_EXCHANGEDB_ActiveSignkeysCallback)(
+ void *cls,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig);
+
+
+/**
+ * Function called with information about the exchange's auditors.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param auditor_pub the public key of the auditor
+ * @param auditor_url URL of the REST API of the auditor
+ * @param auditor_name human readable official name of the auditor
+ */
+typedef void
+(*TALER_EXCHANGEDB_AuditorsCallback)(
+ void *cls,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name);
+
+
+/**
+ * Function called with information about the denominations
+ * audited by the exchange's auditors.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param auditor_pub the public key of an auditor
+ * @param h_denom_pub hash of a denomination key audited by this auditor
+ * @param auditor_sig signature from the auditor affirming this
+ */
+typedef void
+(*TALER_EXCHANGEDB_AuditorDenominationsCallback)(
+ void *cls,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_AuditorSignatureP *auditor_sig);
+
+
+/**
* @brief Information we keep for a withdrawn coin to reproduce
* the /withdraw operation if needed, and to have proof
* that a reserve was drained by this amount.
@@ -1778,6 +1877,73 @@ struct TALER_EXCHANGEDB_Plugin
TALER_EXCHANGEDB_DenominationCallback cb,
void *cb_cls);
+
+ /**
+ * Function called to invoke @a cb on every known denomination key (revoked
+ * and non-revoked) that has been signed by the master key. Runs in its own
+ * read-only transaction (hence no session provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*iterate_denominations)(void *cls,
+ TALER_EXCHANGEDB_DenominationsCallback cb,
+ void *cb_cls);
+
+ /**
+ * Function called to invoke @a cb on every non-revoked exchange signing key
+ * that has been signed by the master key. Revoked and (for signing!)
+ * expired keys are skipped. Runs in its own read-only transaction (hence no
+ * session provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each signing key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*iterate_active_signkeys)(void *cls,
+ TALER_EXCHANGEDB_ActiveSignkeysCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Function called to invoke @a cb on every active auditor. Disabled
+ * auditors are skipped. Runs in its own read-only transaction (hence no
+ * session provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*iterate_active_auditors)(void *cls,
+ TALER_EXCHANGEDB_AuditorsCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Function called to invoke @a cb on every denomination with an active
+ * auditor. Disabled auditors and denominations without auditor are
+ * skipped. Runs in its own read-only transaction (hence no session
+ * provided).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor-denomination pair
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*iterate_auditor_denominations)(
+ void *cls,
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+ void *cb_cls);
+
+
/**
* Get the summary of a reserve.
*