aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exchangedb/0003-aml_history.sql2
-rw-r--r--src/exchangedb/0003-aml_staff.sql3
-rw-r--r--src/exchangedb/0003-aml_status.sql2
-rw-r--r--src/exchangedb/pg_lookup_kyc_process_by_account.c3
-rw-r--r--src/exchangedb/pg_select_purse.c28
-rw-r--r--src/include/taler_crypto_lib.h40
-rw-r--r--src/include/taler_exchangedb_plugin.h307
-rw-r--r--src/lib/exchange_api_common.c17
-rw-r--r--src/testing/test_exchange_p2p.c14
-rw-r--r--src/util/offline_signatures.c8
10 files changed, 382 insertions, 42 deletions
diff --git a/src/exchangedb/0003-aml_history.sql b/src/exchangedb/0003-aml_history.sql
index 009f79d89..d3650f6c6 100644
--- a/src/exchangedb/0003-aml_history.sql
+++ b/src/exchangedb/0003-aml_history.sql
@@ -57,7 +57,7 @@ BEGIN
,partition_suffix
);
PERFORM comment_partitioned_column(
- '0 for AML decision required, 1 for AML is OK, -1 for account is frozen (prevents further transactions)'
+ '0 for all OK, 1 for AML decision required, 2 for account is frozen (prevents further transactions)'
,'new_status'
,table_name
,partition_suffix
diff --git a/src/exchangedb/0003-aml_staff.sql b/src/exchangedb/0003-aml_staff.sql
index dca0fc8d5..00f60985a 100644
--- a/src/exchangedb/0003-aml_staff.sql
+++ b/src/exchangedb/0003-aml_staff.sql
@@ -21,6 +21,7 @@ CREATE TABLE aml_staff
,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
,decider_name VARCHAR NOT NULL
,is_active BOOLEAN NOT NULL
+ ,read_only BOOLEAN NOT NULL
,last_change INT8 NOT NULL
);
COMMENT ON TABLE aml_staff
@@ -33,5 +34,7 @@ COMMENT ON COLUMN aml_staff.decider_name
IS 'Name of the staff member.';
COMMENT ON COLUMN aml_staff.is_active
IS 'true if we are currently supporting the use of this AML staff member.';
+COMMENT ON COLUMN aml_staff.is_active
+ IS 'true if the member has read-only access.';
COMMENT ON COLUMN aml_staff.last_change
IS 'Latest time when active status changed. Used to detect replays of old messages.';
diff --git a/src/exchangedb/0003-aml_status.sql b/src/exchangedb/0003-aml_status.sql
index 1e676bc1c..c0683c0d8 100644
--- a/src/exchangedb/0003-aml_status.sql
+++ b/src/exchangedb/0003-aml_status.sql
@@ -53,7 +53,7 @@ BEGIN
,partition_suffix
);
PERFORM comment_partitioned_column(
- '0 for AML decision required, 1 for AML is OK, -1 for account is frozen (prevents further transactions)'
+ '0 for all OK, 1 for AML decision required, 2 for account is frozen (prevents further transactions)'
,'status'
,table_name
,partition_suffix
diff --git a/src/exchangedb/pg_lookup_kyc_process_by_account.c b/src/exchangedb/pg_lookup_kyc_process_by_account.c
index 6183ae7af..79a9d6c8f 100644
--- a/src/exchangedb/pg_lookup_kyc_process_by_account.c
+++ b/src/exchangedb/pg_lookup_kyc_process_by_account.c
@@ -25,6 +25,7 @@
#include "pg_lookup_kyc_process_by_account.h"
#include "pg_helper.h"
+
enum GNUNET_DB_QueryStatus
TEH_PG_lookup_kyc_process_by_account (
void *cls,
@@ -59,7 +60,7 @@ TEH_PG_lookup_kyc_process_by_account (
*provider_account_id = NULL;
*provider_legitimization_id = NULL;
- /* Used in #postgres_lookup_kyc_process_by_account() */
+ /* Used in #postgres_lookup_kyc_process_by_account() */
PREPARE (pg,
"lookup_process_by_account",
"SELECT "
diff --git a/src/exchangedb/pg_select_purse.c b/src/exchangedb/pg_select_purse.c
index 9143e8721..6496d4a28 100644
--- a/src/exchangedb/pg_select_purse.c
+++ b/src/exchangedb/pg_select_purse.c
@@ -66,20 +66,20 @@ TEH_PG_select_purse (
PREPARE (pg,
"select_purse",
"SELECT "
- " merge_pub"
- ",purse_creation"
- ",purse_expiration"
- ",h_contract_terms"
- ",amount_with_fee_val"
- ",amount_with_fee_frac"
- ",balance_val"
- ",balance_frac"
- ",merge_timestamp"
- ",purse_sig IS NOT NULL AS purse_deleted"
- " FROM purse_requests"
- " LEFT JOIN purse_merges USING (purse_pub)"
- " LEFT JOIN purse_deletion USING (purse_pub)"
- " WHERE purse_pub=$1;");
+ " pr.merge_pub"
+ ",pr.purse_creation"
+ ",pr.purse_expiration"
+ ",pr.h_contract_terms"
+ ",pr.amount_with_fee_val"
+ ",pr.amount_with_fee_frac"
+ ",pr.balance_val"
+ ",pr.balance_frac"
+ ",pm.merge_timestamp"
+ ",pd.purse_sig IS NOT NULL AS purse_deleted"
+ " FROM purse_requests pr"
+ " LEFT JOIN purse_merges pm ON (pm.purse_pub = pr.purse_pub)"
+ " LEFT JOIN purse_deletion pd ON (pd.purse_pub = pr.purse_pub)"
+ " WHERE pr.purse_pub=$1;");
*merge_timestamp = GNUNET_TIME_UNIT_FOREVER_TS;
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"select_purse",
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index d63fd7ccd..5e7ea6059 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -147,6 +147,18 @@ struct TALER_ReserveSignatureP
/**
+ * (Symmetric) key used to encrypt KYC attribute data in the database.
+ */
+struct TALER_AttributeKeyP
+{
+ /**
+ * Actual key material.
+ */
+ struct GNUNET_HashCode key;
+};
+
+
+/**
* @brief Type of public keys to for merchant authorizations.
* Merchants can issue refunds using the corresponding
* private key.
@@ -537,6 +549,30 @@ struct TALER_AmlOfficerSignatureP
/**
+ * Bitmask with possible AML decision states.
+ */
+enum TALER_AmlDecisionState
+{
+
+ /**
+ * All AML requirements are currently satisfied.
+ */
+ TALER_AML_NONE = 0,
+
+ /**
+ * An AML investigation is pending.
+ */
+ TALER_AML_PENDING = 1,
+
+ /**
+ * An AML decision has concluded that the funds must be frozen.
+ */
+ TALER_AML_FROZEN = 2
+
+};
+
+
+/**
* @brief Type of blinding keys for Taler.
* must be 32 bytes (DB)
*/
@@ -4597,6 +4633,7 @@ TALER_exchange_online_purse_status_verify (
* @param officer_name name of the officer
* @param change_date when to affect the status change
* @param is_active true to enable the officer
+ * @param read_only true to only allow read-only access
* @param master_priv private key to sign with
* @param[out] master_sig where to write the signature
*/
@@ -4606,6 +4643,7 @@ TALER_exchange_offline_aml_officer_status_sign (
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
+ bool read_only,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig);
@@ -4617,6 +4655,7 @@ TALER_exchange_offline_aml_officer_status_sign (
* @param officer_name name of the officer
* @param change_date when to affect the status change
* @param is_active true to enable the officer
+ * @param read_only true to only allow read-only access
* @param master_pub public key to verify against
* @param master_sig the signature the signature
* @return #GNUNET_OK if the signature is valid
@@ -4627,6 +4666,7 @@ TALER_exchange_offline_aml_officer_status_verify (
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
+ bool read_only,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index da28262a8..bba593553 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -2245,6 +2245,31 @@ typedef void
/**
+ * Callback with KYC attributes about a particular user.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param provider_section provider that must be checked
+ * @param birthdate birthdate of user, in format YYYY-MM-DD; can be NULL;
+ * digits can be 0 if exact day, month or year are unknown
+ * @param collection_time when was the data collected
+ * @param expiration_time when does the data expire
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ */
+typedef void
+(*TALER_EXCHANGEDB_AttributeCallback)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ const char *provider_section,
+ const char *birthdate,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+
+/**
* Function called with details about deposits that have been made,
* with the goal of auditing the deposit's execution.
*
@@ -3101,6 +3126,46 @@ typedef void
/**
+ * Return AML status.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param h_payto account for which the attribute data is stored
+ * @param threshold currently monthly threshold that would trigger an AML check
+ * @param decision_time when was the last decision made
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlStatusCallback)(
+ void *cls,
+ uint64_t row_id,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct TALER_Amount *threshold,
+ enum TALER_AmlDecisionState status);
+
+
+/**
+ * Return historic AML decision.
+ *
+ * @param cls closure
+ * @param new_threshold new monthly threshold that would trigger an AML check
+ * @param new_status AML decision status
+ * @param decision_time when was the decision made
+ * @param justification human-readable text justifying the decision
+ * @param decider_pub public key of the staff member
+ * @param decider_sig signature of the staff member
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlHistoryCallback)(
+ void *cls,
+ const struct TALER_Amount *new_threshold,
+ enum TALER_AmlDecisionState new_status,
+ struct GNUNET_TIME_Absolute decision_time,
+ const char *justification,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_AmlOfficerSignatureP *decider_sig);
+
+
+/**
* @brief The plugin API, returned from the plugin's "init" function.
* The argument given to "init" is simply a configuration handle.
*/
@@ -6435,6 +6500,248 @@ struct TALER_EXCHANGEDB_Plugin
void *kac_cls);
+ // FIXME: functions below here not yet implemented!
+
+ /**
+ * Store KYC attribute data.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param kyc_prox key for similarity search
+ * @param provider_section provider that must be checked
+ * @param birthdate birthdate of user, in format YYYY-MM-DD; can be NULL;
+ * digits can be 0 if exact day, month or year are unknown
+ * @param collection_time when was the data collected
+ * @param expiration_time when does the data expire
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*insert_kyc_attributes)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct GNUNET_ShortHashCode *kyc_prox,
+ const char *provider_section,
+ const char *birthdate,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+
+ /**
+ * Update KYC attribute data.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param kyc_prox key for similarity search
+ * @param provider_section provider that must be checked
+ * @param birthdate birthdate of user, in format YYYY-MM-DD; can be NULL;
+ * digits can be 0 if exact day, month or year are unknown
+ * @param collection_time when was the data collected
+ * @param expiration_time when does the data expire
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*update_kyc_attributes)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct GNUNET_ShortHashCode *kyc_prox,
+ const char *provider_section,
+ const char *birthdate,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+
+ /**
+ * Lookup similar KYC attribute data.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param kyc_prox key for similarity search
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*select_similar_kyc_attributes)(
+ void *cls,
+ const struct GNUNET_ShortHashCode *kyc_prox,
+ TALER_EXCHANGEDB_AttributeCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Lookup KYC attribute data for a specific account.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*select_kyc_attributes)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AttributeCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Insert AML staff record.
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param master_sig offline signature affirming the AML officer
+ * @param decider_name full name of the staff member
+ * @param is_active true to enable, false to set as inactive
+ * @param read_only true to set read-only access
+ * @param last_change when was the change made effective
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*insert_aml_officer)(
+ void *cls,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *decider_name,
+ bool is_active,
+ bool read_only,
+ struct GNUNET_TIME_Absolute last_change);
+
+
+ /**
+ * Update AML staff record.
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param master_sig offline signature affirming the AML officer
+ * @param decider_name full name of the staff member
+ * @param is_active true to enable, false to set as inactive
+ * @param read_only true to set read-only access
+ * @param last_change when was the change made effective
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*update_aml_officer)(
+ void *cls,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *decider_name,
+ bool is_active,
+ bool read_only,
+ struct GNUNET_TIME_Absolute last_change);
+
+
+ /**
+ * Fetch AML staff record.
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param[out] master_sig offline signature affirming the AML officer
+ * @param[out] decider_name full name of the staff member
+ * @param[out] is_active true to enable, false to set as inactive
+ * @param[out] read_only true to set read-only access
+ * @param[out] last_change when was the change made effective
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_aml_officer)(
+ void *cls,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ struct TALER_MasterSignatureP *master_sig,
+ char **decider_name,
+ bool *is_active,
+ bool *read_only,
+ struct GNUNET_TIME_Absolute *last_change);
+
+
+ /**
+ * Trigger AML process, an account has crossed the threshold. Inserts or
+ * updates the AML status.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param threshold_crossed existing threshold that was crossed
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*trigger_aml_process)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct TALER_Amount *threshold_crossed);
+
+
+ /**
+ * Lookup AML decisions that have a particular state.
+ *
+ * @param cls closure
+ * @param decision which decision states to filter by
+ * @param row_off offset to start from
+ * @param forward true to go forward in time, false to go backwards
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*select_aml_processes)(
+ void *cls,
+ enum TALER_AmlDecisionState decision,
+ uint64_t row_off,
+ bool forward,
+ TALER_EXCHANGEDB_AmlStatusCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Lookup AML decision history for a particular account.
+ *
+ * @param cls closure
+ * @param h_payto which account should we return the AML decision history for
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*select_aml_history)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlHistoryCallback cb,
+ void *cb_cls);
+
+
+ /**
+ * Insert an AML decision. Inserts into AML history and insert or updates AML
+ * status.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param new_threshold new monthly threshold that would trigger an AML check
+ * @param new_status AML decision status
+ * @param decision_time when was the decision made
+ * @param justification human-readable text justifying the decision
+ * @param decider_pub public key of the staff member
+ * @param decider_sig signature of the staff member
+ * @return database transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*insert_aml_decision)(
+ void *cls,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct TALER_Amount *new_threshold,
+ enum TALER_AmlDecisionState new_status,
+ struct GNUNET_TIME_Absolute decision_time,
+ const char *justification,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_AmlOfficerSignatureP *decider_sig);
+
+
};
#endif /* _TALER_EXCHANGE_DB_H */
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index 3807b997f..b895bf9a8 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -1336,15 +1336,11 @@ help_purse_deposit (struct CoinHistoryParseContext *pc,
}
if (refunded)
{
- /* We add the amount to refunds here, the original
- deposit will be added to the balance later because
- we still return GNUNET_YES, thus effectively
- cancelling out this operation with respect to
- the final balance. */
+ /* We wave the deposit fee. */
if (0 >
TALER_amount_add (&pc->rtotal,
&pc->rtotal,
- amount))
+ &pc->dk->fees.deposit))
{
/* overflow in refund history? inconceivable! Bad exchange! */
GNUNET_break_op (0);
@@ -1415,15 +1411,6 @@ help_purse_refund (struct CoinHistoryParseContext *pc,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- if (0 >
- TALER_amount_add (&pc->rtotal,
- &pc->rtotal,
- amount))
- {
- /* overflow in refund history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
return GNUNET_NO;
}
diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c
index ad95bf63c..7c3bdd57e 100644
--- a/src/testing/test_exchange_p2p.c
+++ b/src/testing/test_exchange_p2p.c
@@ -174,17 +174,17 @@ run (void *cls,
TALER_TESTING_cmd_purse_create_with_deposit (
"purse-with-deposit",
MHD_HTTP_OK,
- "{\"amount\":\"EUR:1\",\"summary\":\"ice cream\"}",
+ "{\"amount\":\"EUR:0.99\",\"summary\":\"ice cream\"}",
true, /* upload contract */
GNUNET_TIME_UNIT_MINUTES, /* expiration */
"withdraw-coin-1",
- "EUR:1.01",
+ "EUR:1.00",
NULL),
TALER_TESTING_cmd_purse_poll (
"push-poll-purse-before-merge",
MHD_HTTP_OK,
"purse-with-deposit",
- "EUR:1",
+ "EUR:0.99",
true,
GNUNET_TIME_UNIT_MINUTES),
TALER_TESTING_cmd_contract_get (
@@ -206,13 +206,13 @@ run (void *cls,
TALER_TESTING_cmd_status (
"push-check-post-merge-reserve-balance-get",
"create-reserve-1",
- "EUR:1.03",
+ "EUR:1.02",
MHD_HTTP_OK),
/* POST history doesn't yet support P2P transfers */
TALER_TESTING_cmd_reserve_status (
"push-check-post-merge-reserve-balance-post",
"create-reserve-1",
- "EUR:1.03",
+ "EUR:1.02",
MHD_HTTP_OK),
/* Test conflicting merge */
TALER_TESTING_cmd_purse_merge (
@@ -261,12 +261,12 @@ run (void *cls,
TALER_TESTING_cmd_status (
"pull-check-post-merge-reserve-balance-get",
"create-reserve-1",
- "EUR:2.02",
+ "EUR:2.01",
MHD_HTTP_OK),
TALER_TESTING_cmd_reserve_status (
"push-check-post-merge-reserve-balance-post",
"create-reserve-1",
- "EUR:2.02",
+ "EUR:2.01",
MHD_HTTP_OK),
/* create 2nd purse for a deposit conflict */
TALER_TESTING_cmd_purse_create_with_reserve (
diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c
index d6638998b..b1e3b93a3 100644
--- a/src/util/offline_signatures.c
+++ b/src/util/offline_signatures.c
@@ -54,7 +54,7 @@ struct TALER_MasterAmlOfficerStatusPS
struct GNUNET_HashCode h_officer_name GNUNET_PACKED;
/**
- * 1 if enabled, 0 if disabled, in NBO.
+ * Bitmask: 1 if enabled; 2 for read-only access. in NBO.
*/
uint32_t is_active GNUNET_PACKED;
};
@@ -67,6 +67,7 @@ TALER_exchange_offline_aml_officer_status_sign (
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
+ bool read_only,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
{
@@ -75,7 +76,7 @@ TALER_exchange_offline_aml_officer_status_sign (
.purpose.size = htonl (sizeof (as)),
.change_date = GNUNET_TIME_timestamp_hton (change_date),
.officer_pub = *officer_pub,
- .is_active = htonl (is_active ? 1 : 0)
+ .is_active = htonl ((is_active ? 1 : 0) + (read_only ? 2 : 0))
};
GNUNET_CRYPTO_hash (officer_name,
@@ -93,6 +94,7 @@ TALER_exchange_offline_aml_officer_status_verify (
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
+ bool read_only,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig)
{
@@ -101,7 +103,7 @@ TALER_exchange_offline_aml_officer_status_verify (
.purpose.size = htonl (sizeof (as)),
.change_date = GNUNET_TIME_timestamp_hton (change_date),
.officer_pub = *officer_pub,
- .is_active = htonl (is_active ? 1 : 0)
+ .is_active = htonl ((is_active ? 1 : 0) + (read_only ? 2 : 0))
};
GNUNET_CRYPTO_hash (officer_name,