first steps towards age restriction support for coin refresh

This commit is contained in:
Özgür Kesim 2022-01-23 18:27:31 +01:00
parent 8684a9bfea
commit 2b85559c06
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
12 changed files with 79 additions and 2 deletions

View File

@ -1227,6 +1227,7 @@ static int
refresh_session_cb (void *cls,
uint64_t rowid,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_AgeHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_Amount *amount_with_fee,
@ -1289,6 +1290,7 @@ refresh_session_cb (void *cls,
&fee_refresh,
rc,
&h_denom_pub,
h_age_commitment,
coin_pub,
coin_sig))
{

View File

@ -278,6 +278,7 @@ check_melt_valid (struct MHD_Connection *connection,
&mret);
if (NULL == dk)
return mret;
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_legal.abs_time))
{
/* Way too late now, even zombies have expired */
@ -287,6 +288,7 @@ check_melt_valid (struct MHD_Connection *connection,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
"MELT");
}
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
{
/* This denomination is not yet valid */
@ -299,6 +301,7 @@ check_melt_valid (struct MHD_Connection *connection,
rmc->coin_refresh_fee = dk->meta.fee_refresh;
rmc->coin_value = dk->meta.value;
/* sanity-check that "total melt amount > melt fee" */
if (0 <
TALER_amount_cmp (&rmc->coin_refresh_fee,
@ -328,6 +331,7 @@ check_melt_valid (struct MHD_Connection *connection,
&rmc->coin_refresh_fee,
&rmc->refresh_session.rc,
&rmc->refresh_session.coin.denom_pub_hash,
&rmc->refresh_session.coin.age_commitment_hash,
&rmc->refresh_session.coin.coin_pub,
&rmc->refresh_session.coin_sig))
{
@ -403,6 +407,9 @@ TEH_handler_melt (struct MHD_Connection *connection,
&rmc.refresh_session.coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&rmc.refresh_session.coin.denom_pub_hash),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("age_commitment_hash",
&rmc.refresh_session.coin.age_commitment_hash)),
GNUNET_JSON_spec_fixed_auto ("confirm_sig",
&rmc.refresh_session.coin_sig),
TALER_JSON_spec_amount ("value_with_fee",

View File

@ -122,6 +122,7 @@ TEH_RESPONSE_compile_transaction_history (
{
const struct TALER_EXCHANGEDB_MeltListEntry *melt =
pos->details.melt;
const struct TALER_AgeHash *phac = NULL;
#if ENABLE_SANITY_CHECKS
if (GNUNET_OK !=
@ -129,6 +130,7 @@ TEH_RESPONSE_compile_transaction_history (
&melt->melt_fee,
&melt->rc,
&melt->h_denom_pub,
&melt->h_age_commitment,
coin_pub,
&melt->coin_sig))
{
@ -137,6 +139,12 @@ TEH_RESPONSE_compile_transaction_history (
return NULL;
}
#endif
/* Age restriction is optional. We communicate a NULL value to
* JSON_PACK below */
if (! TALER_AgeHash_isZero (&melt->h_age_commitment))
phac = &melt->h_age_commitment;
if (0 !=
json_array_append_new (
history,
@ -151,6 +159,9 @@ TEH_RESPONSE_compile_transaction_history (
&melt->rc),
GNUNET_JSON_pack_data_auto ("h_denom_pub",
&melt->h_denom_pub),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_auto ("h_age_commitment",
phac)),
GNUNET_JSON_pack_data_auto ("coin_sig",
&melt->coin_sig))))
{

View File

@ -342,6 +342,7 @@ CREATE TABLE IF NOT EXISTS refresh_commitments
(melt_serial_id BIGSERIAL -- UNIQUE
,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,h_age_commitment BYTEA CHECK(LENGTH(h_age_commitment)=32)
,old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64)
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
@ -356,6 +357,8 @@ COMMENT ON COLUMN refresh_commitments.rc
IS 'Commitment made by the client, hash over the various client inputs in the cut-and-choose protocol';
COMMENT ON COLUMN refresh_commitments.old_coin_pub
IS 'Coin being melted in the refresh process.';
COMMENT ON COLUMN refresh_commitments.h_age_commitment
IS '(optional) age commitment that was involved in the minting process of the coin, may be NULL.';
CREATE TABLE IF NOT EXISTS refresh_commitments_default
PARTITION OF refresh_commitments
FOR VALUES WITH (MODULUS 1, REMAINDER 0);

View File

@ -848,6 +848,7 @@ prepare_statements (struct PostgresClosure *pg)
"SELECT"
" denom.denom_pub"
",kc.coin_pub AS old_coin_pub"
",h_age_commitment"
",old_coin_sig"
",amount_with_fee_val"
",amount_with_fee_frac"
@ -8202,6 +8203,8 @@ refreshs_serial_helper_cb (void *cls,
struct TALER_DenominationPublicKey denom_pub;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_AgeHash h_age_commitment;
bool ac_isnull;
struct TALER_Amount amount_with_fee;
uint32_t noreveal_index;
uint64_t rowid;
@ -8209,6 +8212,10 @@ refreshs_serial_helper_cb (void *cls,
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_result_spec_denom_pub ("denom_pub",
&denom_pub),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_auto_from_type ("h_age_commitment",
&h_age_commitment),
&ac_isnull),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
&coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
@ -8234,9 +8241,11 @@ refreshs_serial_helper_cb (void *cls,
rsc->status = GNUNET_SYSERR;
return;
}
ret = rsc->cb (rsc->cb_cls,
rowid,
&denom_pub,
ac_isnull ? NULL : &h_age_commitment,
&coin_pub,
&coin_sig,
&amount_with_fee,

View File

@ -459,6 +459,7 @@ static unsigned int auditor_row_cnt;
* @param cls closure
* @param rowid unique serial ID for the refresh session in our DB
* @param denom_pub denomination of the @a coin_pub
* @param h_age_commitment hash of age commitment that went into the minting, may be NULL
* @param coin_pub public key of the coin
* @param coin_sig signature from the coin
* @param amount_with_fee amount that was deposited including fee
@ -471,6 +472,7 @@ static enum GNUNET_GenericReturnValue
audit_refresh_session_cb (void *cls,
uint64_t rowid,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_AgeHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_Amount *amount_with_fee,

View File

@ -311,6 +311,9 @@ struct TALER_AgeHash
struct GNUNET_ShortHashCode shash;
};
bool
TALER_AgeHash_isZero (
const struct TALER_AgeHash *hash);
/**
* @brief Type of public keys for Taler coins. The same key material is used
@ -712,7 +715,8 @@ struct TALER_CoinPublicInfo
struct TALER_DenominationHash denom_pub_hash;
/**
* Hash of the age commitment.
* Hash of the age commitment. If no age commitment was provided, it must be
* set to all zeroes.
*/
struct TALER_AgeHash age_commitment_hash;
@ -1763,6 +1767,7 @@ TALER_wallet_melt_sign (
* @param melt_fee the melt fee we expect to pay
* @param rc refresh session we are committed to
* @param h_denom_pub hash of the coin denomination's public key
* @param h_age_commitment hash of the age commitment (may be NULL)
* @param coin_pub coins public key
* @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT
* @return #GNUNET_OK if the signature is valid
@ -1773,6 +1778,7 @@ TALER_wallet_melt_verify (
const struct TALER_Amount *melt_fee,
const struct TALER_RefreshCommitmentP *rc,
const struct TALER_DenominationHash *h_denom_pub,
const struct TALER_AgeHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig);

View File

@ -1305,6 +1305,12 @@ struct TALER_EXCHANGEDB_MeltListEntry
*/
struct TALER_DenominationHash h_denom_pub;
/**
* Hash of the age commitment used to sign the coin. May be all zeroes if no
* age restriction applies.
*/
struct TALER_AgeHash h_age_commitment;
/**
* How much value is being melted? This amount includes the fees,
* so the final amount contributed to the melt is this value minus
@ -1585,6 +1591,7 @@ typedef enum GNUNET_GenericReturnValue
* @param cls closure
* @param rowid unique serial ID for the refresh session in our DB
* @param denom_pub denomination public key of @a coin_pub
* @param h_age_commitment age commitment that went into the signing of the coin, may be NULL
* @param coin_pub public key of the coin
* @param coin_sig signature from the coin
* @param amount_with_fee amount that was deposited including fee
@ -1597,6 +1604,7 @@ typedef enum GNUNET_GenericReturnValue
void *cls,
uint64_t rowid,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_AgeHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_Amount *amount_with_fee,

View File

@ -711,6 +711,13 @@ struct TALER_RefreshMeltCoinAffirmationPS
*/
struct TALER_DenominationHash h_denom_pub GNUNET_PACKED;
/**
* If age commitment was provided during the withdrawal of the coin, this is
* the hash of the age commitment vector. It must be all zeroes if no age
* commitment was provided.
*/
struct TALER_AgeHash h_age_commitment GNUNET_PACKED;
/**
* How much of the value of the coin should be melted? This amount
* includes the fees, so the final amount contributed to the melt is

View File

@ -548,6 +548,7 @@ TALER_EXCHANGE_verify_coin_history (
{
struct TALER_CoinSpendSignatureP sig;
struct TALER_RefreshCommitmentP rc;
struct TALER_AgeHash h_age_commitment = {0};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&sig),
@ -555,6 +556,9 @@ TALER_EXCHANGE_verify_coin_history (
&rc),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
&h_age_commitment)),
TALER_JSON_spec_amount_any ("melt_fee",
&fee),
GNUNET_JSON_spec_end ()
@ -568,6 +572,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (NULL != dk)
{
/* check that melt fee matches our expectations from /keys! */
@ -582,11 +587,14 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR;
}
}
if (GNUNET_OK !=
TALER_wallet_melt_verify (&amount,
&fee,
&rc,
h_denom_pub,
TALER_AgeHash_isZero (&h_age_commitment) ?
NULL : &h_age_commitment,
coin_pub,
&sig))
{

View File

@ -352,4 +352,13 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
}
bool
TALER_AgeHash_isZero (
const struct TALER_AgeHash *hash)
{
static struct TALER_AgeHash zeroAgeHash = {0};
return (0 == memcmp (hash, &zeroAgeHash, sizeof(struct TALER_AgeHash)));
}
/* end of crypto.c */

View File

@ -267,6 +267,7 @@ TALER_wallet_melt_verify (
const struct TALER_Amount *melt_fee,
const struct TALER_RefreshCommitmentP *rc,
const struct TALER_DenominationHash *h_denom_pub,
const struct TALER_AgeHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig)
{
@ -274,9 +275,13 @@ TALER_wallet_melt_verify (
.purpose.size = htonl (sizeof (melt)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT),
.rc = *rc,
.h_denom_pub = *h_denom_pub
.h_denom_pub = *h_denom_pub,
};
memset (&melt.h_age_commitment, 0, sizeof(struct TALER_AgeHash));
if (NULL != h_age_commitment)
melt.h_age_commitment = *h_age_commitment;
TALER_amount_hton (&melt.amount_with_fee,
amount_with_fee);
TALER_amount_hton (&melt.melt_fee,