more code refactoring to separate parsing, db and response generation nicely
This commit is contained in:
parent
f9347d2395
commit
ed51946442
@ -27,8 +27,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Convert a TALER amount to a JSON
|
||||
* object.
|
||||
* Convert a TALER amount to a JSON object.
|
||||
*
|
||||
* @param amount the amount
|
||||
* @return a json object describing the amount
|
||||
@ -47,6 +46,17 @@ json_t *
|
||||
TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp);
|
||||
|
||||
|
||||
/**
|
||||
* Convert a signature (with purpose) to a JSON object representation.
|
||||
*
|
||||
* @param purpose purpose of the signature
|
||||
* @param signature the signature
|
||||
* @return the JSON reporesentation of the signature with purpose
|
||||
*/
|
||||
json_t *
|
||||
TALER_JSON_from_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
||||
const struct GNUNET_CRYPTO_EddsaSignature *signature);
|
||||
|
||||
|
||||
/**
|
||||
* Convert binary data to a JSON string
|
||||
@ -65,7 +75,7 @@ TALER_JSON_from_data (const void *data, size_t size);
|
||||
*
|
||||
* @param json the json object representing Amount
|
||||
* @param r_amount where the amount has to be written
|
||||
* @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
* @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
*/
|
||||
int
|
||||
TALER_JSON_to_amount (json_t *json,
|
||||
@ -76,7 +86,7 @@ TALER_JSON_to_amount (json_t *json,
|
||||
*
|
||||
* @param json the json object representing absolute time in seconds
|
||||
* @param r_abs where the time has to be written
|
||||
* @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
* @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
*/
|
||||
int
|
||||
TALER_JSON_to_abs (json_t *json,
|
||||
@ -88,7 +98,7 @@ TALER_JSON_to_abs (json_t *json,
|
||||
* @param json the json object representing data
|
||||
* @param out the pointer to hold the parsed data.
|
||||
* @param out_size the size of r_data.
|
||||
* @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
* @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
|
||||
*/
|
||||
int
|
||||
TALER_JSON_to_data (json_t *json,
|
||||
|
192
src/mint/mint.h
192
src/mint/mint.h
@ -13,14 +13,15 @@
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file taler_mint.h
|
||||
* @file mint.h
|
||||
* @brief Common functionality for the mint
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
*
|
||||
* TODO:
|
||||
* - revisit and document `struct Deposit` members.
|
||||
*/
|
||||
|
||||
#ifndef _MINT_H
|
||||
#define _MINT_H
|
||||
|
||||
@ -55,11 +56,195 @@ struct TALER_MINT_DenomKeyIssuePriv
|
||||
* not available.
|
||||
*/
|
||||
struct TALER_RSA_PrivateKey *denom_priv;
|
||||
|
||||
struct TALER_MINT_DenomKeyIssue issue;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Public information about a coin.
|
||||
*/
|
||||
struct TALER_CoinPublicInfo
|
||||
{
|
||||
/**
|
||||
* The coin's public key.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
|
||||
|
||||
/*
|
||||
* The public key signifying the coin's denomination.
|
||||
*/
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
|
||||
/**
|
||||
* Signature over coin_pub by denom_pub.
|
||||
*/
|
||||
struct TALER_RSA_Signature denom_sig;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct CollectableBlindcoin
|
||||
{
|
||||
struct TALER_RSA_BlindedSignaturePurpose ev;
|
||||
struct TALER_RSA_Signature ev_sig;
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
|
||||
struct GNUNET_CRYPTO_EddsaSignature reserve_sig;
|
||||
};
|
||||
|
||||
|
||||
struct RefreshSession
|
||||
{
|
||||
int has_commit_sig;
|
||||
struct GNUNET_CRYPTO_EddsaSignature commit_sig;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
uint16_t num_oldcoins;
|
||||
uint16_t num_newcoins;
|
||||
uint16_t kappa;
|
||||
uint16_t noreveal_index;
|
||||
uint8_t reveal_ok;
|
||||
};
|
||||
|
||||
|
||||
#define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode))
|
||||
#define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData))
|
||||
|
||||
struct RefreshCommitLink
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub;
|
||||
uint16_t cnc_index;
|
||||
uint16_t oldcoin_index;
|
||||
char shared_secret_enc[sizeof (struct GNUNET_HashCode)];
|
||||
};
|
||||
|
||||
struct LinkData
|
||||
{
|
||||
struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv;
|
||||
struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc;
|
||||
};
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
struct SharedSecretEnc
|
||||
{
|
||||
char data[TALER_REFRESH_SHARED_SECRET_LENGTH];
|
||||
};
|
||||
|
||||
|
||||
struct LinkDataEnc
|
||||
{
|
||||
char data[sizeof (struct LinkData)];
|
||||
};
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
struct RefreshCommitCoin
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
struct TALER_RSA_BlindedSignaturePurpose coin_ev;
|
||||
uint16_t cnc_index;
|
||||
uint16_t newcoin_index;
|
||||
char link_enc[sizeof (struct LinkData)];
|
||||
};
|
||||
|
||||
|
||||
struct KnownCoin
|
||||
{
|
||||
struct TALER_CoinPublicInfo public_info;
|
||||
struct TALER_Amount expended_balance;
|
||||
int is_refreshed;
|
||||
/**
|
||||
* Refreshing session, only valid if
|
||||
* is_refreshed==1.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Specification for a /deposit operation.
|
||||
*/
|
||||
struct Deposit
|
||||
{
|
||||
/* FIXME: should be TALER_CoinPublicInfo */
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey coin_pub;
|
||||
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
|
||||
struct TALER_RSA_Signature coin_sig;
|
||||
|
||||
struct TALER_RSA_Signature ubsig;
|
||||
|
||||
/**
|
||||
* Type of the deposit (also purpose of the signature). Either
|
||||
* #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT.
|
||||
*/
|
||||
struct TALER_RSA_SignaturePurpose purpose;
|
||||
|
||||
uint64_t transaction_id;
|
||||
|
||||
struct TALER_AmountNBO amount;
|
||||
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub;
|
||||
|
||||
struct GNUNET_HashCode h_contract;
|
||||
|
||||
struct GNUNET_HashCode h_wire;
|
||||
|
||||
/* TODO: uint16_t wire_size */
|
||||
char wire[]; /* string encoded wire JSON object */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reserve row. Corresponds to table 'reserves' in the mint's
|
||||
* database. FIXME: not sure this is how we want to store this
|
||||
* information. Also, may currently used in different ways in the
|
||||
* code, so we might need to separate the struct into different ones
|
||||
* depending on the context it is used in.
|
||||
*/
|
||||
struct Reserve
|
||||
{
|
||||
/**
|
||||
* Signature over the purse.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaSignature status_sig;
|
||||
/**
|
||||
* Signature with purpose TALER_SIGNATURE_PURSE.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EccSignaturePurpose status_sig_purpose;
|
||||
/**
|
||||
* Signing key used to sign the purse.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey status_sign_pub;
|
||||
/**
|
||||
* Withdraw public key, identifies the purse.
|
||||
* Only the customer knows the corresponding private key.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
|
||||
/**
|
||||
* Remaining balance in the purse.
|
||||
*/
|
||||
struct TALER_AmountNBO balance;
|
||||
|
||||
/**
|
||||
* Expiration date for the purse.
|
||||
*/
|
||||
struct GNUNET_TIME_AbsoluteNBO expiration;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@ -153,4 +338,3 @@ TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row,
|
||||
int indices[3], struct TALER_AmountNBO *denom_nbo);
|
||||
|
||||
#endif /* _MINT_H */
|
||||
|
||||
|
@ -29,149 +29,8 @@
|
||||
#include "taler_util.h"
|
||||
#include "taler_rsa.h"
|
||||
#include "taler-mint-httpd_db.h"
|
||||
#include "mint.h"
|
||||
|
||||
/**
|
||||
* Public information about a coin.
|
||||
*/
|
||||
struct TALER_CoinPublicInfo
|
||||
{
|
||||
/**
|
||||
* The coin's public key.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
|
||||
|
||||
/*
|
||||
* The public key signifying the coin's denomination.
|
||||
*/
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
|
||||
/**
|
||||
* Signature over coin_pub by denom_pub.
|
||||
*/
|
||||
struct TALER_RSA_Signature denom_sig;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reserve row. Corresponds to table 'reserves' in
|
||||
* the mint's database.
|
||||
*/
|
||||
struct Reserve
|
||||
{
|
||||
/**
|
||||
* Signature over the purse.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaSignature status_sig;
|
||||
/**
|
||||
* Signature with purpose TALER_SIGNATURE_PURSE.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EccSignaturePurpose status_sig_purpose;
|
||||
/**
|
||||
* Signing key used to sign the purse.
|
||||
* Only valid if (blind_session_missing==GNUNET_YES).
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey status_sign_pub;
|
||||
/**
|
||||
* Withdraw public key, identifies the purse.
|
||||
* Only the customer knows the corresponding private key.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
|
||||
/**
|
||||
* Remaining balance in the purse.
|
||||
*/
|
||||
struct TALER_AmountNBO balance;
|
||||
|
||||
/**
|
||||
* Expiration date for the purse.
|
||||
*/
|
||||
struct GNUNET_TIME_AbsoluteNBO expiration;
|
||||
};
|
||||
|
||||
|
||||
struct CollectableBlindcoin
|
||||
{
|
||||
struct TALER_RSA_BlindedSignaturePurpose ev;
|
||||
struct TALER_RSA_Signature ev_sig;
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
|
||||
struct GNUNET_CRYPTO_EddsaSignature reserve_sig;
|
||||
};
|
||||
|
||||
|
||||
struct RefreshSession
|
||||
{
|
||||
int has_commit_sig;
|
||||
struct GNUNET_CRYPTO_EddsaSignature commit_sig;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
uint16_t num_oldcoins;
|
||||
uint16_t num_newcoins;
|
||||
uint16_t kappa;
|
||||
uint16_t noreveal_index;
|
||||
uint8_t reveal_ok;
|
||||
};
|
||||
|
||||
|
||||
#define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode))
|
||||
#define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData))
|
||||
|
||||
struct RefreshCommitLink
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub;
|
||||
uint16_t cnc_index;
|
||||
uint16_t oldcoin_index;
|
||||
char shared_secret_enc[sizeof (struct GNUNET_HashCode)];
|
||||
};
|
||||
|
||||
struct LinkData
|
||||
{
|
||||
struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv;
|
||||
struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc;
|
||||
};
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
struct SharedSecretEnc
|
||||
{
|
||||
char data[TALER_REFRESH_SHARED_SECRET_LENGTH];
|
||||
};
|
||||
|
||||
|
||||
struct LinkDataEnc
|
||||
{
|
||||
char data[sizeof (struct LinkData)];
|
||||
};
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
struct RefreshCommitCoin
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
|
||||
struct TALER_RSA_BlindedSignaturePurpose coin_ev;
|
||||
uint16_t cnc_index;
|
||||
uint16_t newcoin_index;
|
||||
char link_enc[sizeof (struct LinkData)];
|
||||
};
|
||||
|
||||
|
||||
struct KnownCoin
|
||||
{
|
||||
struct TALER_CoinPublicInfo public_info;
|
||||
struct TALER_Amount expended_balance;
|
||||
int is_refreshed;
|
||||
/**
|
||||
* Refreshing session, only valid if
|
||||
* is_refreshed==1.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
|
||||
};
|
||||
|
||||
int
|
||||
TALER_MINT_DB_prepare (PGconn *db_conn);
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <libpq-fe.h>
|
||||
#include <pthread.h>
|
||||
#include "mint.h"
|
||||
#include "mint_db.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_rsa.h"
|
||||
#include "taler_json_lib.h"
|
||||
@ -38,6 +37,7 @@
|
||||
#include "taler-mint-httpd_deposit.h"
|
||||
#include "taler-mint-httpd_withdraw.h"
|
||||
#include "taler-mint-httpd_refresh.h"
|
||||
#include "mint_db.h"
|
||||
|
||||
|
||||
/**
|
||||
|
@ -25,12 +25,15 @@
|
||||
* - /deposit: check for leaks
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <pthread.h>
|
||||
#include <jansson.h>
|
||||
#include "taler-mint-httpd_db.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler-mint-httpd_keys.h"
|
||||
#include "taler-mint-httpd_responses.h"
|
||||
#include "mint_db.h"
|
||||
#include "mint.h"
|
||||
#include <pthread.h>
|
||||
#include "taler_json_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -48,18 +51,15 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
|
||||
const struct Deposit *deposit)
|
||||
{
|
||||
PGconn *db_conn;
|
||||
struct Deposit *existing_deposit;
|
||||
int res;
|
||||
|
||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MINT_reply_internal_error (connection,
|
||||
"Failed to connect to database\n");
|
||||
"Failed to connect to database");
|
||||
}
|
||||
|
||||
{
|
||||
struct Deposit *existing_deposit;
|
||||
int res;
|
||||
|
||||
res = TALER_MINT_DB_get_deposit (db_conn,
|
||||
&deposit->coin_pub,
|
||||
&existing_deposit);
|
||||
@ -85,7 +85,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
|
||||
/* FIXME: return error message to client via MHD! */
|
||||
return MHD_NO;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct KnownCoin known_coin;
|
||||
@ -133,3 +132,228 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
|
||||
TALER_MINT_DB_commit (db_conn);
|
||||
return TALER_MINT_reply_deposit_success (connection, deposit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sign a reserve's status with the current signing key.
|
||||
* FIXME: not sure why we do this. Should just return
|
||||
* existing list of operations on the reserve.
|
||||
*
|
||||
* @param reserve the reserve to sign
|
||||
* @param key_state the key state containing the current
|
||||
* signing private key
|
||||
*/
|
||||
static void
|
||||
sign_reserve (struct Reserve *reserve,
|
||||
struct MintKeyState *key_state)
|
||||
{
|
||||
reserve->status_sign_pub = key_state->current_sign_key_issue.issue.signkey_pub;
|
||||
reserve->status_sig_purpose.purpose = htonl (TALER_SIGNATURE_RESERVE_STATUS);
|
||||
reserve->status_sig_purpose.size = htonl (sizeof (struct Reserve) -
|
||||
offsetof (struct Reserve, status_sig_purpose));
|
||||
GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv,
|
||||
&reserve->status_sig_purpose,
|
||||
&reserve->status_sig);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a /withdraw/status.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param reserve_pub public key of the reserve to check
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection,
|
||||
const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub)
|
||||
{
|
||||
PGconn *db_conn;
|
||||
int res;
|
||||
struct Reserve reserve;
|
||||
struct MintKeyState *key_state;
|
||||
int must_update = GNUNET_NO;
|
||||
|
||||
|
||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MINT_reply_internal_error (connection,
|
||||
"Failed to connect to database");
|
||||
}
|
||||
res = TALER_MINT_DB_get_reserve (db_conn,
|
||||
reserve_pub,
|
||||
&reserve);
|
||||
/* check if these are really the matching error codes,
|
||||
seems odd... */
|
||||
if (GNUNET_SYSERR == res)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Reserve not found");
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MINT_reply_internal_error (connection,
|
||||
"Internal error");
|
||||
}
|
||||
key_state = TALER_MINT_key_state_acquire ();
|
||||
if (0 != memcmp (&key_state->current_sign_key_issue.issue.signkey_pub,
|
||||
&reserve.status_sign_pub,
|
||||
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
|
||||
{
|
||||
sign_reserve (&reserve, key_state);
|
||||
must_update = GNUNET_YES;
|
||||
}
|
||||
if ((GNUNET_YES == must_update) &&
|
||||
(GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return MHD_YES;
|
||||
}
|
||||
return TALER_MINT_reply_withdraw_status_success (connection,
|
||||
&reserve);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a /withdraw/sign.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param wsrd_ro details about the withdraw request
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
|
||||
const struct TALER_WithdrawRequest *wsrd_ro)
|
||||
{
|
||||
PGconn *db_conn;
|
||||
struct Reserve reserve;
|
||||
struct MintKeyState *key_state;
|
||||
struct CollectableBlindcoin collectable;
|
||||
struct TALER_MINT_DenomKeyIssuePriv *dki;
|
||||
struct TALER_RSA_Signature ev_sig;
|
||||
struct TALER_Amount amount_required;
|
||||
/* FIXME: the fact that we do this here is a sign that we
|
||||
need to have different versions of this struct for
|
||||
the different places it is used! */
|
||||
struct TALER_WithdrawRequest wsrd = *wsrd_ro;
|
||||
int res;
|
||||
|
||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
|
||||
res = TALER_MINT_DB_get_collectable_blindcoin (db_conn,
|
||||
&wsrd.coin_envelope,
|
||||
&collectable);
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* Don't sign again if we have already signed the coin */
|
||||
if (GNUNET_YES == res)
|
||||
return TALER_MINT_reply_withdraw_sign_success (connection,
|
||||
&collectable);
|
||||
GNUNET_assert (GNUNET_NO == res);
|
||||
res = TALER_MINT_DB_get_reserve (db_conn,
|
||||
&wsrd.reserve_pub,
|
||||
&reserve);
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_NO == res)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Reserve not found");
|
||||
|
||||
// fill out all the missing info in the request before
|
||||
// we can check the signature on the request
|
||||
|
||||
wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW);
|
||||
wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) -
|
||||
offsetof (struct TALER_WithdrawRequest, purpose));
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW,
|
||||
&wsrd.purpose,
|
||||
&wsrd.sig,
|
||||
&wsrd.reserve_pub))
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
"{s:s}",
|
||||
"error", "Invalid Signature");
|
||||
|
||||
key_state = TALER_MINT_key_state_acquire ();
|
||||
dki = TALER_MINT_get_denom_key (key_state,
|
||||
&wsrd.denomination_pub);
|
||||
TALER_MINT_key_state_release (key_state);
|
||||
if (NULL == dki)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Denomination not found");
|
||||
|
||||
amount_required = TALER_amount_ntoh (dki->issue.value);
|
||||
amount_required = TALER_amount_add (amount_required,
|
||||
TALER_amount_ntoh (dki->issue.fee_withdraw));
|
||||
|
||||
if (0 < TALER_amount_cmp (amount_required,
|
||||
TALER_amount_ntoh (reserve.balance)))
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_PAYMENT_REQUIRED,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Insufficient funds");
|
||||
if (GNUNET_OK !=
|
||||
TALER_RSA_sign (dki->denom_priv,
|
||||
&wsrd.coin_envelope,
|
||||
sizeof (struct TALER_RSA_BlindedSignaturePurpose),
|
||||
&ev_sig))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance),
|
||||
amount_required));
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINT_DB_update_reserve (db_conn,
|
||||
&reserve,
|
||||
GNUNET_YES))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
collectable.ev = wsrd.coin_envelope;
|
||||
collectable.ev_sig = ev_sig;
|
||||
collectable.reserve_pub = wsrd.reserve_pub;
|
||||
collectable.reserve_sig = wsrd.sig;
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINT_DB_insert_collectable_blindcoin (db_conn,
|
||||
&collectable))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;;
|
||||
}
|
||||
return TALER_MINT_reply_withdraw_sign_success (connection,
|
||||
&collectable);
|
||||
}
|
||||
|
@ -17,9 +17,6 @@
|
||||
* @file mint/taler-mint_httpd_db.h
|
||||
* @brief Mint-specific database access
|
||||
* @author Chrisitan Grothoff
|
||||
*
|
||||
* TODO:
|
||||
* - revisit and document `struct Deposit` members.
|
||||
*/
|
||||
#ifndef TALER_MINT_HTTPD_DB_H
|
||||
#define TALER_MINT_HTTPD_DB_H
|
||||
@ -29,46 +26,13 @@
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include "taler_util.h"
|
||||
#include "taler_rsa.h"
|
||||
#include "taler-mint-httpd_keys.h"
|
||||
#include "mint.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specification for a /deposit operation.
|
||||
*/
|
||||
struct Deposit
|
||||
{
|
||||
/* FIXME: should be TALER_CoinPublicInfo */
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey coin_pub;
|
||||
|
||||
struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
|
||||
|
||||
struct TALER_RSA_Signature coin_sig;
|
||||
|
||||
struct TALER_RSA_Signature ubsig;
|
||||
|
||||
/**
|
||||
* Type of the deposit (also purpose of the signature). Either
|
||||
* #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT.
|
||||
*/
|
||||
struct TALER_RSA_SignaturePurpose purpose;
|
||||
|
||||
uint64_t transaction_id;
|
||||
|
||||
struct TALER_AmountNBO amount;
|
||||
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub;
|
||||
|
||||
struct GNUNET_HashCode h_contract;
|
||||
|
||||
struct GNUNET_HashCode h_wire;
|
||||
|
||||
/* TODO: uint16_t wire_size */
|
||||
char wire[]; /* string encoded wire JSON object */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Execute a deposit. The validity of the coin and signature
|
||||
* Execute a /deposit. The validity of the coin and signature
|
||||
* have already been checked. The database must now check that
|
||||
* the coin is not (double or over) spent, and execute the
|
||||
* transaction (record details, generate success or failure response).
|
||||
@ -82,4 +46,28 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
|
||||
const struct Deposit *deposit);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a /withdraw/status.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param reserve_pub public key of the reserve to check
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection,
|
||||
const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a /withdraw/sign.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param wsrd details about the withdraw request
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
|
||||
const struct TALER_WithdrawRequest *wsrd);
|
||||
|
||||
|
||||
#endif /* _NEURO_MINT_DB_H */
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <libpq-fe.h>
|
||||
#include <pthread.h>
|
||||
#include "mint.h"
|
||||
#include "mint_db.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_rsa.h"
|
||||
#include "taler_json_lib.h"
|
||||
@ -35,6 +34,7 @@
|
||||
#include "taler-mint-httpd_keys.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mint key state. Never use directly, instead access via
|
||||
* #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release.
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler-mint-httpd.h"
|
||||
|
||||
#include "mint.h"
|
||||
|
||||
/**
|
||||
* Snapshot of the (coin and signing)
|
||||
|
@ -19,6 +19,9 @@
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Christian Grothoff
|
||||
*
|
||||
* TODO:
|
||||
* - split properly into parsing, DB-ops and response generation
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
@ -70,6 +73,9 @@ sign_as_json (struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FIXME: document!
|
||||
*/
|
||||
static int
|
||||
link_iter (void *cls,
|
||||
const struct LinkDataEnc *link_data_enc,
|
||||
@ -246,9 +252,9 @@ check_confirm_signature (struct MHD_Connection *connection,
|
||||
*
|
||||
* @param connection the connection to send error responses to
|
||||
* @param root the JSON object to extract the coin info from
|
||||
* @return GNUNET_YES if coin public info in JSON was valid
|
||||
* GNUNET_NO otherwise
|
||||
* GNUNET_SYSERR on internal error
|
||||
* @return #GNUNET_YES if coin public info in JSON was valid
|
||||
* #GNUNET_NO otherwise
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
static int
|
||||
request_json_require_coin_public_info (struct MHD_Connection *connection,
|
||||
@ -298,9 +304,9 @@ request_json_require_coin_public_info (struct MHD_Connection *connection,
|
||||
* @param root the JSON object
|
||||
* @param hash_context the hash context that will receive
|
||||
* the coin public keys of the melted coin
|
||||
* @return a GNUnet result code, GNUNET_OK on success,
|
||||
* GNUNET_NO if an error message was generated,
|
||||
* GNUNET_SYSERR on internal errors (no response generated)
|
||||
* @return #GNUNET_OK on success,
|
||||
* #GNUNET_NO if an error message was generated,
|
||||
* #GNUNET_SYSERR on internal errors (no response generated)
|
||||
*/
|
||||
static int
|
||||
refresh_accept_melts (struct MHD_Connection *connection,
|
||||
|
@ -26,9 +26,14 @@
|
||||
* TODO:
|
||||
* - when generating /deposit reply, do include signature of mint
|
||||
* to say that we accepted it (check reply format)
|
||||
* - when generating /withdraw/status reply, which signature do
|
||||
* we use there? Might want to instead return *all* signatures on the
|
||||
* existig withdraw operations, instead of Mint's signature
|
||||
* (check reply format, adjust `struct Reserve` if needed)
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler-mint-httpd_responses.h"
|
||||
#include "taler_json_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -229,4 +234,61 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,
|
||||
"DEPOSIT_OK");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send reserve status information to client.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param reserve reserve status information to return
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_reply_withdraw_status_success (struct MHD_Connection *connection,
|
||||
const struct Reserve *reserve)
|
||||
{
|
||||
json_t *json;
|
||||
|
||||
/* Convert the public information of a reserve (i.e.
|
||||
excluding private key) to a JSON object. */
|
||||
json = json_object ();
|
||||
json_object_set_new (json,
|
||||
"balance",
|
||||
TALER_JSON_from_amount (TALER_amount_ntoh (reserve->balance)));
|
||||
json_object_set_new (json,
|
||||
"expiration",
|
||||
TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (reserve->expiration)));
|
||||
json_object_set_new (json,
|
||||
"signature",
|
||||
TALER_JSON_from_sig (&reserve->status_sig_purpose,
|
||||
&reserve->status_sig));
|
||||
|
||||
return TALER_MINT_reply_json (connection,
|
||||
json,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send blinded coin information to client.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param collectable blinded coin to return
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,
|
||||
const struct CollectableBlindcoin *collectable)
|
||||
{
|
||||
json_t *root = json_object ();
|
||||
|
||||
json_object_set_new (root, "ev_sig",
|
||||
TALER_JSON_from_data (&collectable->ev_sig,
|
||||
sizeof (struct TALER_RSA_Signature)));
|
||||
return TALER_MINT_reply_json (connection,
|
||||
root,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* end of taler-mint-httpd_responses.c */
|
||||
|
@ -31,8 +31,8 @@
|
||||
#include <libpq-fe.h>
|
||||
#include <pthread.h>
|
||||
#include "taler-mint-httpd.h"
|
||||
#include "taler-mint-httpd_db.h"
|
||||
#include "taler-mint-httpd_mhd.h"
|
||||
#include "mint_db.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -135,5 +135,28 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection,
|
||||
const struct Deposit *deposit);
|
||||
|
||||
|
||||
/**
|
||||
* Send reserve status information to client.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param reserve reserve status information to return
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_reply_withdraw_status_success (struct MHD_Connection *connection,
|
||||
const struct Reserve *reserve);
|
||||
|
||||
|
||||
/**
|
||||
* Send blinded coin information to client.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param collectable blinded coin to return
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection,
|
||||
const struct CollectableBlindcoin *collectable);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,9 @@
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Christian Grothoff
|
||||
*
|
||||
* TODO:
|
||||
* - support variable-size RSA keys
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
@ -33,62 +36,12 @@
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler-mint-httpd_parsing.h"
|
||||
#include "taler-mint-httpd_keys.h"
|
||||
#include "taler-mint-httpd_db.h"
|
||||
#include "taler-mint-httpd_mhd.h"
|
||||
#include "taler-mint-httpd_withdraw.h"
|
||||
#include "taler-mint-httpd_responses.h"
|
||||
|
||||
|
||||
/**
|
||||
* Convert a signature (with purpose) to
|
||||
* a JSON object representation.
|
||||
*
|
||||
* @param purpose purpose of the signature
|
||||
* @param signature the signature
|
||||
* @return the JSON reporesentation of the signature with purpose
|
||||
*/
|
||||
static json_t *
|
||||
sig_to_json (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
||||
const struct GNUNET_CRYPTO_EddsaSignature *signature)
|
||||
{
|
||||
json_t *root;
|
||||
json_t *el;
|
||||
|
||||
root = json_object ();
|
||||
|
||||
el = json_integer ((json_int_t) ntohl (purpose->size));
|
||||
json_object_set_new (root, "size", el);
|
||||
|
||||
el = json_integer ((json_int_t) ntohl (purpose->purpose));
|
||||
json_object_set_new (root, "purpose", el);
|
||||
|
||||
el = TALER_JSON_from_data (signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature));
|
||||
json_object_set_new (root, "sig", el);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sign a reserve's status with the current signing key.
|
||||
*
|
||||
* @param reserve the reserve to sign
|
||||
* @param key_state the key state containing the current
|
||||
* signing private key
|
||||
*/
|
||||
static void
|
||||
sign_reserve (struct Reserve *reserve,
|
||||
struct MintKeyState *key_state)
|
||||
{
|
||||
reserve->status_sign_pub = key_state->current_sign_key_issue.issue.signkey_pub;
|
||||
reserve->status_sig_purpose.purpose = htonl (TALER_SIGNATURE_RESERVE_STATUS);
|
||||
reserve->status_sig_purpose.size = htonl (sizeof (struct Reserve) -
|
||||
offsetof (struct Reserve, status_sig_purpose));
|
||||
GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv,
|
||||
&reserve->status_sig_purpose,
|
||||
&reserve->status_sig);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/withdraw/status" request
|
||||
*
|
||||
@ -107,100 +60,18 @@ TALER_MINT_handler_withdraw_status (struct RequestHandler *rh,
|
||||
size_t *upload_data_size)
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
|
||||
PGconn *db_conn;
|
||||
int res;
|
||||
struct Reserve reserve;
|
||||
struct MintKeyState *key_state;
|
||||
int must_update = GNUNET_NO;
|
||||
json_t *json;
|
||||
|
||||
res = TALER_MINT_mhd_request_arg_data (connection,
|
||||
"reserve_pub",
|
||||
&reserve_pub,
|
||||
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
res = TALER_MINT_DB_get_reserve (db_conn,
|
||||
&reserve_pub,
|
||||
&reserve);
|
||||
if (GNUNET_SYSERR == res)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Reserve not found");
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
key_state = TALER_MINT_key_state_acquire ();
|
||||
if (0 != memcmp (&key_state->current_sign_key_issue.issue.signkey_pub,
|
||||
&reserve.status_sign_pub,
|
||||
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
|
||||
{
|
||||
sign_reserve (&reserve, key_state);
|
||||
must_update = GNUNET_YES;
|
||||
}
|
||||
if ((GNUNET_YES == must_update) &&
|
||||
(GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
/* Convert the public information of a reserve (i.e.
|
||||
excluding private key) to a JSON object. */
|
||||
json = json_object ();
|
||||
json_object_set_new (json,
|
||||
"balance",
|
||||
TALER_JSON_from_amount (TALER_amount_ntoh (reserve.balance)));
|
||||
json_object_set_new (json,
|
||||
"expiration",
|
||||
TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (reserve.expiration)));
|
||||
json_object_set_new (json,
|
||||
"signature",
|
||||
sig_to_json (&reserve.status_sig_purpose,
|
||||
&reserve.status_sig));
|
||||
|
||||
return TALER_MINT_reply_json (connection,
|
||||
json,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send positive, normal response for "/withdraw/sign".
|
||||
*
|
||||
* @param connection the connection to send the response to
|
||||
* @param collectable the collectable blindcoin (i.e. the blindly signed coin)
|
||||
* @return a MHD result code
|
||||
*/
|
||||
static int
|
||||
helper_withdraw_sign_send_reply (struct MHD_Connection *connection,
|
||||
const struct CollectableBlindcoin *collectable)
|
||||
{
|
||||
json_t *root = json_object ();
|
||||
|
||||
json_object_set_new (root, "ev_sig",
|
||||
TALER_JSON_from_data (&collectable->ev_sig,
|
||||
sizeof (struct TALER_RSA_Signature)));
|
||||
return TALER_MINT_reply_json (connection,
|
||||
root,
|
||||
MHD_HTTP_OK);
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* parse error */
|
||||
return TALER_MINT_db_execute_withdraw_status (connection,
|
||||
&reserve_pub);
|
||||
}
|
||||
|
||||
|
||||
@ -223,180 +94,44 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
|
||||
{
|
||||
struct TALER_WithdrawRequest wsrd;
|
||||
int res;
|
||||
PGconn *db_conn;
|
||||
struct Reserve reserve;
|
||||
struct MintKeyState *key_state;
|
||||
struct CollectableBlindcoin collectable;
|
||||
struct TALER_MINT_DenomKeyIssuePriv *dki;
|
||||
struct TALER_RSA_Signature ev_sig;
|
||||
struct TALER_Amount amount_required;
|
||||
|
||||
memset (&wsrd,
|
||||
0,
|
||||
sizeof (struct TALER_WithdrawRequest));
|
||||
res = TALER_MINT_mhd_request_arg_data (connection,
|
||||
"reserve_pub",
|
||||
&wsrd.reserve_pub,
|
||||
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* invalid request */
|
||||
|
||||
/* FIXME: handle variable-size signing keys! */
|
||||
res = TALER_MINT_mhd_request_arg_data (connection,
|
||||
"denom_pub",
|
||||
&wsrd.denomination_pub,
|
||||
sizeof (struct TALER_RSA_PublicKeyBinaryEncoded));
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* invalid request */
|
||||
res = TALER_MINT_mhd_request_arg_data (connection,
|
||||
"coin_ev",
|
||||
&wsrd.coin_envelope,
|
||||
sizeof (struct TALER_RSA_Signature));
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* invalid request */
|
||||
res = TALER_MINT_mhd_request_arg_data (connection,
|
||||
"reserve_sig",
|
||||
&wsrd.sig,
|
||||
sizeof (struct GNUNET_CRYPTO_EddsaSignature));
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
|
||||
if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
|
||||
{
|
||||
// FIXME: return 'internal error'?
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
res = TALER_MINT_DB_get_collectable_blindcoin (db_conn,
|
||||
&wsrd.coin_envelope,
|
||||
&collectable);
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
/* Don't sign again if we have already signed the coin */
|
||||
if (GNUNET_YES == res)
|
||||
return helper_withdraw_sign_send_reply (connection,
|
||||
&collectable);
|
||||
GNUNET_assert (GNUNET_NO == res);
|
||||
res = TALER_MINT_DB_get_reserve (db_conn,
|
||||
&wsrd.reserve_pub,
|
||||
&reserve);
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Reserve not found");
|
||||
return MHD_YES; /* invalid request */
|
||||
|
||||
// fill out all the missing info in the request before
|
||||
// we can check the signature on the request
|
||||
|
||||
wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW);
|
||||
wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) -
|
||||
offsetof (struct TALER_WithdrawRequest, purpose));
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW,
|
||||
&wsrd.purpose,
|
||||
&wsrd.sig,
|
||||
&wsrd.reserve_pub))
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
"{s:s}",
|
||||
"error", "Invalid Signature");
|
||||
|
||||
key_state = TALER_MINT_key_state_acquire ();
|
||||
dki = TALER_MINT_get_denom_key (key_state,
|
||||
&wsrd.denomination_pub);
|
||||
TALER_MINT_key_state_release (key_state);
|
||||
if (NULL == dki)
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Denomination not found");
|
||||
|
||||
amount_required = TALER_amount_ntoh (dki->issue.value);
|
||||
amount_required = TALER_amount_add (amount_required,
|
||||
TALER_amount_ntoh (dki->issue.fee_withdraw));
|
||||
|
||||
if (0 < TALER_amount_cmp (amount_required,
|
||||
TALER_amount_ntoh (reserve.balance)))
|
||||
return TALER_MINT_reply_json_pack (connection,
|
||||
MHD_HTTP_PAYMENT_REQUIRED,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"Insufficient funds");
|
||||
if (GNUNET_OK !=
|
||||
TALER_RSA_sign (dki->denom_priv,
|
||||
&wsrd.coin_envelope,
|
||||
sizeof (struct TALER_RSA_BlindedSignaturePurpose),
|
||||
&ev_sig))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance),
|
||||
amount_required));
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINT_DB_update_reserve (db_conn,
|
||||
&reserve,
|
||||
GNUNET_YES))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
collectable.ev = wsrd.coin_envelope;
|
||||
collectable.ev_sig = ev_sig;
|
||||
collectable.reserve_pub = wsrd.reserve_pub;
|
||||
collectable.reserve_sig = wsrd.sig;
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINT_DB_insert_collectable_blindcoin (db_conn,
|
||||
&collectable))
|
||||
{
|
||||
// FIXME: return 'internal error'
|
||||
GNUNET_break (0);
|
||||
return GNUNET_NO;;
|
||||
}
|
||||
return helper_withdraw_sign_send_reply (connection,
|
||||
&collectable);
|
||||
return TALER_MINT_db_execute_withdraw_sign (connection,
|
||||
&wsrd);
|
||||
}
|
||||
|
||||
/* end of taler-mint-httpd_withdraw.c */
|
||||
|
@ -90,6 +90,34 @@ TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a signature (with purpose) to a JSON object representation.
|
||||
*
|
||||
* @param purpose purpose of the signature
|
||||
* @param signature the signature
|
||||
* @return the JSON reporesentation of the signature with purpose
|
||||
*/
|
||||
json_t *
|
||||
TALER_JSON_from_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
||||
const struct GNUNET_CRYPTO_EddsaSignature *signature)
|
||||
{
|
||||
json_t *root;
|
||||
json_t *el;
|
||||
|
||||
root = json_object ();
|
||||
|
||||
el = json_integer ((json_int_t) ntohl (purpose->size));
|
||||
json_object_set_new (root, "size", el);
|
||||
|
||||
el = json_integer ((json_int_t) ntohl (purpose->purpose));
|
||||
json_object_set_new (root, "purpose", el);
|
||||
|
||||
el = TALER_JSON_from_data (signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature));
|
||||
json_object_set_new (root, "sig", el);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert binary data to a JSON string
|
||||
|
Loading…
Reference in New Issue
Block a user