/*
This file is part of TALER
Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
*/
/**
* @file exchangedb/perf_taler_exchangedb_init.c
* @brief Interpreter library for exchange database performance analysis
* @author Nicolas Fournier
* @author Christian Grothoff
*/
#include "platform.h"
#include "perf_taler_exchangedb_init.h"
#include
#include "taler_signatures.h"
#include "taler_amount_lib.h"
#define CURRENCY "EUR"
#define PERF_TALER_EXCHANGEDB_RSA_SIZE 512
/**
* Generate a dummy DenominationKeyInformation for testing purposes
* @return a dummy denomination key
*/
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *
PERF_TALER_EXCHANGEDB_denomination_init ()
{
struct GNUNET_CRYPTO_EddsaPrivateKey *master_prvt;
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
struct TALER_DenominationPrivateKey denom_priv;
struct TALER_DenominationPublicKey denom_pub;
struct TALER_EXCHANGEDB_DenominationKeyInformationP issue;
master_prvt = GNUNET_CRYPTO_eddsa_key_create ();
dki = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyIssueInformation);
GNUNET_assert (NULL != dki);
denom_priv.rsa_private_key
= GNUNET_CRYPTO_rsa_private_key_create (PERF_TALER_EXCHANGEDB_RSA_SIZE);
GNUNET_assert (NULL != denom_priv.rsa_private_key);
denom_pub.rsa_public_key =
GNUNET_CRYPTO_rsa_private_key_get_public (denom_priv.rsa_private_key);
GNUNET_assert (NULL != denom_pub.rsa_public_key);
{/* issue */
struct TALER_MasterSignatureP signature;
struct TALER_DenominationKeyValidityPS properties;
{/* properties */
struct TALER_Amount amount;
struct GNUNET_TIME_Absolute now;
properties.purpose.purpose = htonl (
TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
properties.purpose.size = htonl (sizeof (struct
TALER_DenominationKeyValidityPS));
GNUNET_CRYPTO_eddsa_key_get_public (master_prvt,
&properties.master.eddsa_pub);
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
properties.start = GNUNET_TIME_absolute_hton (now);
properties.expire_withdraw = GNUNET_TIME_absolute_hton (
GNUNET_TIME_UNIT_FOREVER_ABS);
properties.expire_deposit = GNUNET_TIME_absolute_hton (
GNUNET_TIME_UNIT_FOREVER_ABS);
properties.expire_legal = GNUNET_TIME_absolute_hton (
GNUNET_TIME_UNIT_FOREVER_ABS);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.1", &amount));
TALER_amount_hton (&properties.value, &amount);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.1", &amount));
TALER_amount_hton (&properties.fee_withdraw, &amount);
TALER_amount_hton (&properties.fee_deposit, &amount);
TALER_amount_hton (&properties.fee_refresh, &amount);
TALER_amount_hton (&properties.fee_refund, &amount);
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
&properties.denom_hash);
issue.properties = properties;
}
{/* signature */
GNUNET_CRYPTO_eddsa_sign (master_prvt,
&properties.purpose,
&signature.eddsa_signature);
issue.signature = signature;
}
}
dki->denom_priv = denom_priv;
dki->denom_pub = denom_pub;
dki->issue = issue;
GNUNET_free (master_prvt);
return dki;
}
/**
* Copies the given denomination
* @param reserve the deposit copy
* @return a copy of @a deposit; NULL if error
*/
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *
PERF_TALER_EXCHANGEDB_denomination_copy (const struct
TALER_EXCHANGEDB_DenominationKeyIssueInformation
*dki)
{
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *copy;
GNUNET_assert (NULL !=
(copy = GNUNET_new (struct
TALER_EXCHANGEDB_DenominationKeyIssueInformation)));
{/* denom_priv */
copy->denom_priv.rsa_private_key =
GNUNET_CRYPTO_rsa_private_key_dup (dki->denom_priv.rsa_private_key);
}
{/* denom_pub */
copy->denom_pub.rsa_public_key =
GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key);
}
{/* issue */
copy->issue.properties = dki->issue.properties;
copy->issue.signature = dki->issue.signature;
}
return copy;
}
/**
* Free memory of a DenominationKeyIssueInformation
* @param dki pointer to the struct to free
*/
int
PERF_TALER_EXCHANGEDB_denomination_free (struct
TALER_EXCHANGEDB_DenominationKeyIssueInformation
*dki)
{
if (NULL == dki)
return GNUNET_OK;
GNUNET_CRYPTO_rsa_private_key_free (dki->denom_priv.rsa_private_key);
GNUNET_CRYPTO_rsa_public_key_free (dki->denom_pub.rsa_public_key);
GNUNET_free (dki);
return GNUNET_OK;
}
/**
* Generate a dummy reserve for testing
* @return a reserve with 1000 EUR in it
*/
struct PERF_TALER_EXCHANGEDB_Reserve *
PERF_TALER_EXCHANGEDB_reserve_init ()
{
struct PERF_TALER_EXCHANGEDB_Reserve *reserve;
GNUNET_assert (NULL !=
(reserve = GNUNET_new (struct PERF_TALER_EXCHANGEDB_Reserve)));
{/* private */
struct GNUNET_CRYPTO_EddsaPrivateKey *private;
private = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_assert (NULL != private);
reserve->private = *private;
GNUNET_free (private);
}
GNUNET_CRYPTO_eddsa_key_get_public (&reserve->private,
&reserve->reserve.pub.eddsa_pub);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1000",
&reserve->reserve.balance));
reserve->reserve.expiry = GNUNET_TIME_UNIT_FOREVER_ABS;
return reserve;
}
/**
* Copies the given reserve
* @param reserve the reserve to copy
* @return a copy of @a reserve; NULL if error
*/
struct PERF_TALER_EXCHANGEDB_Reserve *
PERF_TALER_EXCHANGEDB_reserve_copy (const struct
PERF_TALER_EXCHANGEDB_Reserve *reserve)
{
struct PERF_TALER_EXCHANGEDB_Reserve *copy;
GNUNET_assert (NULL !=
(copy = GNUNET_new (struct PERF_TALER_EXCHANGEDB_Reserve)));
*copy = *reserve;
return copy;
}
/**
* Free memory of a reserve
* @param reserve pointer to the structure to be freed
*/
int
PERF_TALER_EXCHANGEDB_reserve_free (struct
PERF_TALER_EXCHANGEDB_Reserve *reserve)
{
if (NULL == reserve)
return GNUNET_OK;
GNUNET_free (reserve);
return GNUNET_OK;
}
/**
* Generate a dummy deposit for testing purposes
*
* @param dki the denomination key used to sign the key
*/
struct TALER_EXCHANGEDB_Deposit *
PERF_TALER_EXCHANGEDB_deposit_init (const struct
PERF_TALER_EXCHANGEDB_Coin *coin)
{
struct TALER_EXCHANGEDB_Deposit *deposit;
struct TALER_CoinSpendSignatureP csig;
struct TALER_MerchantPublicKeyP merchant_pub;
struct GNUNET_HashCode h_contract_terms;
struct GNUNET_HashCode h_wire;
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_TIME_Absolute refund_deadline;
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
deposit = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
&h_contract_terms);
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
&h_wire);
{ // csig
struct u32_presign
{
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct GNUNET_HashCode h_wire;
struct GNUNET_HashCode h_contract_terms;
} unsigned_data;
unsigned_data.h_contract_terms = h_contract_terms;
unsigned_data.h_wire = h_wire;
unsigned_data.purpose.size = htonl (sizeof (struct u32_presign));
unsigned_data.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_eddsa_sign (&coin->priv,
&unsigned_data.purpose,
&csig.eddsa_signature));
}
{ // merchant_pub
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_prv;
eddsa_prv = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_assert (NULL != eddsa_prv);
GNUNET_CRYPTO_eddsa_key_get_public (eddsa_prv,
&merchant_pub.eddsa_pub);
GNUNET_free (eddsa_prv);
}
timestamp = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (×tamp);
refund_deadline = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&refund_deadline);
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.1",
&amount_with_fee));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.1",
&deposit_fee));
{
deposit->coin.coin_pub = coin->public_info.coin_pub;
deposit->coin.denom_pub_hash = coin->public_info.denom_pub_hash;
deposit->coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (
coin->public_info.denom_sig.rsa_signature);
GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature);
}
deposit->csig = csig;
deposit->h_contract_terms = h_contract_terms;
deposit->h_wire = h_wire;
deposit->receiver_wire_account
= json_pack ("{s:s, s:s}",
"url", "payto://iban/DE67830654080004822650",
"salt", "this-is-a-salt-value");
deposit->timestamp = timestamp;
deposit->refund_deadline = refund_deadline;
deposit->amount_with_fee = amount_with_fee;
deposit->deposit_fee = deposit_fee;
return deposit;
}
/**
* Copies the given deposit
* @param reserve the deposit copy
* @return a copy of @a deposit; NULL if error
*/
struct TALER_EXCHANGEDB_Deposit *
PERF_TALER_EXCHANGEDB_deposit_copy (const struct
TALER_EXCHANGEDB_Deposit *deposit)
{
struct TALER_EXCHANGEDB_Deposit *copy;
copy = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
*copy = *deposit;
copy->receiver_wire_account = json_incref (deposit->receiver_wire_account);
copy->coin.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (deposit->coin.denom_sig.rsa_signature);
return copy;
}
/**
* Free memory of a deposit
* @param deposit pointer to the structure to free
*/
int
PERF_TALER_EXCHANGEDB_deposit_free (struct TALER_EXCHANGEDB_Deposit *deposit)
{
if (NULL == deposit)
return GNUNET_OK;
GNUNET_CRYPTO_rsa_signature_free (deposit->coin.denom_sig.rsa_signature);
json_decref (deposit->receiver_wire_account);
GNUNET_free (deposit);
return GNUNET_OK;
}
/**
* Generate a CollectableBlindcoin for testing purpuses
* @param dki denomination key used to sign the coin
* @param reserve reserve providing the money for the coin
* @return a randomly generated CollectableBlindcoin
*/
struct PERF_TALER_EXCHANGEDB_Coin *
PERF_TALER_EXCHANGEDB_coin_init (
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki,
const struct PERF_TALER_EXCHANGEDB_Reserve *reserve)
{
struct PERF_TALER_EXCHANGEDB_Coin *coin;
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
struct GNUNET_HashCode hc;
coin = GNUNET_new (struct PERF_TALER_EXCHANGEDB_Coin);
GNUNET_assert (NULL != coin);
/* priv */
priv = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_assert (NULL != priv);
coin->priv = *priv;
GNUNET_free (priv);
/* public_info */
GNUNET_CRYPTO_eddsa_key_get_public (&coin->priv,
&coin->public_info.coin_pub.eddsa_pub);
GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key,
&coin->public_info.denom_pub_hash);
GNUNET_CRYPTO_hash (&coin->public_info.coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP),
&hc);
coin->public_info.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_sign_fdh (dki->denom_priv.rsa_private_key,
&hc);
GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature);
/* blind */
coin->blind.sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature);
coin->blind.denom_pub_hash = coin->public_info.denom_pub_hash;
GNUNET_assert (NULL != coin->blind.sig.rsa_signature);
TALER_amount_ntoh (&coin->blind.amount_with_fee,
&dki->issue.properties.value);
TALER_amount_ntoh (&coin->blind.withdraw_fee,
&dki->issue.properties.fee_withdraw);
coin->blind.reserve_pub = reserve->reserve.pub;
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
&coin->blind.h_coin_envelope);
return coin;
}
/**
* Copies the given coin
*
* @param coin the coin to copy
* @return a copy of coin; NULL if error
*/
struct PERF_TALER_EXCHANGEDB_Coin *
PERF_TALER_EXCHANGEDB_coin_copy (const struct PERF_TALER_EXCHANGEDB_Coin *coin)
{
struct PERF_TALER_EXCHANGEDB_Coin *copy;
copy = GNUNET_new (struct PERF_TALER_EXCHANGEDB_Coin);
/* priv */
copy->priv = coin->priv;
/* public_info */
copy->public_info.coin_pub = coin->public_info.coin_pub;
copy->public_info.denom_pub_hash = coin->public_info.denom_pub_hash;
copy->public_info.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature);
/* blind */
copy->blind.sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (coin->blind.sig.rsa_signature);
copy->blind.denom_pub_hash = coin->blind.denom_pub_hash;
copy->blind.amount_with_fee = coin->blind.amount_with_fee;
copy->blind.withdraw_fee = coin->blind.withdraw_fee;
copy->blind.reserve_pub = coin->blind.reserve_pub;
copy->blind.h_coin_envelope = coin->blind.h_coin_envelope;
copy->blind.reserve_sig = coin->blind.reserve_sig;
return copy;
}
/**
* Free memory of @a coin
*
* @param coin pointer to the structure to free
*/
int
PERF_TALER_EXCHANGEDB_coin_free (struct PERF_TALER_EXCHANGEDB_Coin *coin)
{
if (NULL == coin)
return GNUNET_OK;
GNUNET_CRYPTO_rsa_signature_free (coin->public_info.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_signature_free (coin->blind.sig.rsa_signature);
GNUNET_free (coin);
return GNUNET_OK;
}
/**
* Create a melt operation
*
* @param rc the commitment of the refresh session
* @param dki the denomination the melted coin uses
* @return a pointer to a #TALER_EXCHANGEDB_RefreshMelt
*/
struct TALER_EXCHANGEDB_RefreshMelt *
PERF_TALER_EXCHANGEDB_refresh_melt_init (struct TALER_RefreshCommitmentP *rc,
struct PERF_TALER_EXCHANGEDB_Coin *coin)
{
struct TALER_EXCHANGEDB_RefreshMelt *melt;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_Amount amount;
struct TALER_Amount amount_with_fee;
{
struct
{
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct TALER_RefreshCommitmentP rc;
} to_sign;
to_sign.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_TEST;
to_sign.purpose.size = htonl (sizeof (to_sign));
to_sign.rc = *rc;
GNUNET_CRYPTO_eddsa_sign (&coin->priv,
&to_sign.purpose,
&coin_sig.eddsa_signature);
}
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.1",
&amount));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":0.1",
&amount_with_fee));
melt = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
melt->session.coin.coin_pub = coin->public_info.coin_pub;
melt->session.coin.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature);
melt->session.coin.denom_pub_hash = coin->public_info.denom_pub_hash;
GNUNET_assert (NULL != melt->session.coin.denom_sig.rsa_signature);
melt->session.coin_sig = coin_sig;
melt->session.rc = *rc;
melt->session.amount_with_fee = amount;
melt->melt_fee = amount_with_fee;
return melt;
}
/**
* Copies the internals of a #TALER_EXCHANGEDB_RefreshMelt
*
* @param melt the refresh melt to copy
* @return an copy of @ melt
*/
struct TALER_EXCHANGEDB_RefreshMelt *
PERF_TALER_EXCHANGEDB_refresh_melt_copy (const struct
TALER_EXCHANGEDB_RefreshMelt *melt)
{
struct TALER_EXCHANGEDB_RefreshMelt *copy;
copy = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
*copy = *melt;
copy->session.coin.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_signature_dup (
melt->session.coin.denom_sig.rsa_signature);
GNUNET_assert (NULL != copy->session.coin.denom_sig.rsa_signature);
return copy;
}
/**
* Free the internal memory of a #TALER_EXCHANGEDB_RefreshMelt
*
* @param melt the #TALER_EXCHANGEDB_RefreshMelt to free
* @return #GNUNET_OK if the operation was successful, #GNUNET_SYSERROR
*/
int
PERF_TALER_EXCHANGEDB_refresh_melt_free (struct
TALER_EXCHANGEDB_RefreshMelt *melt)
{
GNUNET_CRYPTO_rsa_signature_free (melt->session.coin.denom_sig.rsa_signature);
GNUNET_free (melt);
return GNUNET_OK;
}