Merge branch 'master' of git+ssh://git.taler.net/var/git/mint

This commit is contained in:
Christian Grothoff 2015-06-22 18:11:34 +02:00
commit d98d085ff5
6 changed files with 548 additions and 73 deletions

View File

@ -420,7 +420,184 @@ void
TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit);
/* ********************* /withdraw/xxx *********************** */
/* ********************* /withdraw/status *********************** */
/**
* @brief A /withdraw/status Handle
*/
struct TALER_MINT_WithdrawStatusHandle;
/**
* Ways how a reserve's balance may change.
*/
enum TALER_MINT_ReserveTransactionType {
/**
* Deposit into the reserve.
*/
TALER_MINT_RTT_DEPOSIT,
/**
* Withdrawal from the reserve.
*/
TALER_MINT_RTT_WITHDRAWAL
};
/**
* Entry in the reserve's transaction history.
*/
struct TALER_MINT_ReserveHistory
{
/**
* Type of the transaction.
*/
enum TALER_MINT_ReserveTransactionType type;
/**
* Amount transferred (in or out).
*/
struct TALER_Amount amount;
/**
* Details depending on @e type.
*/
union {
/**
* Transaction details for the incoming transaction.
*/
json_t *wire_in_details;
/**
* Signature authorizing the withdrawal for outgoing transaction.
*/
struct TALER_ReserveSignatureP out_authorization_sig;
};
};
/**
* Callbacks of this type are used to serve the result of submitting a
* deposit permission request to a mint.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the mint's reply is bogus (fails to follow the protocol)
* @param balance current balance in the reserve
* @param history_length number of entries in the transaction history
* @param history detailed transaction history
*/
typedef void
(*TALER_MINT_WithdrawStatusResultCallback) (void *cls,
unsigned int http_status,
const struct TALER_Amount *balance,
unsigned int history_length,
const struct TALER_MINT_ReserveHistory *history);
/**
* Submit a request to obtain the transaction history of a reserve
* from the mint. Note that while we return the full response to the
* caller for further processing, we do already verify that the
* response is well-formed (i.e. that signatures included in the
* response are all valid and add up to the balance). If the mint's
* reply is not well-formed, we return an HTTP status code of zero to
* @a cb.
*
* @param mint the mint handle; the mint must be ready to operate
* @param reserve_pub public key of the reserve to inspect
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawStatusHandle *
TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_MINT_WithdrawStatusResultCallback cb,
void *cb_cls);
/**
* Cancel a withdraw status request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param status the withdraw status request handle
*/
void
TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *status);
/* ********************* /withdraw/sign *********************** */
/**
* @brief A /withdraw/sign Handle
*/
struct TALER_MINT_WithdrawSignHandle;
/**
* Callbacks of this type are used to serve the result of submitting a
* deposit permission request to a mint.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the mint's reply is bogus (fails to follow the protocol)
* @param sig signature over the coin, NULL on error
* @param full_response full response from the mint (for logging, in case of errors)
*/
typedef void
(*TALER_MINT_WithdrawSignResultCallback) (void *cls,
unsigned int http_status,
const struct TALER_DenominationSignature *sig,
json_t *full_response);
/**
* Withdraw a coin from the mint using a /withdraw/sign request. Note
* that to ensure that no money is lost in case of hardware failures,
* the caller must have committed (most of) the arguments to disk
* before calling, and be ready to repeat the request with the same
* arguments in case of failures.
*
* @param mint the mint handle; the mint must be ready to operate
* @param pk kind of coin to create
* @param coin_priv where to store the coin's private key,
* caller must have committed this value to disk before the call (with @a pk)
* @param blinding_key where to store the coin's blinding key
* caller must have committed this value to disk before the call (with @a pk)
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for the above callback
* @return #GNUNET_OK on success, #GNUNET_SYSERR
* if the inputs are invalid (i.e. denomination key not with this mint).
* In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawSignHandle *
TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
const struct TALER_MINT_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_MINT_WithdrawSignResultCallback res_cb,
void *res_cb_cls);
/**
* Cancel a withdraw status request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param sign the withdraw sign request handle
*/
void
TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign);

View File

@ -213,15 +213,53 @@ verify_deposit_signature_forbidden (const struct TALER_MINT_DepositHandle *dh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
switch (purpose->purpose)
switch (ntohl (purpose->purpose))
{
case TALER_SIGNATURE_WALLET_COIN_DEPOSIT:
{
const struct TALER_DepositRequestPS *dr;
struct TALER_Amount dr_amount;
if (ntohl (purpose->size) != sizeof (struct TALER_DepositRequestPS))
{
GNUNET_break (0);
/* FIXME: check amount! #3516 */
MAJ_parse_free (spec);
return GNUNET_SYSERR;
}
dr = (const struct TALER_DepositRequestPS *) purpose;
TALER_amount_ntoh (&dr_amount,
&dr->amount_with_fee);
if (0 != TALER_amount_cmp (&dr_amount,
&amount))
{
GNUNET_break (0);
MAJ_parse_free (spec);
return GNUNET_SYSERR;
}
}
break;
case TALER_SIGNATURE_WALLET_COIN_MELT:
{
const struct TALER_RefreshMeltCoinAffirmationPS *rm;
struct TALER_Amount rm_amount;
if (ntohl (purpose->size) != sizeof (struct TALER_RefreshMeltCoinAffirmationPS))
{
GNUNET_break (0);
/* FIXME: check amount! #3516 */
MAJ_parse_free (spec);
return GNUNET_SYSERR;
}
rm = (const struct TALER_RefreshMeltCoinAffirmationPS *) purpose;
TALER_amount_ntoh (&rm_amount,
&rm->amount_with_fee);
if (0 != TALER_amount_cmp (&rm_amount,
&amount))
{
GNUNET_break (0);
MAJ_parse_free (spec);
return GNUNET_SYSERR;
}
}
break;
default:
/* signature not supported, new version on server? */
@ -234,7 +272,7 @@ verify_deposit_signature_forbidden (const struct TALER_MINT_DepositHandle *dh,
&total,
&amount))
{
/* overflow in history already!? inconceivable! */
/* overflow in history already!? inconceivable! Bad mint! */
GNUNET_break_op (0);
MAJ_parse_free (spec);
return GNUNET_SYSERR;

View File

@ -202,12 +202,40 @@ parse_json (json_t *root,
case MAJ_CMD_EDDSA_SIGNATURE:
{
/* FIXME: parse the JSON signature
and the purpose, then check that the
signature is valid and the size field
is also correct; if all checks out,
return the purpose */
GNUNET_break (0); // FIXME: implement! #3516
struct TALER_CoinSpendSignatureP sig;
struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
size_t size;
struct MAJ_Specification sig_spec[] = {
MAJ_spec_fixed_auto ("eddsa_sig", &sig),
MAJ_spec_varsize ("eddsa_val", (void**) &purpose, &size),
MAJ_spec_end
};
if (GNUNET_OK !=
MAJ_parse_json (pos,
sig_spec))
{
GNUNET_break_op (0);
MAJ_parse_free (sig_spec);
return i;
}
if (size != ntohl (purpose->size))
{
GNUNET_break_op (0);
MAJ_parse_free (sig_spec);
return i;
}
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (ntohl (purpose->purpose),
purpose,
&sig.eddsa_signature,
spec[i].details.eddsa_signature.pub_key))
{
GNUNET_break_op (0);
MAJ_parse_free (sig_spec);
return i;
}
*spec[i].details.eddsa_signature.purpose_p = purpose;
}
break;

View File

@ -218,6 +218,17 @@ MAJ_parse_free (struct MAJ_Specification *spec);
#define MAJ_spec_fixed_auto(name,obj) { .cmd = MAJ_CMD_BINARY_FIXED, .field = name, .details.fixed_data.dest = obj, .details.fixed_data.dest_size = sizeof (*obj) }
/**
* Variable size object (in network byte order, encoded using Crockford
* Base32hex encoding).
*
* @param name name of the JSON field
* @param obj_ptr pointer where to write the data (a `void **`)
* @param size where to store the number of bytes allocated for @a obj (of type `size_t *`
*/
#define MAJ_spec_varsize(name,obj,size) { .cmd = MAJ_CMD_BINARY_VARIABLE, .field = name, .details.variable_data.dest_p = obj, .details.variable_data.dest_size_p = size }
/**
* Absolute time.
*

View File

@ -227,6 +227,10 @@ interpret_end_loop (struct PERF_TALER_MINTDB_interpreter_state *state)
}
/**
* Saves the data exposed by another command into
* an array in the command specific struct.
*/
static void
interpret_save_array (struct PERF_TALER_MINTDB_interpreter_state *state)
{
@ -309,6 +313,53 @@ interpret_save_array (struct PERF_TALER_MINTDB_interpreter_state *state)
}
static void
interpret_load_array (struct PERF_TALER_MINTDB_interpreter_state *state)
{
int loop_index, save_index;
union PERF_TALER_MINTDB_Data zero = {0};
union PERF_TALER_MINTDB_Data *loaded_data;
loop_index = cmd_find (state->cmd,
state->cmd[state->i].details.load_array.label_loop);
save_index = cmd_find (state->cmd,
state->cmd[state->i].details.load_array.label_save);
/* Extracting the data from the loop_indexth indice in save_index
* array.
*/
loaded_data = &state->cmd[save_index].details.save_array.data_saved[
state->cmd[state->i].details.load_array.permutation[
state->cmd[loop_index].details.loop.curr_iteration]];
switch (state->cmd[state->i].exposed_type)
{
case PERF_TALER_MINTDB_TIME:
state->cmd[state->i].exposed.time = loaded_data->time;
break;
case PERF_TALER_MINTDB_DEPOSIT:
state->cmd[state->i].exposed.deposit = loaded_data->deposit;
break;
case PERF_TALER_MINTDB_BLINDCOIN:
state->cmd[state->i].exposed.blindcoin = loaded_data->blindcoin;
break;
case PERF_TALER_MINTDB_RESERVE:
state->cmd[state->i].exposed.reserve = loaded_data->reserve;
break;
case PERF_TALER_MINTDB_DENOMINATION_INFO:
state->cmd[state->i].exposed.dki = loaded_data->dki;
case PERF_TALER_MINTDB_COIN_INFO:
state->cmd[state->i].exposed.cpi = loaded_data->cpi;
default:
break;
}
*loaded_data = zero;
}
/**
* Main interpreter loop.
*
@ -344,6 +395,7 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state)
int start_index, stop_index;
struct timespec start, stop;
unsigned long elapsed_ms;
start_index = cmd_find (state->cmd,
state->cmd[state->i].details.gauger.label_start);
stop_index = cmd_find (state->cmd,
@ -380,35 +432,7 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state)
break;
case PERF_TALER_MINTDB_CMD_LOAD_ARRAY:
{
int loop_index, save_index;
union PERF_TALER_MINTDB_Data *loaded_data;
loop_index = cmd_find (state->cmd,
state->cmd[state->i].details.load_array.label_loop);
save_index = cmd_find (state->cmd,
state->cmd[state->i].details.load_array.label_save);
/* Extracting the data from the loop_indexth indice in save_index
* array.
*/
loaded_data = &state->cmd[save_index].details.save_array.data_saved[
state->cmd[state->i].details.load_array.permutation[
state->cmd[loop_index].details.loop.curr_iteration]];
switch (state->cmd[state->i].exposed_type)
{
case PERF_TALER_MINTDB_TIME:
state->cmd[state->i].exposed.time = loaded_data->time;
break;
case PERF_TALER_MINTDB_DEPOSIT:
state->cmd[state->i].exposed.deposit = loaded_data->deposit;
loaded_data->deposit = NULL;
break;
default:
break;
}
}
interpret_load_array (state);
break;
case PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT:
@ -431,8 +455,98 @@ interpret (struct PERF_TALER_MINTDB_interpreter_state *state)
state->cmd[state->i]
.details.get_deposit.label_source)]
.exposed.deposit; // Get the deposit from the source
state->plugin->have_deposit (state->plugin->cls,
state->session, deposit);
state->session,
deposit);
}
break;
case PERF_TALER_MINTDB_CMD_INSERT_RESERVE:
{
struct TALER_MINTDB_Reserve *reserve;
json_t *details = json_pack ("si","justification",
GNUNET_CRYPTO_random_u32 (
GNUNET_CRYPTO_QUALITY_WEAK,
UINT32_MAX));
reserve = PERF_TALER_MINTDB_reserve_init ();
state->plugin->reserves_in_insert (
state->plugin->cls,
state->session,
&reserve->pub,
&reserve->balance,
details
);
json_decref (details);
state->cmd[state->i].exposed.reserve = reserve;
}
break;
case PERF_TALER_MINTDB_CMD_GET_RESERVE:
{
struct TALER_MINTDB_Reserve *reserve =
state->cmd[cmd_find (state->cmd,
state->cmd[state->i]
.details.get_reserve.label_source)]
.exposed.reserve; // Get the deposit from the source
state->plugin->reserve_get (state->plugin->cls,
state->session,
reserve);
}
break;
case PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION:
{
struct TALER_MINTDB_DenominationKeyIssueInformation *dki =
PERF_TALER_MINTDB_denomination_init ();
state->plugin->insert_denomination_info (state->plugin->cls,
state->session,
&dki->denom_pub,
&dki->issue);
state->cmd[state->i].exposed.dki = dki;
}
break;
case PERF_TALER_MINTDB_CMD_GET_DENOMINATION:
{
struct TALER_MINTDB_DenominationKeyIssueInformation *dki =
state->cmd[cmd_find (state->cmd,
state->cmd[state->i]
.details.get_denomination.label_source)]
.exposed.dki;
state->plugin->get_denomination_info (state->plugin->cls,
state->session,
&dki->denom_pub,
&dki->issue);
}
break;
case PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW:
{
struct TALER_MINTDB_CollectableBlindcoin *blindcoin =
PERF_TALER_MINTDB_collectable_blindcoin_init ();
state->plugin->insert_withdraw_info (state->plugin->cls,
state->session,
blindcoin);
state->cmd[state->i].exposed.blindcoin = blindcoin;
}
break;
case PERF_TALER_MINTDB_CMD_GET_WITHDRAW:
{
struct TALER_MINTDB_CollectableBlindcoin *blindcoin =
state->cmd[cmd_find (state->cmd,
state->cmd[state->i]
.details.get_denomination.label_source)]
.exposed.blindcoin;
state->plugin->get_withdraw_info (state->plugin->cls,
state->session,
&blindcoin->h_coin_envelope,
blindcoin);
}
break;

View File

@ -118,28 +118,6 @@
.exposed_type = PERF_TALER_MINTDB_NONE, \
}
/**
* Insert a deposit into the database
*/
#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DEPOSIT(_label) \
{ \
.command = PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,\
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_DEPOSIT, \
}
/**
* Check if a deposit is in the database
* @param _label_deposit Label of the deposit to use
*/
#define PERF_TALER_MINTDB_INIT_CMD_GET_DEPOSIT(_label, _label_deposit) \
{ \
.command = PERF_TALER_MINTDB_CMD_GET_DEPOSIT, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_NONE, \
.details.get_deposit.label_source = _label_deposit \
}
/**
* Extracts @a _nb_saved items of type @a _save_type
* from the command @a _label_save during the loop @a _label_loop
@ -171,7 +149,94 @@
.label_save = _label_save \
} \
}
/**
* Insert a deposit into the database
*/
#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DEPOSIT(_label) \
{ \
.command = PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,\
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_DEPOSIT, \
}
/**
* Check if a deposit is in the database
* @param _label_deposit Label of the deposit to use
*/
#define PERF_TALER_MINTDB_INIT_CMD_GET_DEPOSIT(_label, _label_deposit) \
{ \
.command = PERF_TALER_MINTDB_CMD_GET_DEPOSIT, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_NONE, \
.details.get_deposit.label_source = _label_deposit \
}
/**
* Creates a new reserve in the database
*/
#define PERF_TALER_MINTDB_INIT_CMD_INSERT_RESERVE(_label) \
{ \
.command = PERF_TALER_MINTDB_CMD_INSERT_RESERVE \
.label = _label \
.exposed_type = PERF_TALER_MINTDB_RESERVE \
}
/**
* Polls the database for a secific reserve's details
* @param _label_source Source for the reserve to poll
*/
#define PERF_TALER_MINTDB_INIT_CMD_GET_RESERVE(_label, _label_source) \
{ \
.command = PERF_TALER_MINTDB_CMD_GET_RESERVE \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_NONE, \
.details.get_reserve.label_source = _label_source \
}
/**
* Inserts informations about a withdrawal in the database
*/
#define PERF_TALER_MINTDB_INIT_CMD_INSERT_WITHDRAW(_label) \
{ \
.command = PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_BLINDCOIN, \
}\
/**
* Polls the database about informations regarding a secific withdrawal
*/
#define PERF_TALER_MINTDB_INIT_CMD_GET_WITHDRAW(_label, _label_source) \
{ \
.command = PERF_TALER_MINTDB_CMD_GET_WITHDRAW, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_NONE, \
.details.get_withdraw.label_source = _label_source, \
}
/**
* Inserts informations about a denomination key in the database
*/
#define PERF_TALER_MINTDB_INIT_CMD_INSERT_DENOMINATION(_label) \
{ \
.command = PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_DENOMINATION_KEY, \
}
/**
* Polls the database about informations regarding a specific denomination key
*/
#define PERF_TALER_MINTDB_INIT_CMD_GET_DENOMINATION(_label, _label_source) \
{ \
.command = PERF_TALER_MINTDB_CMD_GET_DENOMINATION, \
.label = _label, \
.exposed_type = PERF_TALER_MINTDB_NONE, \
.details.get_denomination.label_source = _label_source, \
}
/**
@ -184,7 +249,9 @@ enum PERF_TALER_MINTDB_Type
PERF_TALER_MINTDB_TIME,
PERF_TALER_MINTDB_DEPOSIT,
PERF_TALER_MINTDB_BLINDCOIN,
PERF_TALER_MINTDB_RESERVE_KEY,
PERF_TALER_MINTDB_RESERVE,
PERF_TALER_MINTDB_DENOMINATION_KEY,
PERF_TALER_MINTDB_DENOMINATION_INFO,
PERF_TALER_MINTDB_COIN_INFO,
};
@ -195,10 +262,11 @@ enum PERF_TALER_MINTDB_Type
*/
union PERF_TALER_MINTDB_Data
{
struct TALER_MINTDB_Deposit *deposit;
struct timespec time;
struct TALER_MINTDB_Deposit *deposit;
struct TALER_MINTDB_CollectableBlindcoin *blindcoin;
struct TALER_MINTDB_Reserve *reserve;
struct TALER_DenominationPublicKey *dpk;
struct TALER_MINTDB_DenominationKeyIssueInformation *dki;
struct TALER_CoinPublicInfo *cpi;
};
@ -239,19 +307,36 @@ enum PERF_TALER_MINTDB_CMD_Name
// Abort a transaction
PERF_TALER_MINTDB_CMD_ABORT_TRANSACTION,
// Insert a deposit into the database
PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,
// Check if a deposit is in the database
PERF_TALER_MINTDB_CMD_GET_DEPOSIT,
// Saves random deposits from a loop
PERF_TALER_MINTDB_CMD_SAVE_ARRAY,
// Load deposits saved earlier
PERF_TALER_MINTDB_CMD_LOAD_ARRAY,
} command;
// Insert a deposit into the database
PERF_TALER_MINTDB_CMD_INSERT_DEPOSIT,
// Check if a deposit is in the database
PERF_TALER_MINTDB_CMD_GET_DEPOSIT,
// Insert currency in a reserve / Create a reserve
PERF_TALER_MINTDB_CMD_INSERT_RESERVE,
// Get Informations about a reserve
PERF_TALER_MINTDB_CMD_GET_RESERVE,
// Insert informations about a withdrawal in the database
PERF_TALER_MINTDB_CMD_INSERT_WITHDRAW,
// Pulls informations about a withdrawal from the database
PERF_TALER_MINTDB_CMD_GET_WITHDRAW,
// Insert informations about a denomination key in the database
PERF_TALER_MINTDB_CMD_INSERT_DENOMINATION,
// polls the database for informations about a specific denomination key
PERF_TALER_MINTDB_CMD_GET_DENOMINATION
};
/**
@ -365,6 +450,26 @@ struct PERF_TALER_MINTDB_CMD_get_deposit_details
};
/**
* Extra data requiered for the GET_DEPOSIT command
*/
struct PERF_TALER_MINTDB_CMD_get_reserve_details
{
/**
* The label of the source of the reserve to check
*/
const char *label_source;
};
struct PERF_TALER_MINTDB_CMD_get_denomination_details
{
/**
* The label of the source of the denomination to check
*/
const char *label_source;
};
/**
* Contains extra data required for any command
*/
@ -376,6 +481,8 @@ union PERF_TALER_MINTDB_CMD_Details
struct PERF_TALER_MINTDB_CMD_save_array_details save_array;
struct PERF_TALER_MINTDB_CMD_load_array_details load_array;
struct PERF_TALER_MINTDB_CMD_get_deposit_details get_deposit;
struct PERF_TALER_MINTDB_CMD_get_reserve_details get_reserve;
struct PERF_TALER_MINTDB_CMD_get_denomination_details get_denomination;
};