mention need to audit randomness of gamma
This commit is contained in:
commit
bf8b9d1435
1
.gitignore
vendored
1
.gitignore
vendored
@ -30,6 +30,7 @@ GTAGS
|
||||
src/lib/test_mint_api
|
||||
doc/doxygen/doxygen_sqlite3.db
|
||||
src/mint-lib/test_mint_api
|
||||
src/mint-tools/taler-auditor-sign
|
||||
src/mint-tools/taler-mint-dbinit
|
||||
src/mint-tools/taler-mint-keycheck
|
||||
src/mint-tools/taler-mint-keyup
|
||||
|
@ -2,7 +2,8 @@
|
||||
# Currency supported by the mint (can only be one)
|
||||
CURRENCY = EUR
|
||||
|
||||
# Wire format supproted by the mint (currently only SEPA is implemented)
|
||||
# Wire format supported by the mint, case-insensitive.
|
||||
# Examples for formats include 'test' for testing and 'sepa' (for EU IBAN).
|
||||
WIREFORMAT = SEPA
|
||||
|
||||
# HTTP port the mint listens to
|
||||
@ -19,3 +20,9 @@ TESTRUN = YES
|
||||
[mintdb-postgres]
|
||||
|
||||
DB_CONN_STR = "postgres:///talercheck"
|
||||
|
||||
[mint-wire-sepa]
|
||||
SEPA_RESPONSE_FILE = "sepa.json"
|
||||
|
||||
[mint-wire-test]
|
||||
REDIRECT_URL = "http://test/"
|
||||
|
@ -3,12 +3,13 @@
|
||||
SUBDIRS = . doxygen
|
||||
|
||||
man_MANS = \
|
||||
taler-auditor-sign.1 \
|
||||
taler-mint-dbinit.1 \
|
||||
taler-mint-httpd.1 \
|
||||
taler-mint-keyup.1 \
|
||||
taler-mint-keycheck.1 \
|
||||
taler-mint-reservemod.1 \
|
||||
taler.conf.5
|
||||
taler.conf.5
|
||||
|
||||
EXTRA_DIST = \
|
||||
coding-style.txt \
|
||||
|
98714
doc/paper/rfc.bib
Normal file
98714
doc/paper/rfc.bib
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,13 @@
|
||||
year={2008}
|
||||
}
|
||||
|
||||
@InProceedings{apod,
|
||||
author = {Elli Androulaki and Steven Bellovin},
|
||||
title = {APOD: Anonymous Physical Object Delivery},
|
||||
booktitle = {Symposium on Privacy-Enhancing Technologies (PETS)},
|
||||
year = {2009},
|
||||
}
|
||||
|
||||
@Article{blum1981,
|
||||
author = {Manuel Blum},
|
||||
title = {Coin Flipping by Telephone},
|
||||
@ -12,6 +19,64 @@
|
||||
pages = {11-15},
|
||||
}
|
||||
|
||||
|
||||
@Misc{greece2015cash,
|
||||
author = {Reuters},
|
||||
title = {Greek council recommends 60 euro limit on ATM withdrawals from Tuesday},
|
||||
howpublished = {\url{http://www.reuters.com/article/2015/06/28/eurozone-greece-limits-idUSA8N0Z302P20150628}},
|
||||
month = {June},
|
||||
year = {2015},
|
||||
}
|
||||
|
||||
@Misc{france2015cash,
|
||||
author = {Heinz-Peter Bader},
|
||||
title = {France steps up monitoring of cash payments to fight low-cost terrorism},
|
||||
howpublished = {\url{http://www.reuters.com/article/2015/03/18/us-france-security-financing-idUSKBN0ME14720150318}},
|
||||
month = {Mar},
|
||||
year = {2015},
|
||||
}
|
||||
|
||||
|
||||
@Misc{fatf1997,
|
||||
title = {FATF-IX report on money laundering typologies},
|
||||
howpublished = {\url{http://www.fatf-gafi.org/media/fatf/documents/reports/1996\%201997\%20ENG.pdf}},
|
||||
month = {feb},
|
||||
year = {1998},
|
||||
}
|
||||
|
||||
@TechReport{,
|
||||
author = {},
|
||||
title = {},
|
||||
institution = {},
|
||||
year = {},
|
||||
OPTkey = {},
|
||||
OPTtype = {},
|
||||
OPTnumber = {},
|
||||
OPTaddress = {},
|
||||
OPTmonth = {},
|
||||
OPTnote = {},
|
||||
OPTannote = {}
|
||||
}
|
||||
|
||||
@InProceedings{sander1999escrow,
|
||||
author = {Tomas Sander and Amnon Ta-Shma},
|
||||
title = {On Anonymous Electronic Cash and Crime},
|
||||
booktitle = {ISW'99},
|
||||
year = {1999},
|
||||
series = {LNCS 1729},
|
||||
pages = {202--206},
|
||||
}
|
||||
|
||||
@Article{solms1992perfect,
|
||||
author = {Sebastiaan H. von Solms and David Naccache},
|
||||
title = {On blind signatures and perfect crimes},
|
||||
journal = {Computers \& Security},
|
||||
year = {1992},
|
||||
volume = {11},
|
||||
number = {6},
|
||||
pages = {581--583},
|
||||
}
|
||||
|
||||
@inproceedings{chaum1990untraceable,
|
||||
title={Untraceable electronic cash},
|
||||
author={Chaum, David and Fiat, Amos and Naor, Moni},
|
||||
@ -48,6 +113,23 @@
|
||||
organization={IEEE}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@InProceedings{fc2014murdoch,
|
||||
author = {Stephen Murdoch and Ross Anderson},
|
||||
title = {Security Protocols and Evidence: Where Many Payment Systems Fail},
|
||||
booktitle = {Financial Cryptography and Data Security},
|
||||
year = {2014},
|
||||
}
|
||||
|
||||
@book{ engels1844,
|
||||
author = "Friedrich Engels",
|
||||
title = "{Umrisse zu einer Kritik der National\"okonomie}",
|
||||
year = "1844",
|
||||
publisher = "Ruge and Marx, Paris",
|
||||
}
|
||||
|
||||
|
||||
@inproceedings{selby2004analyzing,
|
||||
title={Analyzing the Success and Failure of Recent e-Payment Schemes},
|
||||
author={Selby, Jack R},
|
||||
@ -91,4 +173,3 @@
|
||||
www_pdf_url = {https://www.torproject.org/svn/trunk/doc/design-paper/tor-design.pdf},
|
||||
www_section = {Anonymous communication},
|
||||
}
|
||||
|
||||
|
1118
doc/paper/taler.tex
1118
doc/paper/taler.tex
File diff suppressed because it is too large
Load Diff
35
doc/taler-auditor-sign.1
Normal file
35
doc/taler-auditor-sign.1
Normal file
@ -0,0 +1,35 @@
|
||||
.TH TALER\-AUDITOR\-SIGN 1 "Sep 15, 2015" "GNU Taler"
|
||||
|
||||
.SH NAME
|
||||
taler\-auditor\-sign \- Sign mint denomination as auditor.
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B taler\-auditor\-sign
|
||||
.RI [ options ]
|
||||
.br
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBtaler\-auditor\-sign\fP is a command line tool to be used by an auditor to sign that he is aware of certain keys being used by a mint. Using this signature, the auditor affirms that he will verify that the mint is properly accounting for those coins.
|
||||
|
||||
.SH OPTIONS
|
||||
.B
|
||||
.IP "\-a FILE, \-\-auditor-key=FILE"
|
||||
Location of the private EdDSA auditor key. If it does not exist, it will be created.
|
||||
.B
|
||||
.IP "\-h, \-\-help"
|
||||
Print short help on options.
|
||||
.B
|
||||
.IP "\-m KEY, \-\-mint-key=KEY"
|
||||
Public key of the mint in Crockford base32 encoding, for example as generated by gnunet\-ecc \-p.
|
||||
.B
|
||||
.IP "\-r FILE, \-\-mint-request=FILE"
|
||||
File with the mint's denomination key signing request as generated by taler\-mint\-keyup \-o.
|
||||
.B
|
||||
.IP "\-o FILE, \-\-output=FILE"
|
||||
File where the auditor should write the EdDSA signature.
|
||||
|
||||
.SH BUGS
|
||||
Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <taler@gnu.org>
|
||||
|
||||
.SH "SEE ALSO"
|
||||
\fBtaler\-mint\-keyup\fP(1), \fBgnunet\-ecc\fP(1), \fBtaler.conf\fP(5)
|
@ -13,6 +13,9 @@ taler\-mint\-httpd \- Run Taler mint (with RESTful API)
|
||||
|
||||
.SH OPTIONS
|
||||
.B
|
||||
.IP "\-C, \-\-connection-close"
|
||||
Force each HTTP connection to be closed after each request (useful in combination with \-f to avoid having to wait for nc to time out).
|
||||
.B
|
||||
.IP "\-d DIRNAME, \-\-mint-dir=DIRNAME"
|
||||
Use the configuration and other resources for the mint to operate from DIRNAME.
|
||||
.B
|
||||
|
@ -22,6 +22,9 @@ Print short help on options.
|
||||
.IP "\-m FILE, \-\-master-key=FILE"
|
||||
Location of the private EdDSA offline master key of the mint.
|
||||
.B
|
||||
.IP "\-o FILE, \-\-ouptut=FILE"
|
||||
Where to write a denomination key signing request file to be given to the auditor.
|
||||
.B
|
||||
.IP "\-t TIMESTAMP, \-\-time=TIMESTAMP"
|
||||
Operate as if the current time was TIMESTAMP.
|
||||
.B
|
||||
|
@ -189,6 +189,18 @@ struct TALER_AuditorPublicKeyP
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Type of the public key used by the auditor.
|
||||
*/
|
||||
struct TALER_AuditorSignatureP
|
||||
{
|
||||
/**
|
||||
* Taler uses EdDSA signatures for auditors.
|
||||
*/
|
||||
struct GNUNET_CRYPTO_EddsaSignature eddsa_sig;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Type of the offline master public keys used by the mint.
|
||||
*/
|
||||
|
@ -167,12 +167,12 @@ TALER_hash_json (json_t *json,
|
||||
/**
|
||||
* Check if the given wire format JSON object is correctly formatted
|
||||
*
|
||||
* @param type the type of the wire format
|
||||
* @param allowed NULL-terminated array of allowed wire format types
|
||||
* @param wire the JSON wire format object
|
||||
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
|
||||
*/
|
||||
int
|
||||
TALER_json_validate_wireformat (const char *type,
|
||||
TALER_json_validate_wireformat (const char **allowed,
|
||||
const json_t *wire);
|
||||
|
||||
|
||||
|
@ -149,6 +149,11 @@ struct TALER_MINT_DenomPublicKey
|
||||
*/
|
||||
struct TALER_DenominationPublicKey key;
|
||||
|
||||
/**
|
||||
* The hash of the public key.
|
||||
*/
|
||||
struct GNUNET_HashCode h_key;
|
||||
|
||||
/**
|
||||
* Timestamp indicating when the denomination key becomes valid
|
||||
*/
|
||||
@ -165,6 +170,15 @@ struct TALER_MINT_DenomPublicKey
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute deposit_valid_until;
|
||||
|
||||
/**
|
||||
* When do signatures with this denomination key become invalid?
|
||||
* After this point, these signatures cannot be used in (legal)
|
||||
* disputes anymore, as the Mint is then allowed to destroy its side
|
||||
* of the evidence. @e expire_legal is expected to be significantly
|
||||
* larger than @e expire_spend (by a year or more).
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute expire_legal;
|
||||
|
||||
/**
|
||||
* The value of this denomination
|
||||
*/
|
||||
@ -204,6 +218,8 @@ struct TALER_MINT_AuditorInformation
|
||||
* that website. We expect that in practice software is going to
|
||||
* often ship with an initial list of accepted auditors, just like
|
||||
* browsers ship with a CA root store.
|
||||
*
|
||||
* This field may be NULL. (#3987).
|
||||
*/
|
||||
const char *auditor_url;
|
||||
|
||||
@ -218,7 +234,7 @@ struct TALER_MINT_AuditorInformation
|
||||
* elements point to the same locations as the entries
|
||||
* in the key's main `denom_keys` array.
|
||||
*/
|
||||
struct TALER_MINT_DenomPublicKey *const*denom_keys;
|
||||
const struct TALER_MINT_DenomPublicKey **denom_keys;
|
||||
};
|
||||
|
||||
|
||||
@ -246,7 +262,7 @@ struct TALER_MINT_Keys
|
||||
/**
|
||||
* Array of the keys of the auditors of the mint.
|
||||
*/
|
||||
struct TALER_AuditorPublicKeyP *auditors;
|
||||
struct TALER_MINT_AuditorInformation *auditors;
|
||||
|
||||
/**
|
||||
* Length of the @e sign_keys array.
|
||||
@ -353,6 +369,100 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
|
||||
const struct TALER_DenominationPublicKey *pk);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the denomination key details from the mint.
|
||||
*
|
||||
* @param keys the mint's key set
|
||||
* @param hc hash of the public key of the denomination to lookup
|
||||
* @return details about the given denomination key
|
||||
*/
|
||||
const struct TALER_MINT_DenomPublicKey *
|
||||
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
|
||||
const struct GNUNET_HashCode *hc);
|
||||
|
||||
|
||||
/* ********************* /wire *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A Wire format inquiry handle
|
||||
*/
|
||||
struct TALER_MINT_WireHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks of this type are used to serve the result of submitting a
|
||||
* wire format inquiry request to a mint.
|
||||
*
|
||||
* The callback is invoked multiple times, once for each supported @a
|
||||
* method. Finally, it is invoked one more time with cls/0/NULL/NULL
|
||||
* to indicate the end of the iteration. If any request fails to
|
||||
* generate a valid response from the mint, @a http_status will also
|
||||
* be zero and the iteration will also end. Thus, the iteration
|
||||
* always ends with a final call with an @a http_status of 0. If the
|
||||
* @a http_status is already 0 on the first call, then the response to
|
||||
* the /wire request was invalid. Later, clients can tell the
|
||||
* difference between @a http_status of 0 indicating a failed
|
||||
* /wire/method request and a regular end of the iteration by @a
|
||||
* method being non-NULL. If the mint simply correctly asserts that
|
||||
* it does not support any methods, @a method will be NULL but the @a
|
||||
* http_status will be #MHD_HTTP_OK for the first call (followed by a
|
||||
* cls/0/NULL/NULL call to signal the end of the iteration).
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
|
||||
* 0 if the mint's reply is bogus (fails to follow the protocol)
|
||||
* @param method wire format method supported, i.e. "test" or "sepa", or NULL
|
||||
* if already the /wire request failed.
|
||||
* @param obj the received JSON reply, if successful this should be the wire
|
||||
* format details as provided by /wire/METHOD/, or NULL if the
|
||||
* reply was not in JSON format (in this case, the client might
|
||||
* want to do an HTTP request to /wire/METHOD/ with a browser to
|
||||
* provide more information to the user about the @a method).
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_MINT_WireResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
const char *method,
|
||||
json_t *obj);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain information about a mint's wire instructions.
|
||||
* A mint may provide wire instructions for creating
|
||||
* a reserve. The wire instructions also indicate
|
||||
* which wire formats merchants may use with the mint.
|
||||
* This API is typically used by a wallet for wiring
|
||||
* funds, and possibly by a merchant to determine
|
||||
* supported wire formats.
|
||||
*
|
||||
* Note that while we return the (main) response verbatim 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). 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 wire_cb the callback to call when a reply for this request is available
|
||||
* @param wire_cb_cls closure for the above callback
|
||||
* @return a handle for this request
|
||||
*/
|
||||
struct TALER_MINT_WireHandle *
|
||||
TALER_MINT_wire (struct TALER_MINT_Handle *mint,
|
||||
TALER_MINT_WireResultCallback wire_cb,
|
||||
void *wire_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Cancel a wire information request. This function cannot be used
|
||||
* on a request handle if a response is already served for it.
|
||||
*
|
||||
* @param wh the wire information request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_wire_cancel (struct TALER_MINT_WireHandle *wh);
|
||||
|
||||
|
||||
/* ********************* /deposit *********************** */
|
||||
|
||||
|
||||
@ -437,13 +547,13 @@ void
|
||||
TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit);
|
||||
|
||||
|
||||
/* ********************* /withdraw/status *********************** */
|
||||
/* ********************* /reserve/status *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A /withdraw/status Handle
|
||||
* @brief A /reserve/status Handle
|
||||
*/
|
||||
struct TALER_MINT_WithdrawStatusHandle;
|
||||
struct TALER_MINT_ReserveStatusHandle;
|
||||
|
||||
|
||||
/**
|
||||
@ -513,12 +623,12 @@ struct TALER_MINT_ReserveHistory
|
||||
* @param history detailed transaction history, NULL on error
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_MINT_WithdrawStatusResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
const struct TALER_MINT_ReserveHistory *history);
|
||||
(*TALER_MINT_ReserveStatusResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
const struct TALER_MINT_ReserveHistory *history);
|
||||
|
||||
|
||||
/**
|
||||
@ -537,11 +647,11 @@ typedef void
|
||||
* @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);
|
||||
struct TALER_MINT_ReserveStatusHandle *
|
||||
TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
TALER_MINT_ReserveStatusResultCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
@ -551,16 +661,16 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
|
||||
* @param wsh the withdraw status request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh);
|
||||
TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh);
|
||||
|
||||
|
||||
/* ********************* /withdraw/sign *********************** */
|
||||
/* ********************* /reserve/withdraw *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A /withdraw/sign Handle
|
||||
* @brief A /reserve/withdraw Handle
|
||||
*/
|
||||
struct TALER_MINT_WithdrawSignHandle;
|
||||
struct TALER_MINT_ReserveWithdrawHandle;
|
||||
|
||||
|
||||
/**
|
||||
@ -574,14 +684,14 @@ struct TALER_MINT_WithdrawSignHandle;
|
||||
* @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);
|
||||
(*TALER_MINT_ReserveWithdrawResultCallback) (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. This
|
||||
* Withdraw a coin from the mint using a /reserve/withdraw request. This
|
||||
* API is typically used by a wallet. 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
|
||||
@ -601,14 +711,14 @@ typedef void
|
||||
* 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);
|
||||
struct TALER_MINT_ReserveWithdrawHandle *
|
||||
TALER_MINT_reserve_withdraw (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_ReserveWithdrawResultCallback res_cb,
|
||||
void *res_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
@ -618,7 +728,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
|
||||
* @param sign the withdraw sign request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign);
|
||||
TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign);
|
||||
|
||||
|
||||
/* ********************* /refresh/melt+reveal ***************************** */
|
||||
|
@ -37,6 +37,12 @@
|
||||
*/
|
||||
#define TALER_MINTDB_DIR_DENOMINATION_KEYS "denomkeys"
|
||||
|
||||
/**
|
||||
* Subdirectory under the mint's base directory which contains
|
||||
* the mint's auditing information.
|
||||
*/
|
||||
#define TALER_MINTDB_DIR_AUDITORS "auditors"
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
@ -62,7 +68,7 @@ struct TALER_MINTDB_PrivateSigningKeyInformationP
|
||||
|
||||
/**
|
||||
* Information about a denomination key.
|
||||
*/
|
||||
*/
|
||||
struct TALER_MINTDB_DenominationKeyInformationP
|
||||
{
|
||||
|
||||
@ -123,23 +129,6 @@ typedef int
|
||||
const struct TALER_MINTDB_PrivateSigningKeyInformationP *ski);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over denomination keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param dki the denomination key
|
||||
* @param alias coin alias
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_MINTDB_DenominationKeyIterator)(void *cls,
|
||||
const char *alias,
|
||||
const struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each signing key found in the @a mint_base_dir.
|
||||
*
|
||||
@ -158,6 +147,23 @@ TALER_MINTDB_signing_keys_iterate (const char *mint_base_dir,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over denomination keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param dki the denomination key
|
||||
* @param alias coin alias
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_MINTDB_DenominationKeyIterator)(void *cls,
|
||||
const char *alias,
|
||||
const struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each denomination key found in the @a mint_base_dir.
|
||||
*
|
||||
@ -201,6 +207,67 @@ TALER_MINTDB_denomination_key_read (const char *filename,
|
||||
struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over auditor information.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param apub the auditor's public key
|
||||
* @param mpub the mint's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a asig and @a dki arrays
|
||||
* @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len
|
||||
* @param dki array of denomination coin data signed by the auditor, of length @a dki_len
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_MINTDB_AuditorIterator)(void *cls,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
unsigned int dki_len,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_DenominationKeyValidityPS *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it with information for each auditor found in the @a mint_base_dir.
|
||||
*
|
||||
* @param mint_base_dir base directory for the mint,
|
||||
* the signing keys must be in the #TALER_MINTDB_DIR_DENOMINATION_KEYS
|
||||
* subdirectory
|
||||
* @param it function to call with auditor information
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_MINTDB_auditor_iterate (const char *mint_base_dir,
|
||||
TALER_MINTDB_AuditorIterator it,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Write auditor information to the given file.
|
||||
*
|
||||
* @param filename the file where to write the auditor information to
|
||||
* @param apub the auditor's public key
|
||||
* @param asigs the auditor's signatures, array of length @a dki_len
|
||||
* @param mpub the mint's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a dki and @a asigs arrays
|
||||
* @param dki array of denomination coin data signed by the auditor
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_MINTDB_auditor_write (const char *filename,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
unsigned int dki_len,
|
||||
const struct TALER_DenominationKeyValidityPS *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the plugin.
|
||||
*
|
||||
|
@ -416,30 +416,6 @@ struct TALER_MINTDB_LinkDataList
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Specification for a /lock operation.
|
||||
*/
|
||||
struct TALER_MINTDB_LockOperation
|
||||
{
|
||||
/**
|
||||
* Information about the coin that is being locked.
|
||||
*/
|
||||
struct TALER_CoinPublicInfo coin;
|
||||
|
||||
/**
|
||||
* Signature over the locking operation.
|
||||
*/
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
|
||||
/**
|
||||
* How much value is being locked?
|
||||
*/
|
||||
struct TALER_Amount amount;
|
||||
|
||||
// FIXME: more needed...
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration to classify the different types of transactions
|
||||
* that can be done with a coin.
|
||||
@ -454,12 +430,8 @@ enum TALER_MINTDB_TransactionType
|
||||
/**
|
||||
* /refresh/melt operation.
|
||||
*/
|
||||
TALER_MINTDB_TT_REFRESH_MELT = 1,
|
||||
TALER_MINTDB_TT_REFRESH_MELT = 1
|
||||
|
||||
/**
|
||||
* /lock operation.
|
||||
*/
|
||||
TALER_MINTDB_TT_LOCK = 2
|
||||
};
|
||||
|
||||
|
||||
@ -495,11 +467,6 @@ struct TALER_MINTDB_TransactionList
|
||||
*/
|
||||
struct TALER_MINTDB_RefreshMelt *melt;
|
||||
|
||||
/**
|
||||
* Details if transaction was a /lock operation.
|
||||
*/
|
||||
struct TALER_MINTDB_LockOperation *lock;
|
||||
|
||||
} details;
|
||||
|
||||
};
|
||||
@ -549,6 +516,31 @@ struct TALER_MINTDB_MeltCommitment
|
||||
struct TALER_MINTDB_Session;
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about deposits that
|
||||
* have been made, with the goal of executing the
|
||||
* corresponding wire transaction.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param id transaction ID (used as future `min_id` to avoid
|
||||
* iterating over transactions more than once)
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param deposit_fee amount the mint gets to keep as transaction fees
|
||||
* @param transaction_id unique transaction ID chosen by the merchant
|
||||
* @param h_contract hash of the contract between merchant and customer
|
||||
* @param wire wire details for the merchant
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_MINTDB_DepositIterator)(void *cls,
|
||||
uint64_t id,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
const struct TALER_Amount *deposit_fee,
|
||||
uint64_t transaction_id,
|
||||
const struct GNUNET_HashCode *h_contract,
|
||||
const json_t *wire);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the session hashes and transfer secret
|
||||
* information for a given coin.
|
||||
@ -636,23 +628,24 @@ struct TALER_MINTDB_Plugin
|
||||
* Commit a transaction.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to use
|
||||
* @return #GNUNET_OK on success
|
||||
* @param session connection to use
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if the transaction
|
||||
* can be retried, #GNUNET_SYSERR on hard failures
|
||||
*/
|
||||
int
|
||||
(*commit) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion);
|
||||
struct TALER_MINTDB_Session *session);
|
||||
|
||||
|
||||
/**
|
||||
* Abort/rollback a transaction.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to use
|
||||
* @param session connection to use
|
||||
*/
|
||||
void
|
||||
(*rollback) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion);
|
||||
struct TALER_MINTDB_Session *session);
|
||||
|
||||
|
||||
/**
|
||||
@ -661,7 +654,7 @@ struct TALER_MINTDB_Plugin
|
||||
* with this key have.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to use
|
||||
* @param session connection to use
|
||||
* @param denom_pub the public key used for signing coins of this denomination
|
||||
* @param issue issuing information with value, fees and other info about the coin
|
||||
* @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
|
||||
@ -677,7 +670,7 @@ struct TALER_MINTDB_Plugin
|
||||
* Fetch information about a denomination key.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to use
|
||||
* @param session connection to use
|
||||
* @param denom_pub the public key used for signing coins of this denomination
|
||||
* @param[out] issue set to issue information with value, fees and other info about the coin, can be NULL
|
||||
* @return #GNUNET_OK on success; #GNUNET_NO if no record was found, #GNUNET_SYSERR on failure
|
||||
@ -736,7 +729,7 @@ struct TALER_MINTDB_Plugin
|
||||
* key of the hash of the blinded message.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param h_blind hash of the blinded coin to be signed (will match
|
||||
* `h_coin_envelope` in the @a collectable to be returned)
|
||||
* @param collectable corresponding collectable coin (blind signature)
|
||||
@ -747,7 +740,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_withdraw_info) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *h_blind,
|
||||
struct TALER_MINTDB_CollectableBlindcoin *collectable);
|
||||
|
||||
@ -757,7 +750,7 @@ struct TALER_MINTDB_Plugin
|
||||
* hash of the blinded message.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param collectable corresponding collectable coin (blind signature)
|
||||
* if a coin is found
|
||||
* @return #GNUNET_SYSERR on internal error
|
||||
@ -766,7 +759,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_withdraw_info) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_MINTDB_CollectableBlindcoin *collectable);
|
||||
|
||||
|
||||
@ -775,13 +768,13 @@ struct TALER_MINTDB_Plugin
|
||||
* reserve.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to use
|
||||
* @param session connection to use
|
||||
* @param reserve_pub public key of the reserve
|
||||
* @return known transaction history (NULL if reserve is unknown)
|
||||
*/
|
||||
struct TALER_MINTDB_ReserveHistory *
|
||||
(*get_reserve_history) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub);
|
||||
|
||||
|
||||
@ -800,7 +793,7 @@ struct TALER_MINTDB_Plugin
|
||||
* Check if we have the specified deposit already in the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param deposit deposit to search for
|
||||
* @return #GNUNET_YES if we know this operation,
|
||||
* #GNUNET_NO if this exact deposit is unknown to us,
|
||||
@ -808,30 +801,53 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*have_deposit) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_MINTDB_Deposit *deposit);
|
||||
|
||||
|
||||
/**
|
||||
* Insert information about deposited coin into the
|
||||
* database.
|
||||
* Insert information about deposited coin into the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion connection to the database
|
||||
* @param session connection to the database
|
||||
* @param deposit deposit information to store
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||
*/
|
||||
int
|
||||
(*insert_deposit) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_MINTDB_Deposit *deposit);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain information about deposits. Iterates over all deposits
|
||||
* above a certain ID. Use a @a min_id of 0 to start at the beginning.
|
||||
* This operation is executed in its own transaction in transaction
|
||||
* mode "REPEATABLE READ", i.e. we should only see valid deposits.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to the database
|
||||
* @param min_id deposit to start at
|
||||
* @param limit maximum number of transactions to fetch
|
||||
* @param deposit_cb function to call for each deposit
|
||||
* @param deposit_cb_cls closure for @a deposit_cb
|
||||
* @return number of rows processed, 0 if none exist,
|
||||
* #GNUNET_SYSERR on error
|
||||
*/
|
||||
int
|
||||
(*iterate_deposits) (void *cls,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
uint64_t min_id,
|
||||
uint32_t limit,
|
||||
TALER_MINTDB_DepositIterator deposit_cb,
|
||||
void *deposit_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Lookup refresh session data under the given @a session_hash.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database handle to use
|
||||
* @param session database handle to use
|
||||
* @param session_hash hash over the melt to use for the lookup
|
||||
* @param[out] refresh_session where to store the result
|
||||
* @return #GNUNET_YES on success,
|
||||
@ -840,7 +856,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_refresh_session) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
struct TALER_MINTDB_RefreshSession *refresh_session);
|
||||
|
||||
@ -849,7 +865,7 @@ struct TALER_MINTDB_Plugin
|
||||
* Store new refresh session data under the given @a session_hash.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database handle to use
|
||||
* @param session database handle to use
|
||||
* @param session_hash hash over the melt to use to locate the session
|
||||
* @param refresh_session session data to store
|
||||
* @return #GNUNET_YES on success,
|
||||
@ -857,7 +873,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*create_refresh_session) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
const struct TALER_MINTDB_RefreshSession *refresh_session);
|
||||
|
||||
@ -866,7 +882,7 @@ struct TALER_MINTDB_Plugin
|
||||
* Store the given /refresh/melt request in the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param oldcoin_index index of the coin to store
|
||||
* @param melt coin melt operation details to store; includes
|
||||
* the session hash of the melt
|
||||
@ -875,7 +891,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_refresh_melt) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
uint16_t oldcoin_index,
|
||||
const struct TALER_MINTDB_RefreshMelt *melt);
|
||||
|
||||
@ -884,7 +900,7 @@ struct TALER_MINTDB_Plugin
|
||||
* Get information about melted coin details from the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param oldcoin_index index of the coin to retrieve
|
||||
* @param melt melt data to fill in, can be NULL
|
||||
@ -893,7 +909,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_refresh_melt) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t oldcoin_index,
|
||||
struct TALER_MINTDB_RefreshMelt *melt);
|
||||
@ -904,7 +920,7 @@ struct TALER_MINTDB_Plugin
|
||||
* in a given refresh operation.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param num_newcoins number of coins to generate, size of the @a denom_pubs array
|
||||
* @param denom_pubs array denominations of the coins to create
|
||||
@ -913,7 +929,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_refresh_order) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_newcoins,
|
||||
const struct TALER_DenominationPublicKey *denom_pubs);
|
||||
@ -924,7 +940,7 @@ struct TALER_MINTDB_Plugin
|
||||
* create in the given refresh operation.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param num_newcoins size of the @a denom_pubs array
|
||||
* @param[out] denom_pubs where to write @a num_newcoins denomination keys
|
||||
@ -933,7 +949,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_refresh_order) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_newcoins,
|
||||
struct TALER_DenominationPublicKey *denom_pubs);
|
||||
@ -944,7 +960,7 @@ struct TALER_MINTDB_Plugin
|
||||
* for the given refresh session in the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA
|
||||
* @param num_newcoins coin index size of the @a commit_coins array
|
||||
@ -954,7 +970,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_refresh_commit_coins) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t cnc_index,
|
||||
uint16_t num_newcoins,
|
||||
@ -966,7 +982,7 @@ struct TALER_MINTDB_Plugin
|
||||
* given coin of the given refresh session from the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param cnc_index cut and choose set index (1st dimension)
|
||||
* @param num_coins size of the @a commit_coins array
|
||||
@ -977,7 +993,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_refresh_commit_coins) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t cnc_index,
|
||||
uint16_t num_coins,
|
||||
@ -989,7 +1005,7 @@ struct TALER_MINTDB_Plugin
|
||||
* for the given refresh session.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA
|
||||
* @param num_links size of the @a commit_link array
|
||||
@ -998,7 +1014,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_refresh_commit_links) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t cnc_index,
|
||||
uint16_t num_links,
|
||||
@ -1009,7 +1025,7 @@ struct TALER_MINTDB_Plugin
|
||||
* for the given refresh session.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param cnc_index cut and choose index (1st dimension)
|
||||
* @param num_links size of the @a links array to return
|
||||
@ -1020,7 +1036,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_refresh_commit_links) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t cnc_index,
|
||||
uint16_t num_links,
|
||||
@ -1031,14 +1047,14 @@ struct TALER_MINTDB_Plugin
|
||||
* Get all of the information from the given melt commit operation.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection to use
|
||||
* @param session database connection to use
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @return NULL if the @a session_hash does not correspond to any known melt
|
||||
* operation
|
||||
*/
|
||||
struct TALER_MINTDB_MeltCommitment *
|
||||
(*get_melt_commitment) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash);
|
||||
|
||||
|
||||
@ -1060,7 +1076,7 @@ struct TALER_MINTDB_Plugin
|
||||
* be used to try to obtain the private keys during "/refresh/link".
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param session_hash hash to identify refresh session
|
||||
* @param newcoin_index coin index
|
||||
* @param ev_sig coin signature
|
||||
@ -1068,7 +1084,7 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*insert_refresh_out) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t newcoin_index,
|
||||
const struct TALER_DenominationSignature *ev_sig);
|
||||
@ -1079,13 +1095,13 @@ struct TALER_MINTDB_Plugin
|
||||
* information, the denomination keys and the signatures.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param session_hash session to get linkage data for
|
||||
* @return all known link data for the session
|
||||
*/
|
||||
struct TALER_MINTDB_LinkDataList *
|
||||
(*get_link_data_list) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash);
|
||||
|
||||
|
||||
@ -1108,7 +1124,7 @@ struct TALER_MINTDB_Plugin
|
||||
*
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param coin_pub public key of the coin
|
||||
* @param tdc function to call for each session the coin was melted into
|
||||
* @param tdc_cls closure for @a tdc
|
||||
@ -1118,56 +1134,24 @@ struct TALER_MINTDB_Plugin
|
||||
*/
|
||||
int
|
||||
(*get_transfer) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
TALER_MINTDB_TransferDataCallback tdc,
|
||||
void *tdc_cls);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test if the given /lock request is known to us.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param lock lock operation
|
||||
* @return #GNUNET_YES if known,
|
||||
* #GNUNET_NO if not,
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
int
|
||||
(*have_lock) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
const struct TALER_MINTDB_LockOperation *lock);
|
||||
|
||||
|
||||
/**
|
||||
* Store the given /lock request in the database.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param lock lock operation
|
||||
* @return #GNUNET_OK on success
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
int
|
||||
(*insert_lock) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
const struct TALER_MINTDB_LockOperation *lock);
|
||||
|
||||
|
||||
/**
|
||||
* Compile a list of all (historic) transactions performed
|
||||
* with the given coin (/refresh/melt and /deposit operations).
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param sesssion database connection
|
||||
* @param session database connection
|
||||
* @param coin_pub coin to investigate
|
||||
* @return list of transactions, NULL if coin is fresh
|
||||
*/
|
||||
struct TALER_MINTDB_TransactionList *
|
||||
(*get_coin_transactions) (void *cls,
|
||||
struct TALER_MINTDB_Session *sesssion,
|
||||
struct TALER_MINTDB_Session *session,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub);
|
||||
|
||||
|
||||
|
@ -653,13 +653,73 @@ struct TALER_MintKeyValidityPS
|
||||
struct TALER_MasterPublicKeyP master;
|
||||
|
||||
/**
|
||||
* Array of hash(es) of the mint's denomination keys.
|
||||
* Specifically, this is the hash over the
|
||||
* `struct TALER_DenominationKeyValidityPS`, not just
|
||||
* the public key (as the auditor needs to check against
|
||||
* the correct valuations and fee structure).
|
||||
* Start time of the validity period for this key.
|
||||
*/
|
||||
/* struct GNUNET_HashCode h_dks; */
|
||||
struct GNUNET_TIME_AbsoluteNBO start;
|
||||
|
||||
/**
|
||||
* The mint will sign fresh coins between @e start and this time.
|
||||
* @e expire_withdraw will be somewhat larger than @e start to
|
||||
* ensure a sufficiently large anonymity set, while also allowing
|
||||
* the Mint to limit the financial damage in case of a key being
|
||||
* compromised. Thus, mints with low volume are expected to have a
|
||||
* longer withdraw period (@e expire_withdraw - @e start) than mints
|
||||
* with high transaction volume. The period may also differ between
|
||||
* types of coins. A mint may also have a few denomination keys
|
||||
* with the same value with overlapping validity periods, to address
|
||||
* issues such as clock skew.
|
||||
*/
|
||||
struct GNUNET_TIME_AbsoluteNBO expire_withdraw;
|
||||
|
||||
/**
|
||||
* Coins signed with the denomination key must be spent or refreshed
|
||||
* between @e start and this expiration time. After this time, the
|
||||
* mint will refuse transactions involving this key as it will
|
||||
* "drop" the table with double-spending information (shortly after)
|
||||
* this time. Note that wallets should refresh coins significantly
|
||||
* before this time to be on the safe side. @e expire_spend must be
|
||||
* significantly larger than @e expire_withdraw (by months or even
|
||||
* years).
|
||||
*/
|
||||
struct GNUNET_TIME_AbsoluteNBO expire_spend;
|
||||
|
||||
/**
|
||||
* When do signatures with this denomination key become invalid?
|
||||
* After this point, these signatures cannot be used in (legal)
|
||||
* disputes anymore, as the Mint is then allowed to destroy its side
|
||||
* of the evidence. @e expire_legal is expected to be significantly
|
||||
* larger than @e expire_spend (by a year or more).
|
||||
*/
|
||||
struct GNUNET_TIME_AbsoluteNBO expire_legal;
|
||||
|
||||
/**
|
||||
* The value of the coins signed with this denomination key.
|
||||
*/
|
||||
struct TALER_AmountNBO value;
|
||||
|
||||
/**
|
||||
* The fee the mint charges when a coin of this type is withdrawn.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_withdraw;
|
||||
|
||||
/**
|
||||
* The fee the mint charges when a coin of this type is deposited.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_deposit;
|
||||
|
||||
/**
|
||||
* The fee the mint charges when a coin of this type is refreshed.
|
||||
* (can be zero).
|
||||
*/
|
||||
struct TALER_AmountNBO fee_refresh;
|
||||
|
||||
/**
|
||||
* Hash code of the denomination public key. (Used to avoid having
|
||||
* the variable-size RSA key in this struct.)
|
||||
*/
|
||||
struct GNUNET_HashCode denom_hash GNUNET_PACKED;
|
||||
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,8 @@ libtalermint_la_SOURCES = \
|
||||
mint_api_deposit.c \
|
||||
mint_api_refresh.c \
|
||||
mint_api_refresh_link.c \
|
||||
mint_api_withdraw.c
|
||||
mint_api_reserve.c \
|
||||
mint_api_wire.c
|
||||
|
||||
libtalermint_la_LIBADD = \
|
||||
-lgnunetutil \
|
||||
|
34
src/mint-lib/afl-generate.sh
Normal file
34
src/mint-lib/afl-generate.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This file is part of TALER
|
||||
# Copyright (C) 2015 GNUnet e.V.
|
||||
#
|
||||
# TALER is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with
|
||||
# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
#
|
||||
# This will generate testcases in a directory 'afl-tests', which can then
|
||||
# be moved into src/mint/afl-tests/ to be run during mint-testing.
|
||||
#
|
||||
# This script uses American Fuzzy Loop (AFL) to fuzz the mint to
|
||||
# automatically create tests with good coverage. You must install
|
||||
# AFL and set AFL_HOME to the directory where AFL is installed
|
||||
# before running. Also, a directory "baseline/" should exist with
|
||||
# templates for inputs for AFL to fuzz. These can be generated
|
||||
# by running wireshark on loopback while running 'make check' in
|
||||
# this directory. Save each HTTP request to a new file.
|
||||
#
|
||||
# Note that you want to switch 'TESTRUN = NO' and pre-init the
|
||||
# database before running this, otherwise it will be awfully slow.
|
||||
#
|
||||
# Must be run from this directory.
|
||||
#
|
||||
$AFL_HOME/afl-fuzz -i baseline/ -m 250 -o afl-tests/ -f /tmp/afl-input taler-mint-httpd -f /tmp/afl-input -d test-mint-home/ -C
|
7
src/mint-lib/baseline/admin_add_incoming.req
Normal file
7
src/mint-lib/baseline/admin_add_incoming.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
8
src/mint-lib/baseline/deposit.req
Normal file
8
src/mint-lib/baseline/deposit.req
Normal file
@ -0,0 +1,8 @@
|
||||
POST /deposit HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 1658
|
||||
Expect: 100-continue
|
||||
|
||||
{"ub_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26E9M8S0M6CSH6X334GSN8RW30D9G8MT46CA660W34GSG6MT4AD9K8GT3ECSH6MVK0E2374V38H1M8MR4CDJ66MWK4E1S6MR3GCT28CV32H1Q8N23GCHG70S36C1K8MS3GCSN8RV36D9S710KGD9K6GWKEGJ28GRM4CJ56X1K6DJ18D2KGHA46D13GDA66GVK4GHJ8N13AE9J8RVK6GT184S48E1K6X336G9Q8N142CJ4692M6EA16GRKJD9N6523ADA36X13GG9G70TK6DHN68R36CT18GR4CDSJ6CW3GCT364W46CSR8RV42GJ474SMADSH851K4H9Q8GS42CHS8RV3GCSJ64V46DSN8RSM6HHN6N246D9S6934AH9P6X23JGSH652K0DJ5612KJGA26N242CH35452081918G2J2G0","timestamp":"/Date(1442821652)/","f":{"currency":"EUR","value":5,"fraction":0},"wire":{"type":"TEST","bank":"dest bank","account":42},"coin_pub":"JXWK4NS0H2W4V4BETQ90CCEDADP6QQ3MV3YZ7RV2KXEM8PWXE8Q0","H_wire":"YQED9FDYPKK2QQYB3FS19Y15ZMKBAXJP2C73CXASAF1KM6ZYY723TEJ3HBR6D864A7X5W58G92QJ0A9PFMZNB81ZP9NJAQQCCABM4RG","H_contract":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","transaction_id":1,"refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"}
|
7
src/mint-lib/baseline/keys.req
Normal file
7
src/mint-lib/baseline/keys.req
Normal file
@ -0,0 +1,7 @@
|
||||
GET /keys HTTP/1.1
|
||||
User-Agent: Wget/1.16.3 (linux-gnu)
|
||||
Accept: */*
|
||||
Accept-Encoding: identity
|
||||
Host: 127.0.0.1:8081
|
||||
Connection: Keep-Alive
|
||||
|
5
src/mint-lib/baseline/refresh_link.req
Normal file
5
src/mint-lib/baseline/refresh_link.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /refresh/link?coin_pub=WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
8
src/mint-lib/baseline/refresh_melt.req
Normal file
8
src/mint-lib/baseline/refresh_melt.req
Normal file
File diff suppressed because one or more lines are too long
7
src/mint-lib/baseline/refresh_reveal.req
Normal file
7
src/mint-lib/baseline/refresh_reveal.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /refresh/reveal HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 255
|
||||
|
||||
{"session_hash":"V97SB8T670M9V71D1Q0KVQ4GSJCVQ5AAKTTH9QKT0ZJZZBFNZAV4NA8NMWRRGVPFEBEGB6ANCN9BPQASJ40TM4Y1C49648TJJ07PGSG","transfer_privs":[["EQKJA401A9NJ2YJDFZJ1EV8AYXBHWZB6NT5T0TWSJHVKVDM6W8A0"],["TKDJ4DF3GZVG0DGAB9E3RGBGSTANYB6JVVWXJGPMB2AY4VQNTBA0"]]}
|
4
src/mint-lib/baseline/reserve_status.req
Normal file
4
src/mint-lib/baseline/reserve_status.req
Normal file
@ -0,0 +1,4 @@
|
||||
GET /reserve/status?reserve_pub=TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0 HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
|
7
src/mint-lib/baseline/reserve_withdraw.req
Normal file
7
src/mint-lib/baseline/reserve_withdraw.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /reserve/withdraw HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 919
|
||||
|
||||
{"coin_ev":"Q5X8A8TCBFH7E5BMY7HSB17SHFTM1JPJGV61P2CA7Z9EXG8P2HYS69B31NZESKXHSZHNJ2DQN3CC2AWFNC6V90J577JD3TXBMAY8Y5M9V60KKT73Z1DW24JFSNAK91G1F2WT55ADP1EG7N5F9AY7A7ZJD03MPYSH0RDP7SVZS2KRPA5JRHFR4GDJ59CFNE7A43M95ZKQHQAS8","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","reserve_sig":"8427B3RTB217124EB1C37ZVJFC08KN17RHGHE9ENZQMQVJ0S11SAX6H8Z06SWCKT06DRQ9DQ8XD786XKQ94T27PYR9GC9EMT1Y02W10"}
|
5
src/mint-lib/baseline/wire.req
Normal file
5
src/mint-lib/baseline/wire.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
5
src/mint-lib/baseline/wire_sepa.req
Normal file
5
src/mint-lib/baseline/wire_sepa.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire/sepa HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
5
src/mint-lib/baseline/wire_test.req
Normal file
5
src/mint-lib/baseline/wire_test.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire/test HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
@ -435,6 +435,29 @@ MAC_download_get_result (struct MAC_DownloadBuffer *db,
|
||||
{
|
||||
json_t *json;
|
||||
json_error_t error;
|
||||
char *ct;
|
||||
|
||||
if ( (CURLE_OK !=
|
||||
curl_easy_getinfo (eh,
|
||||
CURLINFO_CONTENT_TYPE,
|
||||
&ct)) ||
|
||||
(NULL == ct) ||
|
||||
(0 != strcasecmp (ct,
|
||||
"application/json")) )
|
||||
{
|
||||
/* No content type or explicitly not JSON, refuse to parse
|
||||
(but keep response code) */
|
||||
if (CURLE_OK !=
|
||||
curl_easy_getinfo (eh,
|
||||
CURLINFO_RESPONSE_CODE,
|
||||
response_code))
|
||||
{
|
||||
/* unexpected error... */
|
||||
GNUNET_break (0);
|
||||
*response_code = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json = NULL;
|
||||
if (0 == db->eno)
|
||||
|
@ -325,9 +325,11 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
|
||||
&denom_key_issue.denom_hash,
|
||||
sizeof (struct GNUNET_HashCode));
|
||||
denom_key->key.rsa_public_key = pk;
|
||||
denom_key->h_key = denom_key_issue.denom_hash;
|
||||
denom_key->valid_from = valid_from;
|
||||
denom_key->withdraw_valid_until = withdraw_valid_until;
|
||||
denom_key->deposit_valid_until = deposit_valid_until;
|
||||
denom_key->expire_legal = expire_legal;
|
||||
denom_key->value = value;
|
||||
denom_key->fee_withdraw = fee_withdraw;
|
||||
denom_key->fee_deposit = fee_deposit;
|
||||
@ -340,6 +342,116 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a mint's auditor information encoded in JSON.
|
||||
*
|
||||
* @param[out] auditor where to return the result
|
||||
* @param[in] auditor_obj json to parse
|
||||
* @param key_data information about denomination keys
|
||||
* @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
|
||||
* invalid or the json malformed.
|
||||
*/
|
||||
static int
|
||||
parse_json_auditor (struct TALER_MINT_AuditorInformation *auditor,
|
||||
json_t *auditor_obj,
|
||||
const struct TALER_MINT_Keys *key_data)
|
||||
{
|
||||
json_t *keys;
|
||||
json_t *key;
|
||||
unsigned int len;
|
||||
unsigned int off;
|
||||
unsigned int i;
|
||||
struct TALER_MintKeyValidityPS kv;
|
||||
struct MAJ_Specification spec[] = {
|
||||
MAJ_spec_fixed_auto ("auditor_pub",
|
||||
&auditor->auditor_pub),
|
||||
MAJ_spec_json ("denomination_keys",
|
||||
&keys),
|
||||
MAJ_spec_end
|
||||
};
|
||||
|
||||
auditor->auditor_url = NULL; /* #3987 */
|
||||
if (GNUNET_OK !=
|
||||
MAJ_parse_json (auditor_obj,
|
||||
spec))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
|
||||
kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
|
||||
kv.master = key_data->master_pub;
|
||||
len = json_array_size (keys);
|
||||
auditor->denom_keys = GNUNET_new_array (len,
|
||||
const struct TALER_MINT_DenomPublicKey *);
|
||||
i = 0;
|
||||
off = 0;
|
||||
json_array_foreach (keys, i, key) {
|
||||
struct TALER_AuditorSignatureP auditor_sig;
|
||||
struct GNUNET_HashCode denom_h;
|
||||
const struct TALER_MINT_DenomPublicKey *dk;
|
||||
unsigned int j;
|
||||
struct MAJ_Specification spec[] = {
|
||||
MAJ_spec_fixed_auto ("denom_pub_h",
|
||||
&denom_h),
|
||||
MAJ_spec_fixed_auto ("auditor_sig",
|
||||
&auditor_sig),
|
||||
MAJ_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
MAJ_parse_json (key,
|
||||
spec))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
continue;
|
||||
}
|
||||
dk = NULL;
|
||||
for (j=0;j<key_data->num_denom_keys;j++)
|
||||
{
|
||||
if (0 == memcmp (&denom_h,
|
||||
&key_data->denom_keys[j].h_key,
|
||||
sizeof (struct GNUNET_HashCode)))
|
||||
{
|
||||
dk = &key_data->denom_keys[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (NULL == dk)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
continue;
|
||||
}
|
||||
kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
|
||||
kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
|
||||
kv.expire_spend = GNUNET_TIME_absolute_hton (dk->deposit_valid_until);
|
||||
kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
|
||||
TALER_amount_hton (&kv.value,
|
||||
&dk->value);
|
||||
TALER_amount_hton (&kv.fee_withdraw,
|
||||
&dk->fee_withdraw);
|
||||
TALER_amount_hton (&kv.fee_deposit,
|
||||
&dk->fee_deposit);
|
||||
TALER_amount_hton (&kv.fee_refresh,
|
||||
&dk->fee_refresh);
|
||||
kv.denom_hash = dk->h_key;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_MINT_KEYS,
|
||||
&kv.purpose,
|
||||
&auditor_sig.eddsa_sig,
|
||||
&auditor->auditor_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
continue;
|
||||
}
|
||||
auditor->denom_keys[off] = dk;
|
||||
off++;
|
||||
}
|
||||
auditor->num_denom_keys = off;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the JSON in @a resp_obj from the /keys response and store the data
|
||||
* in the @a key_data.
|
||||
@ -394,8 +506,8 @@ decode_keys_json (json_t *resp_obj,
|
||||
EXITIF (0 == (key_data->num_sign_keys =
|
||||
json_array_size (sign_keys_array)));
|
||||
key_data->sign_keys
|
||||
= GNUNET_malloc (sizeof (struct TALER_MINT_SigningPublicKey)
|
||||
* key_data->num_sign_keys);
|
||||
= GNUNET_new_array (key_data->num_sign_keys,
|
||||
struct TALER_MINT_SigningPublicKey);
|
||||
index = 0;
|
||||
json_array_foreach (sign_keys_array, index, sign_key_obj) {
|
||||
EXITIF (GNUNET_SYSERR ==
|
||||
@ -415,8 +527,8 @@ decode_keys_json (json_t *resp_obj,
|
||||
json_object_get (resp_obj, "denoms")));
|
||||
EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
|
||||
EXITIF (0 == (key_data->num_denom_keys = json_array_size (denom_keys_array)));
|
||||
key_data->denom_keys = GNUNET_malloc (sizeof (struct TALER_MINT_DenomPublicKey)
|
||||
* key_data->num_denom_keys);
|
||||
key_data->denom_keys = GNUNET_new_array (key_data->num_denom_keys,
|
||||
struct TALER_MINT_DenomPublicKey);
|
||||
index = 0;
|
||||
json_array_foreach (denom_keys_array, index, denom_key_obj) {
|
||||
EXITIF (GNUNET_SYSERR ==
|
||||
@ -427,7 +539,30 @@ decode_keys_json (json_t *resp_obj,
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: parse the auditor keys (#3847) */
|
||||
/* parse the auditor information */
|
||||
{
|
||||
json_t *auditors_array;
|
||||
json_t *auditor_info;
|
||||
unsigned int len;
|
||||
unsigned int index;
|
||||
|
||||
EXITIF (NULL == (auditors_array =
|
||||
json_object_get (resp_obj, "auditors")));
|
||||
EXITIF (JSON_ARRAY != json_typeof (auditors_array));
|
||||
len = json_array_size (auditors_array);
|
||||
if (0 != len)
|
||||
{
|
||||
key_data->auditors = GNUNET_new_array (len,
|
||||
struct TALER_MINT_AuditorInformation);
|
||||
index = 0;
|
||||
json_array_foreach (auditors_array, index, auditor_info) {
|
||||
EXITIF (GNUNET_SYSERR ==
|
||||
parse_json_auditor (&key_data->auditors[index],
|
||||
auditor_info,
|
||||
key_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate signature... */
|
||||
ks.purpose.size = htonl (sizeof (ks));
|
||||
@ -551,7 +686,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h)
|
||||
* Obtain the URL to use for an API request.
|
||||
*
|
||||
* @param h the mint handle to query
|
||||
* @param path Taler API path (i.e. "/withdraw/sign")
|
||||
* @param path Taler API path (i.e. "/reserve/withdraw")
|
||||
* @return the full URI to use with cURL
|
||||
*/
|
||||
char *
|
||||
@ -708,6 +843,28 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the denomination key details from the mint.
|
||||
*
|
||||
* @param keys the mint's key set
|
||||
* @param hc hash of the public key of the denomination to lookup
|
||||
* @return details about the given denomination key
|
||||
*/
|
||||
const struct TALER_MINT_DenomPublicKey *
|
||||
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
|
||||
const struct GNUNET_HashCode *hc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;i<keys->num_denom_keys;i++)
|
||||
if (0 == memcmp (hc,
|
||||
&keys->denom_keys[i].h_key,
|
||||
sizeof (struct GNUNET_HashCode)))
|
||||
return &keys->denom_keys[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the keys from the mint.
|
||||
*
|
||||
|
@ -48,7 +48,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h);
|
||||
* Obtain the URL to use for an API request.
|
||||
*
|
||||
* @param h the mint handle to query
|
||||
* @param path Taler API path (i.e. "/withdraw/sign")
|
||||
* @param path Taler API path (i.e. "/reserve/withdraw")
|
||||
* @return the full URI to use with cURL
|
||||
*/
|
||||
char *
|
||||
|
@ -15,8 +15,8 @@
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file mint-lib/mint_api_withdraw.c
|
||||
* @brief Implementation of the /withdraw requests of the mint's HTTP API
|
||||
* @file mint-lib/mint_api_reserve.c
|
||||
* @brief Implementation of the /reserve requests of the mint's HTTP API
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
@ -31,12 +31,12 @@
|
||||
#include "taler_signatures.h"
|
||||
|
||||
|
||||
/* ********************** /withdraw/status ********************** */
|
||||
/* ********************** /reserve/status ********************** */
|
||||
|
||||
/**
|
||||
* @brief A Withdraw Status Handle
|
||||
*/
|
||||
struct TALER_MINT_WithdrawStatusHandle
|
||||
struct TALER_MINT_ReserveStatusHandle
|
||||
{
|
||||
|
||||
/**
|
||||
@ -57,7 +57,7 @@ struct TALER_MINT_WithdrawStatusHandle
|
||||
/**
|
||||
* Function to call with the result.
|
||||
*/
|
||||
TALER_MINT_WithdrawStatusResultCallback cb;
|
||||
TALER_MINT_ReserveStatusResultCallback cb;
|
||||
|
||||
/**
|
||||
* Public key of the reserve we are querying.
|
||||
@ -264,16 +264,16 @@ parse_reserve_history (json_t *history,
|
||||
|
||||
/**
|
||||
* Function called when we're done processing the
|
||||
* HTTP /withdraw/status request.
|
||||
* HTTP /reserve/status request.
|
||||
*
|
||||
* @param cls the `struct TALER_MINT_WithdrawStatusHandle`
|
||||
* @param cls the `struct TALER_MINT_ReserveStatusHandle`
|
||||
* @param eh curl handle of the request that finished
|
||||
*/
|
||||
static void
|
||||
handle_withdraw_status_finished (void *cls,
|
||||
CURL *eh)
|
||||
handle_reserve_status_finished (void *cls,
|
||||
CURL *eh)
|
||||
{
|
||||
struct TALER_MINT_WithdrawStatusHandle *wsh = cls;
|
||||
struct TALER_MINT_ReserveStatusHandle *wsh = cls;
|
||||
long response_code;
|
||||
json_t *json;
|
||||
|
||||
@ -376,7 +376,7 @@ handle_withdraw_status_finished (void *cls,
|
||||
NULL,
|
||||
0, NULL);
|
||||
json_decref (json);
|
||||
TALER_MINT_withdraw_status_cancel (wsh);
|
||||
TALER_MINT_reserve_status_cancel (wsh);
|
||||
}
|
||||
|
||||
|
||||
@ -396,13 +396,13 @@ handle_withdraw_status_finished (void *cls,
|
||||
* @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)
|
||||
struct TALER_MINT_ReserveStatusHandle *
|
||||
TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
TALER_MINT_ReserveStatusResultCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
struct TALER_MINT_WithdrawStatusHandle *wsh;
|
||||
struct TALER_MINT_ReserveStatusHandle *wsh;
|
||||
struct TALER_MINT_Context *ctx;
|
||||
CURL *eh;
|
||||
char *pub_str;
|
||||
@ -417,10 +417,10 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
|
||||
pub_str = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
|
||||
sizeof (struct TALER_ReservePublicKeyP));
|
||||
GNUNET_asprintf (&arg_str,
|
||||
"/withdraw/status?reserve_pub=%s",
|
||||
"/reserve/status?reserve_pub=%s",
|
||||
pub_str);
|
||||
GNUNET_free (pub_str);
|
||||
wsh = GNUNET_new (struct TALER_MINT_WithdrawStatusHandle);
|
||||
wsh = GNUNET_new (struct TALER_MINT_ReserveStatusHandle);
|
||||
wsh->mint = mint;
|
||||
wsh->cb = cb;
|
||||
wsh->cb_cls = cb_cls;
|
||||
@ -446,7 +446,7 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
|
||||
wsh->job = MAC_job_add (ctx,
|
||||
eh,
|
||||
GNUNET_NO,
|
||||
&handle_withdraw_status_finished,
|
||||
&handle_reserve_status_finished,
|
||||
wsh);
|
||||
return wsh;
|
||||
}
|
||||
@ -459,7 +459,7 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
|
||||
* @param wsh the withdraw status request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
|
||||
TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh)
|
||||
{
|
||||
if (NULL != wsh->job)
|
||||
{
|
||||
@ -472,12 +472,12 @@ TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
|
||||
}
|
||||
|
||||
|
||||
/* ********************** /withdraw/sign ********************** */
|
||||
/* ********************** /reserve/withdraw ********************** */
|
||||
|
||||
/**
|
||||
* @brief A Withdraw Sign Handle
|
||||
*/
|
||||
struct TALER_MINT_WithdrawSignHandle
|
||||
struct TALER_MINT_ReserveWithdrawHandle
|
||||
{
|
||||
|
||||
/**
|
||||
@ -503,7 +503,7 @@ struct TALER_MINT_WithdrawSignHandle
|
||||
/**
|
||||
* Function to call with the result.
|
||||
*/
|
||||
TALER_MINT_WithdrawSignResultCallback cb;
|
||||
TALER_MINT_ReserveWithdrawResultCallback cb;
|
||||
|
||||
/**
|
||||
* Key used to blind the value.
|
||||
@ -539,7 +539,7 @@ struct TALER_MINT_WithdrawSignHandle
|
||||
|
||||
|
||||
/**
|
||||
* We got a 200 OK response for the /withdraw/sign operation.
|
||||
* We got a 200 OK response for the /reserve/withdraw operation.
|
||||
* Extract the coin's signature and return it to the caller.
|
||||
* The signature we get from the mint is for the blinded value.
|
||||
* Thus, we first must unblind it and then should verify its
|
||||
@ -553,7 +553,7 @@ struct TALER_MINT_WithdrawSignHandle
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static int
|
||||
withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
|
||||
reserve_withdraw_ok (struct TALER_MINT_ReserveWithdrawHandle *wsh,
|
||||
json_t *json)
|
||||
{
|
||||
struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
|
||||
@ -598,7 +598,7 @@ withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
|
||||
|
||||
|
||||
/**
|
||||
* We got a 402 PAYMENT REQUIRED response for the /withdraw/sign operation.
|
||||
* We got a 402 PAYMENT REQUIRED response for the /reserve/withdraw operation.
|
||||
* Check the signatures on the withdraw transactions in the provided
|
||||
* history and that the balances add up. We don't do anything directly
|
||||
* with the information, as the JSON will be returned to the application.
|
||||
@ -610,8 +610,8 @@ withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static int
|
||||
withdraw_sign_payment_required (struct TALER_MINT_WithdrawSignHandle *wsh,
|
||||
json_t *json)
|
||||
reserve_withdraw_payment_required (struct TALER_MINT_ReserveWithdrawHandle *wsh,
|
||||
json_t *json)
|
||||
{
|
||||
struct TALER_Amount balance;
|
||||
struct TALER_Amount balance_from_history;
|
||||
@ -690,16 +690,16 @@ withdraw_sign_payment_required (struct TALER_MINT_WithdrawSignHandle *wsh,
|
||||
|
||||
/**
|
||||
* Function called when we're done processing the
|
||||
* HTTP /withdraw/sign request.
|
||||
* HTTP /reserve/withdraw request.
|
||||
*
|
||||
* @param cls the `struct TALER_MINT_WithdrawSignHandle`
|
||||
* @param cls the `struct TALER_MINT_ReserveWithdrawHandle`
|
||||
* @param eh curl handle of the request that finished
|
||||
*/
|
||||
static void
|
||||
handle_withdraw_sign_finished (void *cls,
|
||||
CURL *eh)
|
||||
handle_reserve_withdraw_finished (void *cls,
|
||||
CURL *eh)
|
||||
{
|
||||
struct TALER_MINT_WithdrawSignHandle *wsh = cls;
|
||||
struct TALER_MINT_ReserveWithdrawHandle *wsh = cls;
|
||||
long response_code;
|
||||
json_t *json;
|
||||
|
||||
@ -713,7 +713,7 @@ handle_withdraw_sign_finished (void *cls,
|
||||
break;
|
||||
case MHD_HTTP_OK:
|
||||
if (GNUNET_OK !=
|
||||
withdraw_sign_ok (wsh,
|
||||
reserve_withdraw_ok (wsh,
|
||||
json))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
@ -728,7 +728,7 @@ handle_withdraw_sign_finished (void *cls,
|
||||
/* The mint says that the reserve has insufficient funds;
|
||||
check the signatures in the history... */
|
||||
if (GNUNET_OK !=
|
||||
withdraw_sign_payment_required (wsh,
|
||||
reserve_withdraw_payment_required (wsh,
|
||||
json))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
@ -766,12 +766,12 @@ handle_withdraw_sign_finished (void *cls,
|
||||
NULL,
|
||||
json);
|
||||
json_decref (json);
|
||||
TALER_MINT_withdraw_sign_cancel (wsh);
|
||||
TALER_MINT_reserve_withdraw_cancel (wsh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Withdraw a coin from the mint using a /withdraw/sign request. Note
|
||||
* Withdraw a coin from the mint using a /reserve/withdraw 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
|
||||
@ -790,16 +790,16 @@ handle_withdraw_sign_finished (void *cls,
|
||||
* 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)
|
||||
struct TALER_MINT_ReserveWithdrawHandle *
|
||||
TALER_MINT_reserve_withdraw (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_ReserveWithdrawResultCallback res_cb,
|
||||
void *res_cb_cls)
|
||||
{
|
||||
struct TALER_MINT_WithdrawSignHandle *wsh;
|
||||
struct TALER_MINT_ReserveWithdrawHandle *wsh;
|
||||
struct TALER_WithdrawRequestPS req;
|
||||
struct TALER_ReserveSignatureP reserve_sig;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
@ -810,7 +810,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
|
||||
json_t *withdraw_obj;
|
||||
CURL *eh;
|
||||
|
||||
wsh = GNUNET_new (struct TALER_MINT_WithdrawSignHandle);
|
||||
wsh = GNUNET_new (struct TALER_MINT_ReserveWithdrawHandle);
|
||||
wsh->mint = mint;
|
||||
wsh->cb = res_cb;
|
||||
wsh->cb_cls = res_cb_cls;
|
||||
@ -866,7 +866,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
|
||||
GNUNET_free (coin_ev);
|
||||
|
||||
wsh->blinding_key = blinding_key;
|
||||
wsh->url = MAH_path_to_url (mint, "/withdraw/sign");
|
||||
wsh->url = MAH_path_to_url (mint, "/reserve/withdraw");
|
||||
|
||||
eh = curl_easy_init ();
|
||||
GNUNET_assert (NULL != (wsh->json_enc =
|
||||
@ -897,7 +897,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
|
||||
wsh->job = MAC_job_add (ctx,
|
||||
eh,
|
||||
GNUNET_YES,
|
||||
&handle_withdraw_sign_finished,
|
||||
&handle_reserve_withdraw_finished,
|
||||
wsh);
|
||||
return wsh;
|
||||
}
|
||||
@ -910,7 +910,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
|
||||
* @param sign the withdraw sign request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
|
||||
TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign)
|
||||
{
|
||||
if (NULL != sign->job)
|
||||
{
|
||||
@ -924,4 +924,4 @@ TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
|
||||
}
|
||||
|
||||
|
||||
/* end of mint_api_withdraw.c */
|
||||
/* end of mint_api_reserve.c */
|
619
src/mint-lib/mint_api_wire.c
Normal file
619
src/mint-lib/mint_api_wire.c
Normal file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
|
||||
|
||||
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, If not, see
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file mint-lib/mint_api_wire.c
|
||||
* @brief Implementation of the /wire request of the mint's HTTP API
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <curl/curl.h>
|
||||
#include <jansson.h>
|
||||
#include <microhttpd.h> /* just for HTTP status codes */
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include "taler_mint_service.h"
|
||||
#include "mint_api_common.h"
|
||||
#include "mint_api_json.h"
|
||||
#include "mint_api_context.h"
|
||||
#include "mint_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief A Wire Handle
|
||||
*/
|
||||
struct TALER_MINT_WireHandle
|
||||
{
|
||||
|
||||
/**
|
||||
* The connection to mint this request handle will use
|
||||
*/
|
||||
struct TALER_MINT_Handle *mint;
|
||||
|
||||
/**
|
||||
* The url for this request.
|
||||
*/
|
||||
char *url;
|
||||
|
||||
/**
|
||||
* Handle for the request.
|
||||
*/
|
||||
struct MAC_Job *job;
|
||||
|
||||
/**
|
||||
* Function to call with the result.
|
||||
*/
|
||||
TALER_MINT_WireResultCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @a cb.
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Download buffer
|
||||
*/
|
||||
struct MAC_DownloadBuffer db;
|
||||
|
||||
/**
|
||||
* Set to the "methods" JSON array returned by the
|
||||
* /wire request.
|
||||
*/
|
||||
json_t *methods;
|
||||
|
||||
/**
|
||||
* Current iteration offset in the @e methods array.
|
||||
*/
|
||||
unsigned int methods_off;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Verify that the signature on the "200 OK" response
|
||||
* for /wire/sepa from the mint is valid.
|
||||
*
|
||||
* @param wh wire handle
|
||||
* @param json json reply with the signature
|
||||
* @return #GNUNET_SYSERR if @a json is invalid,
|
||||
* #GNUNET_NO if the method is unknown,
|
||||
* #GNUNET_OK if the json is valid
|
||||
*/
|
||||
static int
|
||||
verify_wire_sepa_signature_ok (const struct TALER_MINT_WireHandle *wh,
|
||||
json_t *json)
|
||||
{
|
||||
struct TALER_MasterSignatureP mint_sig;
|
||||
struct TALER_MasterWireSepaDetailsPS mp;
|
||||
const char *receiver_name;
|
||||
const char *iban;
|
||||
const char *bic;
|
||||
const struct TALER_MINT_Keys *key_state;
|
||||
struct GNUNET_HashContext *hc;
|
||||
struct MAJ_Specification spec[] = {
|
||||
MAJ_spec_fixed_auto ("sig", &mint_sig),
|
||||
MAJ_spec_string ("receiver_name", &receiver_name),
|
||||
MAJ_spec_string ("iban", &iban),
|
||||
MAJ_spec_string ("bic", &bic),
|
||||
MAJ_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
MAJ_parse_json (json,
|
||||
spec))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
key_state = TALER_MINT_get_keys (wh->mint);
|
||||
mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
|
||||
mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS));
|
||||
hc = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
receiver_name,
|
||||
strlen (receiver_name) + 1);
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
iban,
|
||||
strlen (iban) + 1);
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
bic,
|
||||
strlen (bic) + 1);
|
||||
GNUNET_CRYPTO_hash_context_finish (hc,
|
||||
&mp.h_sepa_details);
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
|
||||
&mp.purpose,
|
||||
&mint_sig.eddsa_signature,
|
||||
&key_state->master_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
MAJ_parse_free (spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
MAJ_parse_free (spec);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that the signature on the "200 OK" response
|
||||
* for /wire/METHOD from the mint is valid.
|
||||
*
|
||||
* @param wh wire handle with key material
|
||||
* @param method method to verify the reply for
|
||||
* @param json json reply with the signature
|
||||
* @return #GNUNET_SYSERR if @a json is invalid,
|
||||
* #GNUNET_NO if the method is unknown,
|
||||
* #GNUNET_OK if the json is valid
|
||||
*/
|
||||
static int
|
||||
verify_wire_method_signature_ok (const struct TALER_MINT_WireHandle *wh,
|
||||
const char *method,
|
||||
json_t *json)
|
||||
{
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Name fo the method.
|
||||
*/
|
||||
const char *method;
|
||||
|
||||
/**
|
||||
* Handler to invoke to verify signature.
|
||||
*
|
||||
* @param wh wire handle with key material
|
||||
* @param json json reply with signature to verify
|
||||
*/
|
||||
int (*handler)(const struct TALER_MINT_WireHandle *wh,
|
||||
json_t *json);
|
||||
} handlers[] = {
|
||||
{ "sepa", &verify_wire_sepa_signature_ok },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;NULL != handlers[i].method; i++)
|
||||
if (0 == strcasecmp (handlers[i].method,
|
||||
method))
|
||||
return handlers[i].handler (wh,
|
||||
json);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Wire transfer method `%s' not supported\n",
|
||||
method);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform the next /wire/method request or signal
|
||||
* the end of the iteration.
|
||||
*
|
||||
* @param wh the wire handle
|
||||
* @return a handle for this request
|
||||
*/
|
||||
static void
|
||||
request_wire_method (struct TALER_MINT_WireHandle *wh);
|
||||
|
||||
|
||||
/**
|
||||
* Function called when we're done processing the
|
||||
* HTTP /wire/METHOD request.
|
||||
*
|
||||
* @param cls the `struct TALER_MINT_WireHandle`
|
||||
* @param eh the curl request handle
|
||||
*/
|
||||
static void
|
||||
handle_wire_method_finished (void *cls,
|
||||
CURL *eh)
|
||||
{
|
||||
struct TALER_MINT_WireHandle *wh = cls;
|
||||
long response_code;
|
||||
json_t *json;
|
||||
|
||||
wh->job = NULL;
|
||||
json = MAC_download_get_result (&wh->db,
|
||||
eh,
|
||||
&response_code);
|
||||
switch (response_code)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case MHD_HTTP_OK:
|
||||
{
|
||||
const char *method;
|
||||
|
||||
method = json_string_value (json_array_get (wh->methods,
|
||||
wh->methods_off - 1));
|
||||
if (GNUNET_OK !=
|
||||
verify_wire_method_signature_ok (wh,
|
||||
method,
|
||||
json))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
response_code = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MHD_HTTP_FOUND:
|
||||
/* /wire/test returns a 302 redirect, we should just give
|
||||
this information back to the callback below */
|
||||
break;
|
||||
case MHD_HTTP_BAD_REQUEST:
|
||||
/* This should never happen, either us or the mint is buggy
|
||||
(or API version conflict); just pass JSON reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_NOT_FOUND:
|
||||
/* Nothing really to verify, this should never
|
||||
happen, we should pass the JSON reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||
/* Server had an internal issue; we should retry, but this API
|
||||
leaves this to the application */
|
||||
break;
|
||||
default:
|
||||
/* unexpected response code */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u\n",
|
||||
response_code);
|
||||
GNUNET_break (0);
|
||||
response_code = 0;
|
||||
break;
|
||||
}
|
||||
if (0 == response_code)
|
||||
{
|
||||
/* signal end of iteration */
|
||||
wh->cb (wh->cb_cls,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
json_decref (json);
|
||||
TALER_MINT_wire_cancel (wh);
|
||||
return;
|
||||
}
|
||||
/* pass on successful reply */
|
||||
wh->cb (wh->cb_cls,
|
||||
response_code,
|
||||
json_string_value (json_array_get (wh->methods,
|
||||
wh->methods_off-1)),
|
||||
json);
|
||||
/* trigger request for the next /wire/method */
|
||||
request_wire_method (wh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform the next /wire/method request or signal
|
||||
* the end of the iteration.
|
||||
*
|
||||
* @param wh the wire handle
|
||||
* @return a handle for this request
|
||||
*/
|
||||
static void
|
||||
request_wire_method (struct TALER_MINT_WireHandle *wh)
|
||||
{
|
||||
struct TALER_MINT_Context *ctx;
|
||||
CURL *eh;
|
||||
char *path;
|
||||
|
||||
if (json_array_size (wh->methods) <= wh->methods_off)
|
||||
{
|
||||
/* we are done, signal end of iteration */
|
||||
wh->cb (wh->cb_cls,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
TALER_MINT_wire_cancel (wh);
|
||||
return;
|
||||
}
|
||||
GNUNET_free_non_null (wh->db.buf);
|
||||
wh->db.buf = NULL;
|
||||
wh->db.buf_size = 0;
|
||||
wh->db.eno = 0;
|
||||
GNUNET_free_non_null (wh->url);
|
||||
GNUNET_asprintf (&path,
|
||||
"/wire/%s",
|
||||
json_string_value (json_array_get (wh->methods,
|
||||
wh->methods_off++)));
|
||||
wh->url = MAH_path_to_url (wh->mint,
|
||||
path);
|
||||
GNUNET_free (path);
|
||||
|
||||
eh = curl_easy_init ();
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_URL,
|
||||
wh->url));
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_WRITEFUNCTION,
|
||||
&MAC_download_cb));
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_WRITEDATA,
|
||||
&wh->db));
|
||||
/* The default is 'disabled', but let's be sure */
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_FOLLOWLOCATION,
|
||||
(long) 0));
|
||||
ctx = MAH_handle_to_context (wh->mint);
|
||||
wh->job = MAC_job_add (ctx,
|
||||
eh,
|
||||
GNUNET_YES,
|
||||
&handle_wire_method_finished,
|
||||
wh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that the signature on the "200 OK" response
|
||||
* for /wire from the mint is valid.
|
||||
*
|
||||
* @param wh wire handle
|
||||
* @param json json reply with the signature
|
||||
* @return NULL if @a json is invalid, otherwise the
|
||||
* "methods" array (with an RC of 1)
|
||||
*/
|
||||
static json_t *
|
||||
verify_wire_signature_ok (const struct TALER_MINT_WireHandle *wh,
|
||||
json_t *json)
|
||||
{
|
||||
struct TALER_MintSignatureP mint_sig;
|
||||
struct TALER_MintPublicKeyP mint_pub;
|
||||
struct TALER_MintWireSupportMethodsPS mp;
|
||||
json_t *methods;
|
||||
const struct TALER_MINT_Keys *key_state;
|
||||
struct GNUNET_HashContext *hc;
|
||||
struct MAJ_Specification spec[] = {
|
||||
MAJ_spec_fixed_auto ("sig", &mint_sig),
|
||||
MAJ_spec_fixed_auto ("pub", &mint_pub),
|
||||
MAJ_spec_json ("methods", &methods),
|
||||
MAJ_spec_end
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
MAJ_parse_json (json,
|
||||
spec))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return NULL;
|
||||
}
|
||||
if (! json_is_array (methods))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
MAJ_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key_state = TALER_MINT_get_keys (wh->mint);
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINT_test_signing_key (key_state,
|
||||
&mint_pub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return NULL;
|
||||
}
|
||||
hc = GNUNET_CRYPTO_hash_context_start ();
|
||||
for (i=0;i<json_array_size (methods);i++)
|
||||
{
|
||||
const json_t *element = json_array_get (methods, i);
|
||||
const char *method;
|
||||
|
||||
if (! json_is_string (element))
|
||||
{
|
||||
GNUNET_CRYPTO_hash_context_abort (hc);
|
||||
GNUNET_break_op (0);
|
||||
MAJ_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
method = json_string_value (element);
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
method,
|
||||
strlen (method) + 1);
|
||||
}
|
||||
mp.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES);
|
||||
mp.purpose.size = htonl (sizeof (struct TALER_MintWireSupportMethodsPS));
|
||||
GNUNET_CRYPTO_hash_context_finish (hc,
|
||||
&mp.h_wire_types);
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_WIRE_TYPES,
|
||||
&mp.purpose,
|
||||
&mint_sig.eddsa_signature,
|
||||
&mint_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
MAJ_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called when we're done processing the
|
||||
* HTTP /wire request.
|
||||
*
|
||||
* @param cls the `struct TALER_MINT_WireHandle`
|
||||
* @param eh the curl request handle
|
||||
*/
|
||||
static void
|
||||
handle_wire_finished (void *cls,
|
||||
CURL *eh)
|
||||
{
|
||||
struct TALER_MINT_WireHandle *wh = cls;
|
||||
long response_code;
|
||||
json_t *json;
|
||||
|
||||
wh->job = NULL;
|
||||
json = MAC_download_get_result (&wh->db,
|
||||
eh,
|
||||
&response_code);
|
||||
switch (response_code)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case MHD_HTTP_OK:
|
||||
{
|
||||
json_t *methods;
|
||||
|
||||
if (NULL ==
|
||||
(methods = verify_wire_signature_ok (wh,
|
||||
json)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
response_code = 0;
|
||||
break;
|
||||
}
|
||||
wh->methods = methods;
|
||||
request_wire_method (wh);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MHD_HTTP_BAD_REQUEST:
|
||||
/* This should never happen, either us or the mint is buggy
|
||||
(or API version conflict); just pass JSON reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_NOT_FOUND:
|
||||
/* Nothing really to verify, this should never
|
||||
happen, we should pass the JSON reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||
/* Server had an internal issue; we should retry, but this API
|
||||
leaves this to the application */
|
||||
break;
|
||||
default:
|
||||
/* unexpected response code */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u\n",
|
||||
response_code);
|
||||
GNUNET_break (0);
|
||||
response_code = 0;
|
||||
break;
|
||||
}
|
||||
if (0 != response_code)
|
||||
{
|
||||
/* pass on successful reply */
|
||||
wh->cb (wh->cb_cls,
|
||||
response_code,
|
||||
NULL,
|
||||
json);
|
||||
}
|
||||
/* signal end of iteration */
|
||||
wh->cb (wh->cb_cls,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NULL != json)
|
||||
json_decref (json);
|
||||
TALER_MINT_wire_cancel (wh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain information about a mint's wire instructions.
|
||||
* A mint may provide wire instructions for creating
|
||||
* a reserve. The wire instructions also indicate
|
||||
* which wire formats merchants may use with the mint.
|
||||
* This API is typically used by a wallet for wiring
|
||||
* funds, and possibly by a merchant to determine
|
||||
* supported wire formats.
|
||||
*
|
||||
* Note that while we return the (main) response verbatim 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). 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 wire_cb the callback to call when a reply for this request is available
|
||||
* @param wire_cb_cls closure for the above callback
|
||||
* @return a handle for this request
|
||||
*/
|
||||
struct TALER_MINT_WireHandle *
|
||||
TALER_MINT_wire (struct TALER_MINT_Handle *mint,
|
||||
TALER_MINT_WireResultCallback wire_cb,
|
||||
void *wire_cb_cls)
|
||||
{
|
||||
struct TALER_MINT_WireHandle *wh;
|
||||
struct TALER_MINT_Context *ctx;
|
||||
CURL *eh;
|
||||
|
||||
if (GNUNET_YES !=
|
||||
MAH_handle_is_ready (mint))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
wh = GNUNET_new (struct TALER_MINT_WireHandle);
|
||||
wh->mint = mint;
|
||||
wh->cb = wire_cb;
|
||||
wh->cb_cls = wire_cb_cls;
|
||||
wh->url = MAH_path_to_url (mint, "/wire");
|
||||
|
||||
eh = curl_easy_init ();
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_URL,
|
||||
wh->url));
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_WRITEFUNCTION,
|
||||
&MAC_download_cb));
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_WRITEDATA,
|
||||
&wh->db));
|
||||
ctx = MAH_handle_to_context (mint);
|
||||
wh->job = MAC_job_add (ctx,
|
||||
eh,
|
||||
GNUNET_YES,
|
||||
&handle_wire_finished,
|
||||
wh);
|
||||
return wh;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cancel a wire information request. This function cannot be used
|
||||
* on a request handle if a response is already served for it.
|
||||
*
|
||||
* @param wire the wire information request handle
|
||||
*/
|
||||
void
|
||||
TALER_MINT_wire_cancel (struct TALER_MINT_WireHandle *wire)
|
||||
{
|
||||
if (NULL != wire->job)
|
||||
{
|
||||
MAC_job_cancel (wire->job);
|
||||
wire->job = NULL;
|
||||
}
|
||||
if (NULL != wire->methods)
|
||||
{
|
||||
json_decref (wire->methods);
|
||||
wire->methods = NULL;
|
||||
}
|
||||
GNUNET_free_non_null (wire->db.buf);
|
||||
GNUNET_free (wire->url);
|
||||
GNUNET_free (wire);
|
||||
}
|
||||
|
||||
|
||||
/* end of mint_api_wire.c */
|
@ -2,9 +2,10 @@
|
||||
# Currency supported by the mint (can only be one)
|
||||
CURRENCY = EUR
|
||||
|
||||
# Wire format supproted by the mint
|
||||
# TEST is used for testing... (what a shock)
|
||||
WIREFORMAT = TEST
|
||||
# Wire format supported by the mint
|
||||
# We use 'test' for testing of the actual
|
||||
# coin operations, and 'sepa' to test SEPA-specific routines.
|
||||
WIREFORMAT = test sepa
|
||||
|
||||
# HTTP port the mint listens to
|
||||
PORT = 8081
|
||||
@ -15,9 +16,15 @@ MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
|
||||
# This is a testcase, use transient DB actions
|
||||
TESTRUN = YES
|
||||
# Is this is a testcase, use transient DB actions?
|
||||
TESTRUN = NO
|
||||
|
||||
[mintdb-postgres]
|
||||
|
||||
DB_CONN_STR = "postgres:///talercheck"
|
||||
|
||||
[mint-wire-sepa]
|
||||
SEPA_RESPONSE_FILE = "test-mint-home/sepa.json"
|
||||
|
||||
[mint-wire-test]
|
||||
REDIRECT_URL = "http://www.taler.net/"
|
||||
|
6
src/mint-lib/test-mint-home/sepa.json
Normal file
6
src/mint-lib/test-mint-home/sepa.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"receiver_name": "Max Mustermann",
|
||||
"iban": "DE89370400440532013000",
|
||||
"bic": "COBADEFF370",
|
||||
"sig": "8M5YJXM68PRAXKH76HYEBCJW657B23JA0RFGNDMZK2379YZMT626H1BN89KC0M1KJBWGYEN5Z763Q0Y7MCTZQ6BPPT7D9KFCTW60C10"
|
||||
}
|
@ -26,6 +26,15 @@
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <microhttpd.h>
|
||||
|
||||
/**
|
||||
* Is the configuration file is set to include wire format 'test'?
|
||||
*/
|
||||
#define WIRE_TEST 1
|
||||
|
||||
/**
|
||||
* Is the configuration file is set to include wire format 'sepa'?
|
||||
*/
|
||||
#define WIRE_SEPA 1
|
||||
|
||||
/**
|
||||
* Main execution context for the main loop.
|
||||
@ -97,7 +106,12 @@ enum OpCode
|
||||
* Verify mint's /refresh/link by linking original private key to
|
||||
* results from #OC_REFRESH_REVEAL step.
|
||||
*/
|
||||
OC_REFRESH_LINK
|
||||
OC_REFRESH_LINK,
|
||||
|
||||
/**
|
||||
* Verify the mint's /wire-method.
|
||||
*/
|
||||
OC_WIRE
|
||||
|
||||
};
|
||||
|
||||
@ -116,7 +130,7 @@ struct MeltDetails
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Reference to withdraw_sign operations for coin to
|
||||
* Reference to reserve_withdraw operations for coin to
|
||||
* be used for the /refresh/melt operation.
|
||||
*/
|
||||
const char *coin_ref;
|
||||
@ -228,14 +242,14 @@ struct Command
|
||||
/**
|
||||
* Set to the API's handle during the operation.
|
||||
*/
|
||||
struct TALER_MINT_WithdrawStatusHandle *wsh;
|
||||
struct TALER_MINT_ReserveStatusHandle *wsh;
|
||||
|
||||
/**
|
||||
* Expected reserve balance.
|
||||
*/
|
||||
const char *expected_balance;
|
||||
|
||||
} withdraw_status;
|
||||
} reserve_status;
|
||||
|
||||
/**
|
||||
* Information for a #OC_WITHDRAW_SIGN command.
|
||||
@ -281,9 +295,9 @@ struct Command
|
||||
/**
|
||||
* Withdraw handle (while operation is running).
|
||||
*/
|
||||
struct TALER_MINT_WithdrawSignHandle *wsh;
|
||||
struct TALER_MINT_ReserveWithdrawHandle *wsh;
|
||||
|
||||
} withdraw_sign;
|
||||
} reserve_withdraw;
|
||||
|
||||
/**
|
||||
* Information for a #OC_DEPOSIT command.
|
||||
@ -297,7 +311,7 @@ struct Command
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Reference to a withdraw_sign operation for a coin to
|
||||
* Reference to a reserve_withdraw operation for a coin to
|
||||
* be used for the /deposit operation.
|
||||
*/
|
||||
const char *coin_ref;
|
||||
@ -439,6 +453,23 @@ struct Command
|
||||
|
||||
} refresh_link;
|
||||
|
||||
/**
|
||||
* Information for the /wire command.
|
||||
*/
|
||||
struct {
|
||||
|
||||
/**
|
||||
* Handle to the wire request.
|
||||
*/
|
||||
struct TALER_MINT_WireHandle *wh;
|
||||
|
||||
/**
|
||||
* Format we expect to see, others will be *ignored*.
|
||||
*/
|
||||
const char *format;
|
||||
|
||||
} wire;
|
||||
|
||||
} details;
|
||||
|
||||
};
|
||||
@ -622,8 +653,8 @@ compare_admin_add_incoming_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
* @return #GNUNET_OK if they match, #GNUNET_SYSERR if not
|
||||
*/
|
||||
static int
|
||||
compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
const struct Command *cmd)
|
||||
compare_reserve_withdraw_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
const struct Command *cmd)
|
||||
{
|
||||
struct TALER_Amount amount;
|
||||
struct TALER_Amount amount_with_fee;
|
||||
@ -634,12 +665,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (cmd->details.withdraw_sign.amount,
|
||||
TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
|
||||
&amount));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_add (&amount_with_fee,
|
||||
&amount,
|
||||
&cmd->details.withdraw_sign.pk->fee_withdraw));
|
||||
&cmd->details.reserve_withdraw.pk->fee_withdraw));
|
||||
if (0 != TALER_amount_cmp (&amount_with_fee,
|
||||
&h->amount))
|
||||
{
|
||||
@ -651,7 +682,7 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the result of a /withdraw/status request.
|
||||
* Function called with the result of a /reserve/status request.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
@ -662,12 +693,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
|
||||
* @param history detailed transaction history, NULL on error
|
||||
*/
|
||||
static void
|
||||
withdraw_status_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
const struct TALER_MINT_ReserveHistory *history)
|
||||
reserve_status_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
const struct TALER_MINT_ReserveHistory *history)
|
||||
{
|
||||
struct InterpreterState *is = cls;
|
||||
struct Command *cmd = &is->commands[is->ip];
|
||||
@ -676,7 +707,7 @@ withdraw_status_cb (void *cls,
|
||||
unsigned int j;
|
||||
struct TALER_Amount amount;
|
||||
|
||||
cmd->details.withdraw_status.wsh = NULL;
|
||||
cmd->details.reserve_status.wsh = NULL;
|
||||
if (cmd->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -700,10 +731,10 @@ withdraw_status_cb (void *cls,
|
||||
{
|
||||
case OC_ADMIN_ADD_INCOMING:
|
||||
if ( ( (NULL != rel->label) &&
|
||||
(0 == strcmp (cmd->details.withdraw_status.reserve_reference,
|
||||
(0 == strcmp (cmd->details.reserve_status.reserve_reference,
|
||||
rel->label) ) ) ||
|
||||
( (NULL != rel->details.admin_add_incoming.reserve_reference) &&
|
||||
(0 == strcmp (cmd->details.withdraw_status.reserve_reference,
|
||||
(0 == strcmp (cmd->details.reserve_status.reserve_reference,
|
||||
rel->details.admin_add_incoming.reserve_reference) ) ) )
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
@ -718,11 +749,11 @@ withdraw_status_cb (void *cls,
|
||||
}
|
||||
break;
|
||||
case OC_WITHDRAW_SIGN:
|
||||
if (0 == strcmp (cmd->details.withdraw_status.reserve_reference,
|
||||
rel->details.withdraw_sign.reserve_reference))
|
||||
if (0 == strcmp (cmd->details.reserve_status.reserve_reference,
|
||||
rel->details.reserve_withdraw.reserve_reference))
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
compare_withdraw_sign_history (&history[j],
|
||||
compare_reserve_withdraw_history (&history[j],
|
||||
rel))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -743,10 +774,10 @@ withdraw_status_cb (void *cls,
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
if (NULL != cmd->details.withdraw_status.expected_balance)
|
||||
if (NULL != cmd->details.reserve_status.expected_balance)
|
||||
{
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (cmd->details.withdraw_status.expected_balance,
|
||||
TALER_string_to_amount (cmd->details.reserve_status.expected_balance,
|
||||
&amount));
|
||||
if (0 != TALER_amount_cmp (&amount,
|
||||
balance))
|
||||
@ -769,7 +800,7 @@ withdraw_status_cb (void *cls,
|
||||
|
||||
|
||||
/**
|
||||
* Function called upon completion of our /withdraw/sign request.
|
||||
* Function called upon completion of our /reserve/withdraw request.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
@ -778,15 +809,15 @@ withdraw_status_cb (void *cls,
|
||||
* @param full_response full response from the mint (for logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
withdraw_sign_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
const struct TALER_DenominationSignature *sig,
|
||||
json_t *full_response)
|
||||
reserve_withdraw_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
const struct TALER_DenominationSignature *sig,
|
||||
json_t *full_response)
|
||||
{
|
||||
struct InterpreterState *is = cls;
|
||||
struct Command *cmd = &is->commands[is->ip];
|
||||
|
||||
cmd->details.withdraw_sign.wsh = NULL;
|
||||
cmd->details.reserve_withdraw.wsh = NULL;
|
||||
if (cmd->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -807,7 +838,7 @@ withdraw_sign_cb (void *cls,
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
cmd->details.withdraw_sign.sig.rsa_signature
|
||||
cmd->details.reserve_withdraw.sig.rsa_signature
|
||||
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
|
||||
break;
|
||||
case MHD_HTTP_PAYMENT_REQUIRED:
|
||||
@ -1011,10 +1042,6 @@ link_cb (void *cls,
|
||||
return;
|
||||
}
|
||||
/* check that the coins match */
|
||||
fprintf (stderr,
|
||||
"Got %u coins\n",
|
||||
num_coins);
|
||||
|
||||
for (i=0;i<num_coins;i++)
|
||||
for (j=i+1;j<num_coins;j++)
|
||||
if (0 == memcmp (&coin_privs[i],
|
||||
@ -1027,7 +1054,7 @@ link_cb (void *cls,
|
||||
for (j=0;j<num_coins;j++)
|
||||
{
|
||||
const struct FreshCoin *fc;
|
||||
|
||||
|
||||
fc = &ref->details.refresh_reveal.fresh_coins[j];
|
||||
if ( (0 == memcmp (&coin_privs[i],
|
||||
&fc->coin_priv,
|
||||
@ -1048,8 +1075,8 @@ link_cb (void *cls,
|
||||
found,
|
||||
num_coins);
|
||||
GNUNET_break (0);
|
||||
fail (is);
|
||||
return;
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1115,6 +1142,83 @@ find_pk (const struct TALER_MINT_Keys *keys,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks called with the result(s) of a
|
||||
* wire format inquiry request to the mint.
|
||||
*
|
||||
* The callback is invoked multiple times, once for each supported @a
|
||||
* method. Finally, it is invoked one more time with cls/0/NULL/NULL
|
||||
* to indicate the end of the iteration. If any request fails to
|
||||
* generate a valid response from the mint, @a http_status will also
|
||||
* be zero and the iteration will also end. Thus, the iteration
|
||||
* always ends with a final call with an @a http_status of 0. If the
|
||||
* @a http_status is already 0 on the first call, then the response to
|
||||
* the /wire request was invalid. Later, clients can tell the
|
||||
* difference between @a http_status of 0 indicating a failed
|
||||
* /wire/method request and a regular end of the iteration by @a
|
||||
* method being non-NULL. If the mint simply correctly asserts that
|
||||
* it does not support any methods, @a method will be NULL but the @a
|
||||
* http_status will be #MHD_HTTP_OK for the first call (followed by a
|
||||
* cls/0/NULL/NULL call to signal the end of the iteration).
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
|
||||
* 0 if the mint's reply is bogus (fails to follow the protocol)
|
||||
* @param method wire format method supported, i.e. "test" or "sepa", or NULL
|
||||
* if already the /wire request failed.
|
||||
* @param obj the received JSON reply, if successful this should be the wire
|
||||
* format details as provided by /wire/METHOD/, or NULL if the
|
||||
* reply was not in JSON format (in this case, the client might
|
||||
* want to do an HTTP request to /wire/METHOD/ with a browser to
|
||||
* provide more information to the user about the @a method).
|
||||
*/
|
||||
static void
|
||||
wire_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
const char *method,
|
||||
json_t *obj)
|
||||
{
|
||||
struct InterpreterState *is = cls;
|
||||
struct Command *cmd = &is->commands[is->ip];
|
||||
|
||||
if (0 == http_status)
|
||||
{
|
||||
/* 0 always signals the end of the iteration */
|
||||
cmd->details.wire.wh = NULL;
|
||||
}
|
||||
else if ( (NULL != method) &&
|
||||
(0 != strcasecmp (method,
|
||||
cmd->details.wire.format)) )
|
||||
{
|
||||
/* not the method we care about, skip */
|
||||
return;
|
||||
}
|
||||
if (cmd->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s/%s\n",
|
||||
http_status,
|
||||
cmd->label,
|
||||
method);
|
||||
json_dumpf (obj, stderr, 0);
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
if (0 == http_status)
|
||||
{
|
||||
/* end of iteration, move to next command */
|
||||
is->ip++;
|
||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||
is);
|
||||
return;
|
||||
}
|
||||
/* For now, we only support to be called only once
|
||||
with a "positive" result; so we switch to an
|
||||
expected value of 0 for the 2nd iteration */
|
||||
cmd->expected_response_code = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the main interpreter loop that performs mint operations.
|
||||
*
|
||||
@ -1212,44 +1316,44 @@ interpreter_run (void *cls,
|
||||
return;
|
||||
case OC_WITHDRAW_STATUS:
|
||||
GNUNET_assert (NULL !=
|
||||
cmd->details.withdraw_status.reserve_reference);
|
||||
cmd->details.reserve_status.reserve_reference);
|
||||
ref = find_command (is,
|
||||
cmd->details.withdraw_status.reserve_reference);
|
||||
cmd->details.reserve_status.reserve_reference);
|
||||
GNUNET_assert (NULL != ref);
|
||||
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ref->details.admin_add_incoming.reserve_priv.eddsa_priv,
|
||||
&reserve_pub.eddsa_pub);
|
||||
cmd->details.withdraw_status.wsh
|
||||
= TALER_MINT_withdraw_status (mint,
|
||||
&reserve_pub,
|
||||
&withdraw_status_cb,
|
||||
is);
|
||||
cmd->details.reserve_status.wsh
|
||||
= TALER_MINT_reserve_status (mint,
|
||||
&reserve_pub,
|
||||
&reserve_status_cb,
|
||||
is);
|
||||
trigger_context_task ();
|
||||
return;
|
||||
case OC_WITHDRAW_SIGN:
|
||||
GNUNET_assert (NULL !=
|
||||
cmd->details.withdraw_sign.reserve_reference);
|
||||
cmd->details.reserve_withdraw.reserve_reference);
|
||||
ref = find_command (is,
|
||||
cmd->details.withdraw_sign.reserve_reference);
|
||||
cmd->details.reserve_withdraw.reserve_reference);
|
||||
GNUNET_assert (NULL != ref);
|
||||
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
|
||||
if (NULL != cmd->details.withdraw_sign.amount)
|
||||
if (NULL != cmd->details.reserve_withdraw.amount)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (cmd->details.withdraw_sign.amount,
|
||||
TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
|
||||
&amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u\n",
|
||||
cmd->details.withdraw_sign.amount,
|
||||
cmd->details.reserve_withdraw.amount,
|
||||
is->ip);
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
cmd->details.withdraw_sign.pk = find_pk (is->keys,
|
||||
&amount);
|
||||
cmd->details.reserve_withdraw.pk = find_pk (is->keys,
|
||||
&amount);
|
||||
}
|
||||
if (NULL == cmd->details.withdraw_sign.pk)
|
||||
if (NULL == cmd->details.reserve_withdraw.pk)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to determine denomination key at %u\n",
|
||||
@ -1263,23 +1367,22 @@ interpreter_run (void *cls,
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
|
||||
|
||||
priv = GNUNET_CRYPTO_eddsa_key_create ();
|
||||
cmd->details.withdraw_sign.coin_priv.eddsa_priv = *priv;
|
||||
cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
|
||||
GNUNET_free (priv);
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.withdraw_sign.coin_priv.eddsa_priv,
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
cmd->details.withdraw_sign.blinding_key.rsa_blinding_key
|
||||
= GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.withdraw_sign.pk->key.rsa_public_key));
|
||||
|
||||
cmd->details.withdraw_sign.wsh
|
||||
= TALER_MINT_withdraw_sign (mint,
|
||||
cmd->details.withdraw_sign.pk,
|
||||
&ref->details.admin_add_incoming.reserve_priv,
|
||||
&cmd->details.withdraw_sign.coin_priv,
|
||||
&cmd->details.withdraw_sign.blinding_key,
|
||||
&withdraw_sign_cb,
|
||||
is);
|
||||
if (NULL == cmd->details.withdraw_sign.wsh)
|
||||
cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key
|
||||
= GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.reserve_withdraw.pk->key.rsa_public_key));
|
||||
cmd->details.reserve_withdraw.wsh
|
||||
= TALER_MINT_reserve_withdraw (mint,
|
||||
cmd->details.reserve_withdraw.pk,
|
||||
&ref->details.admin_add_incoming.reserve_priv,
|
||||
&cmd->details.reserve_withdraw.coin_priv,
|
||||
&cmd->details.reserve_withdraw.blinding_key,
|
||||
&reserve_withdraw_cb,
|
||||
is);
|
||||
if (NULL == cmd->details.reserve_withdraw.wsh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
fail (is);
|
||||
@ -1308,9 +1411,9 @@ interpreter_run (void *cls,
|
||||
switch (ref->oc)
|
||||
{
|
||||
case OC_WITHDRAW_SIGN:
|
||||
coin_priv = &ref->details.withdraw_sign.coin_priv;
|
||||
coin_pk = ref->details.withdraw_sign.pk;
|
||||
coin_pk_sig = &ref->details.withdraw_sign.sig;
|
||||
coin_priv = &ref->details.reserve_withdraw.coin_priv;
|
||||
coin_pk = ref->details.reserve_withdraw.pk;
|
||||
coin_pk_sig = &ref->details.reserve_withdraw.sig;
|
||||
break;
|
||||
case OC_REFRESH_REVEAL:
|
||||
{
|
||||
@ -1355,7 +1458,6 @@ interpreter_run (void *cls,
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
|
||||
@ -1377,6 +1479,7 @@ interpreter_run (void *cls,
|
||||
{
|
||||
struct TALER_DepositRequestPS dr;
|
||||
|
||||
memset (&dr, 0, sizeof (dr));
|
||||
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
|
||||
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
|
||||
dr.h_contract = h_contract;
|
||||
@ -1395,7 +1498,6 @@ interpreter_run (void *cls,
|
||||
GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
|
||||
&dr.purpose,
|
||||
&coin_sig.eddsa_signature));
|
||||
|
||||
}
|
||||
cmd->details.deposit.dh
|
||||
= TALER_MINT_deposit (mint,
|
||||
@ -1454,7 +1556,7 @@ interpreter_run (void *cls,
|
||||
GNUNET_assert (NULL != ref);
|
||||
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
|
||||
|
||||
melt_privs[i] = ref->details.withdraw_sign.coin_priv;
|
||||
melt_privs[i] = ref->details.reserve_withdraw.coin_priv;
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (md->amount,
|
||||
&melt_amounts[i]))
|
||||
@ -1466,8 +1568,8 @@ interpreter_run (void *cls,
|
||||
fail (is);
|
||||
return;
|
||||
}
|
||||
melt_sigs[i] = ref->details.withdraw_sign.sig;
|
||||
melt_pks[i] = *ref->details.withdraw_sign.pk;
|
||||
melt_sigs[i] = ref->details.reserve_withdraw.sig;
|
||||
melt_pks[i] = *ref->details.reserve_withdraw.pk;
|
||||
}
|
||||
for (i=0;i<num_fresh_coins;i++)
|
||||
{
|
||||
@ -1477,7 +1579,7 @@ interpreter_run (void *cls,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u\n",
|
||||
cmd->details.withdraw_sign.amount,
|
||||
cmd->details.reserve_withdraw.amount,
|
||||
is->ip);
|
||||
fail (is);
|
||||
return;
|
||||
@ -1544,7 +1646,7 @@ interpreter_run (void *cls,
|
||||
/* find melt command */
|
||||
ref = find_command (is,
|
||||
ref->details.refresh_reveal.melt_ref);
|
||||
/* find withdraw_sign command */
|
||||
/* find reserve_withdraw command */
|
||||
{
|
||||
unsigned int idx;
|
||||
const struct MeltDetails *md;
|
||||
@ -1563,7 +1665,7 @@ interpreter_run (void *cls,
|
||||
/* finally, use private key from withdraw sign command */
|
||||
cmd->details.refresh_link.rlh
|
||||
= TALER_MINT_refresh_link (mint,
|
||||
&ref->details.withdraw_sign.coin_priv,
|
||||
&ref->details.reserve_withdraw.coin_priv,
|
||||
&link_cb,
|
||||
is);
|
||||
if (NULL == cmd->details.refresh_link.rlh)
|
||||
@ -1574,6 +1676,12 @@ interpreter_run (void *cls,
|
||||
}
|
||||
trigger_context_task ();
|
||||
return;
|
||||
case OC_WIRE:
|
||||
cmd->details.wire.wh = TALER_MINT_wire (mint,
|
||||
&wire_cb,
|
||||
is);
|
||||
trigger_context_task ();
|
||||
return;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unknown instruction %d at %u (%s)\n",
|
||||
@ -1623,35 +1731,35 @@ do_shutdown (void *cls,
|
||||
}
|
||||
break;
|
||||
case OC_WITHDRAW_STATUS:
|
||||
if (NULL != cmd->details.withdraw_status.wsh)
|
||||
if (NULL != cmd->details.reserve_status.wsh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
i,
|
||||
cmd->label);
|
||||
TALER_MINT_withdraw_status_cancel (cmd->details.withdraw_status.wsh);
|
||||
cmd->details.withdraw_status.wsh = NULL;
|
||||
TALER_MINT_reserve_status_cancel (cmd->details.reserve_status.wsh);
|
||||
cmd->details.reserve_status.wsh = NULL;
|
||||
}
|
||||
break;
|
||||
case OC_WITHDRAW_SIGN:
|
||||
if (NULL != cmd->details.withdraw_sign.wsh)
|
||||
if (NULL != cmd->details.reserve_withdraw.wsh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
i,
|
||||
cmd->label);
|
||||
TALER_MINT_withdraw_sign_cancel (cmd->details.withdraw_sign.wsh);
|
||||
cmd->details.withdraw_sign.wsh = NULL;
|
||||
TALER_MINT_reserve_withdraw_cancel (cmd->details.reserve_withdraw.wsh);
|
||||
cmd->details.reserve_withdraw.wsh = NULL;
|
||||
}
|
||||
if (NULL != cmd->details.withdraw_sign.sig.rsa_signature)
|
||||
if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_signature_free (cmd->details.withdraw_sign.sig.rsa_signature);
|
||||
cmd->details.withdraw_sign.sig.rsa_signature = NULL;
|
||||
GNUNET_CRYPTO_rsa_signature_free (cmd->details.reserve_withdraw.sig.rsa_signature);
|
||||
cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
|
||||
}
|
||||
if (NULL != cmd->details.withdraw_sign.blinding_key.rsa_blinding_key)
|
||||
if (NULL != cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.withdraw_sign.blinding_key.rsa_blinding_key);
|
||||
cmd->details.withdraw_sign.blinding_key.rsa_blinding_key = NULL;
|
||||
GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key);
|
||||
cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key = NULL;
|
||||
}
|
||||
break;
|
||||
case OC_DEPOSIT:
|
||||
@ -1714,6 +1822,13 @@ do_shutdown (void *cls,
|
||||
cmd->details.refresh_link.rlh = NULL;
|
||||
}
|
||||
break;
|
||||
case OC_WIRE:
|
||||
if (NULL != cmd->details.wire.wh)
|
||||
{
|
||||
TALER_MINT_wire_cancel (cmd->details.wire.wh);
|
||||
cmd->details.wire.wh = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unknown instruction %d at %u (%s)\n",
|
||||
@ -1880,6 +1995,28 @@ run (void *cls,
|
||||
};
|
||||
static struct Command commands[] =
|
||||
{
|
||||
/* *************** start of /wire testing ************** */
|
||||
|
||||
#if WIRE_TEST
|
||||
{ .oc = OC_WIRE,
|
||||
.label = "wire-test",
|
||||
/* /wire/test replies with a 302 redirect */
|
||||
.expected_response_code = MHD_HTTP_FOUND,
|
||||
.details.wire.format = "test" },
|
||||
#endif
|
||||
#if WIRE_SEPA
|
||||
{ .oc = OC_WIRE,
|
||||
.label = "wire-sepa",
|
||||
/* /wire/sepa replies with a 200 redirect */
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.wire.format = "sepa" },
|
||||
#endif
|
||||
/* *************** end of /wire testing ************** */
|
||||
|
||||
#if WIRE_TEST
|
||||
/* None of this works if 'test' is not allowed as we do
|
||||
/admin/add/incoming with format 'test' */
|
||||
|
||||
/* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
|
||||
{ .oc = OC_ADMIN_ADD_INCOMING,
|
||||
.label = "create-reserve-1",
|
||||
@ -1890,15 +2027,15 @@ run (void *cls,
|
||||
{ .oc = OC_WITHDRAW_SIGN,
|
||||
.label = "withdraw-coin-1",
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.withdraw_sign.reserve_reference = "create-reserve-1",
|
||||
.details.withdraw_sign.amount = "EUR:5" },
|
||||
.details.reserve_withdraw.reserve_reference = "create-reserve-1",
|
||||
.details.reserve_withdraw.amount = "EUR:5" },
|
||||
/* Check that deposit and withdraw operation are in history, and
|
||||
that the balance is now at zero */
|
||||
{ .oc = OC_WITHDRAW_STATUS,
|
||||
.label = "withdraw-status-1",
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.withdraw_status.reserve_reference = "create-reserve-1",
|
||||
.details.withdraw_status.expected_balance = "EUR:0" },
|
||||
.details.reserve_status.reserve_reference = "create-reserve-1",
|
||||
.details.reserve_status.expected_balance = "EUR:0" },
|
||||
/* Try to deposit the 5 EUR coin (in full) */
|
||||
{ .oc = OC_DEPOSIT,
|
||||
.label = "deposit-simple",
|
||||
@ -1913,8 +2050,8 @@ run (void *cls,
|
||||
{ .oc = OC_WITHDRAW_SIGN,
|
||||
.label = "withdraw-coin-2",
|
||||
.expected_response_code = MHD_HTTP_PAYMENT_REQUIRED,
|
||||
.details.withdraw_sign.reserve_reference = "create-reserve-1",
|
||||
.details.withdraw_sign.amount = "EUR:5" },
|
||||
.details.reserve_withdraw.reserve_reference = "create-reserve-1",
|
||||
.details.reserve_withdraw.amount = "EUR:5" },
|
||||
|
||||
/* Try to double-spend the 5 EUR coin with different wire details */
|
||||
{ .oc = OC_DEPOSIT,
|
||||
@ -1958,8 +2095,8 @@ run (void *cls,
|
||||
{ .oc = OC_WITHDRAW_SIGN,
|
||||
.label = "refresh-withdraw-coin-1",
|
||||
.expected_response_code = MHD_HTTP_OK,
|
||||
.details.withdraw_sign.reserve_reference = "refresh-create-reserve-1",
|
||||
.details.withdraw_sign.amount = "EUR:5" },
|
||||
.details.reserve_withdraw.reserve_reference = "refresh-create-reserve-1",
|
||||
.details.reserve_withdraw.amount = "EUR:5" },
|
||||
/* Try to partially spend (deposit) 1 EUR of the 5 EUR coin (in full)
|
||||
(merchant would receive EUR:0.99 due to 1 ct deposit fee) */
|
||||
{ .oc = OC_DEPOSIT,
|
||||
@ -2024,10 +2161,10 @@ run (void *cls,
|
||||
.details.refresh_melt.melted_coins = melt_coins_1,
|
||||
.details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
|
||||
|
||||
// FIXME: also test with coin that was already melted
|
||||
// FIXME: also test with coin that was already melted
|
||||
// (signature differs from coin that was deposited...)
|
||||
|
||||
/* *************** end of /refresh testing ************** */
|
||||
#endif
|
||||
|
||||
{ .oc = OC_END }
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ if USE_COVERAGE
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = \
|
||||
taler-auditor-sign \
|
||||
taler-mint-keyup \
|
||||
taler-mint-keycheck \
|
||||
taler-mint-reservemod \
|
||||
@ -15,7 +16,6 @@ bin_PROGRAMS = \
|
||||
|
||||
taler_mint_keyup_SOURCES = \
|
||||
taler-mint-keyup.c
|
||||
|
||||
taler_mint_keyup_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
@ -24,6 +24,14 @@ taler_mint_keyup_LDADD = \
|
||||
-lgnunetutil $(XLIB)
|
||||
taler_mint_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS)
|
||||
|
||||
taler_auditor_sign_SOURCES = \
|
||||
taler-auditor-sign.c
|
||||
taler_auditor_sign_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/mintdb/libtalermintdb.la \
|
||||
-lgnunetutil $(XLIB)
|
||||
|
||||
|
||||
taler_mint_sepa_SOURCES = \
|
||||
taler-mint-sepa.c
|
||||
|
@ -23,6 +23,11 @@
|
||||
#include "taler_mintdb_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Are we running in verbose mode?
|
||||
*/
|
||||
static int verbose;
|
||||
|
||||
/**
|
||||
* Filename of the auditor's private key.
|
||||
*/
|
||||
@ -44,17 +49,68 @@ static char *mint_request_file;
|
||||
*/
|
||||
static char *output_file;
|
||||
|
||||
/**
|
||||
* Handle to the auditor's configuration
|
||||
*/
|
||||
static struct GNUNET_CONFIGURATION_Handle *kcfg;
|
||||
|
||||
/**
|
||||
* Master public key of the mint.
|
||||
*/
|
||||
static struct TALER_MasterPublicKeyP master_public_key;
|
||||
|
||||
|
||||
/**
|
||||
* Print denomination key details for diagnostics.
|
||||
*
|
||||
* @param dk denomination key to print
|
||||
*/
|
||||
static void
|
||||
print_dk (const struct TALER_DenominationKeyValidityPS *dk)
|
||||
{
|
||||
struct TALER_Amount a;
|
||||
char *s;
|
||||
|
||||
fprintf (stdout,
|
||||
"Denomination key hash: %s\n",
|
||||
GNUNET_h2s_full (&dk->denom_hash));
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->value);
|
||||
fprintf (stdout,
|
||||
"Value: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_withdraw);
|
||||
fprintf (stdout,
|
||||
"Withdraw fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_deposit);
|
||||
fprintf (stdout,
|
||||
"Deposit fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_refresh);
|
||||
fprintf (stdout,
|
||||
"Refresh fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
|
||||
fprintf (stdout,
|
||||
"Validity start time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->start)));
|
||||
fprintf (stdout,
|
||||
"Withdraw end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_withdraw)));
|
||||
fprintf (stdout,
|
||||
"Deposit end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_spend)));
|
||||
fprintf (stdout,
|
||||
"Legal dispute end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_legal)));
|
||||
|
||||
fprintf (stdout,
|
||||
"\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main function of the taler-auditor-sign tool. This tool is used
|
||||
@ -79,18 +135,24 @@ main (int argc,
|
||||
"public key of the mint (Crockford base32 encoded)", 1,
|
||||
&GNUNET_GETOPT_set_filename, &mint_public_key},
|
||||
{'r', "mint-request", "FILE",
|
||||
"set of keys the mint requested the auditor to sign", 0,
|
||||
"set of keys the mint requested the auditor to sign", 1,
|
||||
&GNUNET_GETOPT_set_string, &mint_request_file},
|
||||
{'o', "output", "FILE",
|
||||
"where to write our signature", 0,
|
||||
"where to write our signature", 1,
|
||||
&GNUNET_GETOPT_set_string, &output_file},
|
||||
GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION),
|
||||
GNUNET_GETOPT_OPTION_VERBOSE (&verbose),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
|
||||
struct TALER_AuditorSignatureP *sigs;
|
||||
struct TALER_AuditorPublicKeyP apub;
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
struct GNUNET_DISK_FileHandle *fout;
|
||||
struct TALER_DenominationKeyValidityPS *dks;
|
||||
unsigned int dks_len;
|
||||
struct TALER_MintKeyValidityPS kv;
|
||||
off_t in_size;
|
||||
unsigned int i;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_log_setup ("taler-mint-keyup",
|
||||
@ -114,10 +176,13 @@ main (int argc,
|
||||
auditor_key_file);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (eddsa_priv,
|
||||
&apub.eddsa_pub);
|
||||
if (NULL == mint_public_key)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Mint public key not given\n");
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
@ -129,12 +194,14 @@ main (int argc,
|
||||
fprintf (stderr,
|
||||
"Public key `%s' malformed\n",
|
||||
mint_public_key);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
if (NULL == mint_request_file)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Mint signing request not given\n");
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
fh = GNUNET_DISK_file_open (mint_request_file,
|
||||
@ -146,6 +213,7 @@ main (int argc,
|
||||
"Failed to open file `%s': %s\n",
|
||||
mint_request_file,
|
||||
STRERROR (errno));
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
@ -157,34 +225,95 @@ main (int argc,
|
||||
mint_request_file,
|
||||
STRERROR (errno));
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
if (0 != (in_size % sizeof (struct TALER_DenominationKeyValidityPS)))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Input file size of file `%s' is invalid\n",
|
||||
mint_request_file);
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
dks_len = in_size / sizeof (struct TALER_DenominationKeyValidityPS);
|
||||
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
|
||||
kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
|
||||
kv.master = master_public_key;
|
||||
dks = GNUNET_new_array (dks_len,
|
||||
struct TALER_DenominationKeyValidityPS);
|
||||
sigs = GNUNET_new_array (dks_len,
|
||||
struct TALER_AuditorSignatureP);
|
||||
if (in_size !=
|
||||
GNUNET_DISK_file_read (fh,
|
||||
dks,
|
||||
in_size))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to read input file `%s': %s\n",
|
||||
mint_request_file,
|
||||
STRERROR (errno));
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (dks);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_DISK_file_close (fh);
|
||||
for (i=0;i<dks_len;i++)
|
||||
{
|
||||
struct TALER_DenominationKeyValidityPS *dk = &dks[i];
|
||||
|
||||
if (verbose)
|
||||
print_dk (dk);
|
||||
kv.start = dk->start;
|
||||
kv.expire_withdraw = dk->expire_withdraw;
|
||||
kv.expire_spend = dk->expire_spend;
|
||||
kv.expire_legal = dk->expire_legal;
|
||||
kv.value = dk->value;
|
||||
kv.fee_withdraw = dk->fee_withdraw;
|
||||
kv.fee_deposit = dk->fee_deposit;
|
||||
kv.fee_refresh = dk->fee_refresh;
|
||||
kv.denom_hash = dk->denom_hash;
|
||||
|
||||
/* Finally sign ... */
|
||||
GNUNET_CRYPTO_eddsa_sign (eddsa_priv,
|
||||
&kv.purpose,
|
||||
&sigs[i].eddsa_sig);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (NULL == output_file)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Output file not given\n");
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (dks);
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 1;
|
||||
}
|
||||
fout = GNUNET_DISK_file_open (output_file,
|
||||
GNUNET_DISK_OPEN_READ |
|
||||
GNUNET_DISK_OPEN_TRUNCATE |
|
||||
GNUNET_DISK_OPEN_CREATE,
|
||||
GNUNET_DISK_PERM_USER_READ |
|
||||
GNUNET_DISK_PERM_USER_WRITE |
|
||||
GNUNET_DISK_PERM_GROUP_READ |
|
||||
GNUNET_DISK_PERM_OTHER_READ);
|
||||
if (NULL == fout)
|
||||
|
||||
/* write result to disk */
|
||||
if (GNUNET_OK !=
|
||||
TALER_MINTDB_auditor_write (output_file,
|
||||
&apub,
|
||||
sigs,
|
||||
&master_public_key,
|
||||
dks_len,
|
||||
dks))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to open file `%s': %s\n",
|
||||
"Failed to write to file `%s': %s\n",
|
||||
output_file,
|
||||
STRERROR (errno));
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (dks);
|
||||
return 1;
|
||||
}
|
||||
/* FIXME: finally do real work... */
|
||||
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (dks);
|
||||
GNUNET_free (eddsa_priv);
|
||||
return 0;
|
||||
}
|
||||
|
@ -157,6 +157,17 @@ struct CoinTypeParams
|
||||
*/
|
||||
static char *masterkeyfile;
|
||||
|
||||
/**
|
||||
* Filename where to write denomination key signing
|
||||
* requests for the auditor (optional, can be NULL).
|
||||
*/
|
||||
static char *auditorrequestfile;
|
||||
|
||||
/**
|
||||
* Handle for writing the output for the auditor.
|
||||
*/
|
||||
static FILE *auditor_output_file;
|
||||
|
||||
/**
|
||||
* Director of the mint, containing the keys.
|
||||
*/
|
||||
@ -807,6 +818,20 @@ mint_keys_update_cointype (void *cls,
|
||||
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
|
||||
return;
|
||||
}
|
||||
if ( (NULL != auditor_output_file) &&
|
||||
(sizeof (denomkey_issue.issue.properties) !=
|
||||
fwrite (&denomkey_issue.issue.properties,
|
||||
sizeof (struct TALER_DenominationKeyValidityPS),
|
||||
1,
|
||||
auditor_output_file)) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to write denomination key information to %s: %s\n",
|
||||
auditorrequestfile,
|
||||
STRERROR (errno));
|
||||
*ret = GNUNET_SYSERR;
|
||||
return;
|
||||
}
|
||||
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
|
||||
p.anchor = GNUNET_TIME_absolute_add (p.anchor,
|
||||
p.duration_spend);
|
||||
@ -859,6 +884,9 @@ main (int argc,
|
||||
{'m', "master-key", "FILE",
|
||||
"master key file (private key)", 1,
|
||||
&GNUNET_GETOPT_set_filename, &masterkeyfile},
|
||||
{'o', "output", "FILE",
|
||||
"auditor denomination key signing request file to create", 1,
|
||||
&GNUNET_GETOPT_set_filename, &auditorrequestfile},
|
||||
{'t', "time", "TIMESTAMP",
|
||||
"pretend it is a different time for the update", 0,
|
||||
&GNUNET_GETOPT_set_string, &pretend_time_str},
|
||||
@ -927,6 +955,20 @@ main (int argc,
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv,
|
||||
&master_public_key.eddsa_pub);
|
||||
|
||||
if (NULL != auditorrequestfile)
|
||||
{
|
||||
auditor_output_file = FOPEN (auditorrequestfile,
|
||||
"w");
|
||||
if (NULL == auditor_output_file)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to open `%s' for writing: %s\n",
|
||||
auditorrequestfile,
|
||||
STRERROR (errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if key from file matches the one from the configuration */
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey master_public_key_from_cfg;
|
||||
@ -986,6 +1028,11 @@ main (int argc,
|
||||
|
||||
if (GNUNET_OK != mint_keys_update_denomkeys ())
|
||||
return 1;
|
||||
if (NULL != auditor_output_file)
|
||||
{
|
||||
FCLOSE (auditor_output_file);
|
||||
auditor_output_file = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ taler_mint_httpd_SOURCES = \
|
||||
taler-mint-httpd_mhd.c taler-mint-httpd_mhd.h \
|
||||
taler-mint-httpd_admin.c taler-mint-httpd_admin.h \
|
||||
taler-mint-httpd_deposit.c taler-mint-httpd_deposit.h \
|
||||
taler-mint-httpd_withdraw.c taler-mint-httpd_withdraw.h \
|
||||
taler-mint-httpd_reserve.c taler-mint-httpd_reserve.h \
|
||||
taler-mint-httpd_wire.c taler-mint-httpd_wire.h \
|
||||
taler-mint-httpd_refresh.c taler-mint-httpd_refresh.h
|
||||
taler_mint_httpd_LDADD = \
|
||||
@ -34,3 +34,9 @@ if HAVE_DEVELOPER
|
||||
taler_mint_httpd_SOURCES += \
|
||||
taler-mint-httpd_test.c taler-mint-httpd_test.h
|
||||
endif
|
||||
|
||||
check_SCRIPTS = \
|
||||
test_taler_mint_httpd.sh \
|
||||
test_taler_mint_httpd_afl.sh
|
||||
|
||||
TESTS = $(check_SCRIPTS)
|
||||
|
7
src/mint/afl-tests/id:000000,orig:admin_add_incoming.req
Normal file
7
src/mint/afl-tests/id:000000,orig:admin_add_incoming.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
8
src/mint/afl-tests/id:000001,orig:deposit.req
Normal file
8
src/mint/afl-tests/id:000001,orig:deposit.req
Normal file
@ -0,0 +1,8 @@
|
||||
POST /deposit HTTP/1.1
|
||||
Host: locst:8081
|
||||
Accept: */*
|
||||
Content-: applicn/json
|
||||
Content-Length: 1658
|
||||
Expect: 100-continue
|
||||
|
||||
{"ub_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26E9M8S0M6CSH6X334GSN8RW30D9G8MT46CA660W34GSG6MT4AD9K8GT3ECSH6MVK0E2374V38H1M8MR4CDJ66MWK4E1S6MR3GCT28CV32H1Q8N23GCHG70S36C1K8MS3GCSN8RV36D9S710KGD9K6GWKEGJ28GRM4CJ56X1K6DJ18D2KGHA46D13GDA66GVK4GHJ8N13AE9J8RVK6GT184S48E1K6X336G9Q8N142CJ4692M6EA16GRKJD9N6523ADA36X13GG9G70TK6DHN68R36CT18GR4CDSJ6CW3GCT364W46CSR8RV42GJ474SMADSH851K4H9Q8GS42CHS8RV3GCSJ64V46DSN8RSM6HHN6N246D9S6934AH9P6X23JGSH652K0DJ5612KJGA26N242CH35452081918G2J2G0","timestamp":"/Date(1442821652)/","f":{"currency":"EUR","value":5,"fraction":0},"wire":{"type":"TEST","bank":"dest bank","account":42},"coin_pub":"JXWK4NS0H2W4V4BETQ90CCEDADP6QQ3MV3YZ7RV2KXEM8PWXE8Q0","H_wire":"YQED9FDYPKK2QQYB3FS19Y15ZMKBAXJP2C73CXASAF1KM6ZYY723TEJ3HBR6D864A7X5W58G92QJ0A9PFMZNB81ZP9NJAQQCCABM4RG","H_contract":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","transaction_id":1,"refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"}
|
File diff suppressed because one or more lines are too long
7
src/mint/afl-tests/id:000002,orig:keys.req
Normal file
7
src/mint/afl-tests/id:000002,orig:keys.req
Normal file
@ -0,0 +1,7 @@
|
||||
GET /keys HTTP/1.1
|
||||
User-Agent: Wget/1.16.3 (linux-gnu)
|
||||
Accept: */*
|
||||
Accept-Encoding: identity
|
||||
Host: 127.0.0.1:8081
|
||||
Connection: Keep-Alive
|
||||
|
5
src/mint/afl-tests/id:000003,orig:refresh_link.req
Normal file
5
src/mint/afl-tests/id:000003,orig:refresh_link.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /refresh/link?coin_pub=WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
8
src/mint/afl-tests/id:000004,orig:refresh_melt.req
Normal file
8
src/mint/afl-tests/id:000004,orig:refresh_melt.req
Normal file
File diff suppressed because one or more lines are too long
7
src/mint/afl-tests/id:000005,orig:refresh_reveal.req
Normal file
7
src/mint/afl-tests/id:000005,orig:refresh_reveal.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /refresh/reveal HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 255
|
||||
|
||||
{"session_hash":"V97SB8T670M9V71D1Q0KVQ4GSJCVQ5AAKTTH9QKT0ZJZZBFNZAV4NA8NMWRRGVPFEBEGB6ANCN9BPQASJ40TM4Y1C49648TJJ07PGSG","transfer_privs":[["EQKJA401A9NJ2YJDFZJ1EV8AYXBHWZB6NT5T0TWSJHVKVDM6W8A0"],["TKDJ4DF3GZVG0DGAB9E3RGBGSTANYB6JVVWXJGPMB2AY4VQNTBA0"]]}
|
4
src/mint/afl-tests/id:000006,orig:reserve_status.req
Normal file
4
src/mint/afl-tests/id:000006,orig:reserve_status.req
Normal file
@ -0,0 +1,4 @@
|
||||
GET /reserve/status?reserve_pub=TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0 HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
|
7
src/mint/afl-tests/id:000007,orig:reserve_withdraw.req
Normal file
7
src/mint/afl-tests/id:000007,orig:reserve_withdraw.req
Normal file
@ -0,0 +1,7 @@
|
||||
POST /reserve/withdraw HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 919
|
||||
|
||||
{"coin_ev":"Q5X8A8TCBFH7E5BMY7HSB17SHFTM1JPJGV61P2CA7Z9EXG8P2HYS69B31NZESKXHSZHNJ2DQN3CC2AWFNC6V90J577JD3TXBMAY8Y5M9V60KKT73Z1DW24JFSNAK91G1F2WT55ADP1EG7N5F9AY7A7ZJD03MPYSH0RDP7SVZS2KRPA5JRHFR4GDJ59CFNE7A43M95ZKQHQAS8","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","reserve_sig":"8427B3RTB217124EB1C37ZVJFC08KN17RHGHE9ENZQMQVJ0S11SAX6H8Z06SWCKT06DRQ9DQ8XD786XKQ94T27PYR9GC9EMT1Y02W10"}
|
5
src/mint/afl-tests/id:000008,orig:wire.req
Normal file
5
src/mint/afl-tests/id:000008,orig:wire.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
5
src/mint/afl-tests/id:000009,orig:wire_sepa.req
Normal file
5
src/mint/afl-tests/id:000009,orig:wire_sepa.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire/sepa HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
5
src/mint/afl-tests/id:000010,orig:wire_test.req
Normal file
5
src/mint/afl-tests/id:000010,orig:wire_test.req
Normal file
@ -0,0 +1,5 @@
|
||||
GET /wire/test HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
|
@ -0,0 +1,7 @@
|
||||
PoST /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POsT /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POSt /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
BIN
src/mint/afl-tests/id:000012,src:000000,op:flip1,pos:4,+cov
Normal file
BIN
src/mint/afl-tests/id:000012,src:000000,op:flip1,pos:4,+cov
Normal file
Binary file not shown.
BIN
src/mint/afl-tests/id:000013,src:000000,op:flip1,pos:4,+cov
Normal file
BIN
src/mint/afl-tests/id:000013,src:000000,op:flip1,pos:4,+cov
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
POST ¯admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST ¯admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST ?admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /adMin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
7
src/mint/afl-tests/id:000016,src:000000,op:flip1,pos:11
Normal file
7
src/mint/afl-tests/id:000016,src:000000,op:flip1,pos:11
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin?add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST 'admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/aDd/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /aDmin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/atd/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admIn/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
7
src/mint/afl-tests/id:000019,src:000000,op:flip1,pos:11
Normal file
7
src/mint/afl-tests/id:000019,src:000000,op:flip1,pos:11
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin?add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incOming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/Add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incmming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/aDd/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incomIng HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/iNcoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incominG HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incomiNg HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
BIN
src/mint/afl-tests/id:000025,src:000000,op:flip1,pos:24,+cov
Normal file
BIN
src/mint/afl-tests/id:000025,src:000000,op:flip1,pos:24,+cov
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming @TTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HtTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HDTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HVTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTÔP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
7
src/mint/afl-tests/id:000030,src:000000,op:flip1,pos:27
Normal file
7
src/mint/afl-tests/id:000030,src:000000,op:flip1,pos:27
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTDP/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HT\P/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTT@/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTÐ/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/±.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTT@/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/q.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTT/1.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/9.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/0.1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1&1
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.±
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
7
src/mint/afl-tests/id:000038,src:000000,op:flip1,pos:32
Normal file
7
src/mint/afl-tests/id:000038,src:000000,op:flip1,pos:32
Normal file
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.3
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
@ -0,0 +1,7 @@
|
||||
POST /admin/add/incoming HTTP/1.!
|
||||
Host: localhost:8081
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 220
|
||||
|
||||
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user