resolving merge issue
This commit is contained in:
commit
1d740824fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -30,6 +30,7 @@ GTAGS
|
||||
src/lib/test_exchange_api
|
||||
doc/doxygen/doxygen_sqlite3.db
|
||||
src/auditor/taler-auditor
|
||||
src/auditor/taler-auditor-sign
|
||||
src/bank-lib/test_bank_api
|
||||
src/bank-lib/test_bank_api_with_fakebank
|
||||
src/exchange-lib/test_exchange_api
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "doc/api"]
|
||||
path = doc/api
|
||||
url = git@git.taler.net:api
|
||||
[submodule "gnunet"]
|
||||
path = gnunet
|
||||
url = git://taler.net/gnunet.git
|
||||
|
84
default.nix
Normal file
84
default.nix
Normal file
@ -0,0 +1,84 @@
|
||||
# Nix package for GNUnet development
|
||||
#
|
||||
## INSTALL
|
||||
#
|
||||
# To build and install the package in the user environment, use:
|
||||
#
|
||||
# $ nix-env -f . -i
|
||||
#
|
||||
## BUILD ONLY
|
||||
#
|
||||
# To build the package and add it to the nix store, use:
|
||||
#
|
||||
# $ nix-build
|
||||
#
|
||||
## SHELL
|
||||
#
|
||||
# To launch a shell with all dependencies installed in the environment, use one of the following:
|
||||
# $ nix-shell
|
||||
#
|
||||
# After entering nix-shell, build it:
|
||||
#
|
||||
# $ configurePhase
|
||||
# $ buildPhase
|
||||
#
|
||||
## NIXPKGS
|
||||
#
|
||||
# For all of the above commands, nixpkgs to use can be set the following way:
|
||||
#
|
||||
# a) by default it uses nixpkgs pinned to a known working version
|
||||
#
|
||||
# b) use nixpkgs from the system:
|
||||
# --arg pkgs 0
|
||||
#
|
||||
# c) use nixpkgs at a given path
|
||||
# --arg pkgs /path/to/nixpkgs
|
||||
#
|
||||
## CCACHE
|
||||
#
|
||||
# To enable ccache, use the following:
|
||||
#
|
||||
# --argstr ccache_dir /var/cache/ccache
|
||||
|
||||
# or when using nix-shell:
|
||||
# --argstr ccache_dir ~/.ccache
|
||||
#
|
||||
# and make sure the given directory is writable by the nixpkgs group when using nix-build or nix-env -i,
|
||||
# or the current user when using nix-shell
|
||||
#
|
||||
|
||||
{
|
||||
pkgs ? null,
|
||||
ccache_dir ? "",
|
||||
}:
|
||||
|
||||
let
|
||||
syspkgs = import <nixpkgs> { };
|
||||
pinpkgs = syspkgs.fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nixpkgs";
|
||||
|
||||
# binary cache exists for revisions in https://nixos.org/releases/nixos/<release>/<build>/git-revision
|
||||
rev = "c4469edac1fc1fa5e5b5aa2ceadeda8f3f92d30a"; # https://nixos.org/releases/nixos/16.09/nixos-16.09beta430.c4469ed/git-revision
|
||||
sha256 = "1x6hmf815d5anfxrxl6iivfkk60q5qxa6waa9xnwhwkbc14rhvn9";
|
||||
};
|
||||
usepkgs = if null == pkgs then
|
||||
import pinpkgs {}
|
||||
else
|
||||
if 0 == pkgs then
|
||||
import <nixpkgs> { }
|
||||
else
|
||||
import pkgs {};
|
||||
stdenv = usepkgs.stdenvAdapters.keepDebugInfo usepkgs.stdenv;
|
||||
|
||||
in {
|
||||
gnunet-dev = usepkgs.callPackage ./gnunet/gnunet-dev.nix {
|
||||
inherit ccache_dir;
|
||||
};
|
||||
taler-exchange-dev = usepkgs.callPackage ./taler-exchange-dev.nix {
|
||||
inherit ccache_dir;
|
||||
gnunet-dev = usepkgs.callPackage ./gnunet/gnunet-dev.nix {
|
||||
inherit ccache_dir;
|
||||
};
|
||||
};
|
||||
}
|
@ -19,6 +19,13 @@
|
||||
pages = {11-15},
|
||||
}
|
||||
|
||||
@misc{BOLT,
|
||||
author = {Matthew Green and Ian Miers},
|
||||
title = {Bolt: Anonymous Payment Channels for Decentralized Currencies},
|
||||
howpublished = {Cryptology ePrint Archive, Report 2016/701},
|
||||
year = {2016},
|
||||
note = {\url{http://eprint.iacr.org/2016/701}},
|
||||
}
|
||||
|
||||
@Misc{greece2015cash,
|
||||
author = {Reuters},
|
||||
@ -90,6 +97,13 @@
|
||||
organization={Springer}
|
||||
}
|
||||
|
||||
@inproceedings{zerocash,
|
||||
author = {Eli Ben-Sasson and Alessandro Chiesa and Christina Garman and Matthew Green and Ian Miers and Eran Tromer and Madars Virza},
|
||||
title = {Zerocash: Decentralized Anonymous Payments from Bitcoin},
|
||||
booktitle = {IEEE Symposium on Security \& Privacy},
|
||||
year = {2014},
|
||||
}
|
||||
|
||||
@inproceedings{miers2013zerocoin,
|
||||
title={Zerocoin: Anonymous distributed e-cash from bitcoin},
|
||||
author={Miers, Ian and Garman, Christina and Green, Matthew and Rubin, Aviel D},
|
||||
@ -197,9 +211,9 @@
|
||||
author="Bellare, Mihir and Namprempre, Chanathip and Pointcheval, David and Semanko, Michael",
|
||||
editor="Syverson, Paul",
|
||||
chapter="The Power of RSA Inversion Oracles and the Security of Chaum's RSA-Based Blind Signature Scheme",
|
||||
title="Financial Cryptography: 5th International Conference, FC 2001 Grand Cayman, British West Indies, February 19--22, 2001 Proceedings",
|
||||
title="Financial Cryptography: 5th International Conference",
|
||||
year="2002",
|
||||
publisher="Springer Berlin Heidelberg",
|
||||
publisher="Springer",
|
||||
address="Berlin, Heidelberg",
|
||||
pages="319--338",
|
||||
isbn="978-3-540-46088-6",
|
||||
|
@ -63,7 +63,7 @@
|
||||
% - sharing = coin copying that should not be taxed
|
||||
|
||||
|
||||
\title{Refreshing Coins for Giving Change and Refunds \\ in Chaum-style Anonymous Payments}
|
||||
\title{Refreshing Coins for Giving Change and Refunds \\ in Chaum-style Anonymous Payment Systems}
|
||||
|
||||
\begin{document}
|
||||
\mainmatter
|
||||
@ -77,7 +77,7 @@
|
||||
\begin{abstract}
|
||||
This paper introduces {\em Taler}, a Chaum-style digital currency that
|
||||
enables anonymous payments while ensuring that entities that receive
|
||||
payments are auditable and thus taxable. In Taler, customers can
|
||||
payments are auditable. In Taler, customers can
|
||||
never defraud anyone, merchants can only fail to deliver the
|
||||
merchandise to the customer, and payment service providers can be
|
||||
fully audited. All parties receive cryptographic evidence for all
|
||||
@ -88,10 +88,10 @@ systems that do not provide for privacy.
|
||||
|
||||
The key technical contribution underpinning Taler is a new {\em
|
||||
refresh protocol} which allows fractional payments and refunds while
|
||||
maintaining anonymity of the customer and unlinkability of
|
||||
transactions. The refresh protocol combines an efficient
|
||||
cut-and-choose mechanism with a {\em link} step to ensure that
|
||||
refreshing is not abused for transactional payments.
|
||||
maintaining untraceability of the customer and unlinkability of
|
||||
transactions. The refresh protocol combines an
|
||||
efficient cut-and-choose mechanism with a {\em link} step to ensure
|
||||
that refreshing is not abused for transactional payments.
|
||||
|
||||
We argue that Taler provides a secure digital currency for modern
|
||||
liberal societies as it is a flexible, libre and efficient protocol
|
||||
@ -106,11 +106,11 @@ developed nation states have adopted highly transparent payment systems,
|
||||
such as the MasterCard and VisaCard credit card schemes and computerized
|
||||
bank transactions such as SWIFT. These systems enable mass surveillance
|
||||
by both governments and private companies. Aspects of this surveillance
|
||||
sometimes benifit society by providing information about tax evasion or
|
||||
sometimes benefit society by providing information about tax evasion or
|
||||
crimes like extortion. % TODO : anti-money laundering later?
|
||||
In particular, bribery and corruption are limited to elites who can
|
||||
afford to escape the dragnet.
|
||||
|
||||
%
|
||||
At the other extreme, weaker developing nation states have economic
|
||||
activity based largely on coins, paper money or even barter. Here,
|
||||
the state is often unable to effectively monitor or tax economic
|
||||
@ -118,24 +118,23 @@ activity, and this limits the ability of the state to shape the
|
||||
society. As bribery is virtually impossible to detect, corruption is
|
||||
widespread and not limited to social elites.
|
||||
%
|
||||
ZeroCoin~\cite{miers2013zerocoin} is an example for translating an
|
||||
Zerocoin~\cite{miers2013zerocoin} is an example for translating an
|
||||
anarchistic economy into the digital realm.
|
||||
|
||||
This paper describes Taler, a simple and practical payment system for
|
||||
a modern social-liberal society, which is not being served well by
|
||||
current payment systems which enable either an authoritarian state in
|
||||
total control of the population, or create weak states with almost
|
||||
anarchistic economies.
|
||||
a social-liberal society, which is underserved by
|
||||
current payment systems.
|
||||
|
||||
The Taler protocol is influenced by ideas from
|
||||
Chaum~\cite{chaum1983blind} and also follows Chaum's basic architecture of
|
||||
customer, merchant and exchange (Figure~\ref{fig:cmm}).
|
||||
The two designs share the key first step where the {\em customer}
|
||||
withdraws digital {\em coins} from the {\em exchange} with unlinkability
|
||||
provided via blind signatures. The coins can then be spent at a
|
||||
{\em merchant} who {\em deposits} them at the exchange.
|
||||
Taler uses online detection of double-spending, thus assuring the merchant
|
||||
instantly that a transaction is valid.
|
||||
Chaum~\cite{chaum1983blind} and also follows Chaum's basic
|
||||
architecture of customer, merchant and exchange
|
||||
(Figure~\ref{fig:cmm}). The two designs share the key first step
|
||||
where the {\em customer} withdraws digital {\em coins} from the {\em
|
||||
exchange} with unlinkability provided via blind signatures. The
|
||||
coins can then be spent at a {\em merchant} who {\em deposits} them at
|
||||
the exchange. Taler uses online detection of double-spending and
|
||||
provides excuplability via cryptographic proofs. Thus merchants are
|
||||
instantly assured that a transaction is valid.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
@ -159,16 +158,14 @@ instantly that a transaction is valid.
|
||||
\label{fig:cmm}
|
||||
\end{figure}
|
||||
|
||||
|
||||
A key issue for an efficient Chaumian digital payment system is the
|
||||
need to provide change. For example, a customer may want to pay
|
||||
\EUR{49,99}, but has withdrawn a \EUR{100,00} coin. Withdrawng 10,000
|
||||
pieces with a denomination of \EUR{0,01} and transferring 4,999 would
|
||||
be too inefficient, even for modern systems. The customer should not
|
||||
\EUR{49,99}, but has withdrawn a \EUR{100,00} coin. Withdrawing 10,000
|
||||
coins with a denomination of \EUR{0,01} and transferring 4,999 coins would
|
||||
be too inefficient. The customer should not
|
||||
withdraw exact change from her account, as doing so reduces anonymity
|
||||
due to the obvious corrolation. A practical payment system must thus
|
||||
support giving change in the form of spendable coins, say a \EUR{0,01}
|
||||
coin and a \EUR{50,00} coin.
|
||||
due to the obvious correlation. A practical payment system must thus
|
||||
support giving change.
|
||||
|
||||
Taler solves the problem of giving change by introducing a new
|
||||
{\em refresh protocol}. Using this protocol, a customer can obtain
|
||||
@ -178,9 +175,11 @@ Additionally, the refresh protocol ensures that the change is owned by
|
||||
the same entity which owned the original coin.
|
||||
|
||||
|
||||
\vspace{-0.3cm}
|
||||
\section{Related Work}
|
||||
\vspace{-0.3cm}
|
||||
|
||||
\subsection{Blockchain-based currencies}
|
||||
%\subsection{Blockchain-based currencies}
|
||||
|
||||
In recent years, a class of decentralized electronic payment systems,
|
||||
based on collectively recorded and verified append-only public
|
||||
@ -191,13 +190,14 @@ transactions are recorded for eternity, which can enable
|
||||
identification of users. In theory, this concern has been addressed
|
||||
with the Zerocoin extension to the protocol~\cite{miers2013zerocoin}.
|
||||
|
||||
These protocols dispense with the need for a central, trusted
|
||||
authority, while providing a useful measure of pseudonymity.
|
||||
The key contribution of blockchain-based protocols is that
|
||||
they dispense with the need for a central, trusted
|
||||
authority.
|
||||
Yet, there are several major irredeemable problems inherent in their designs:
|
||||
|
||||
\begin{itemize}
|
||||
\item The computational puzzles solved by Bitcoin nodes with the purpose
|
||||
of securing the block chain consume a considerable amount of energy.
|
||||
of securing the blockchain consume a considerable amount of energy.
|
||||
So Bitcoin is an environmentally irresponsible design.
|
||||
\item Bitcoin transactions have pseduononymous recipients, making taxation
|
||||
hard to systematically enforce.
|
||||
@ -216,6 +216,15 @@ Yet, there are several major irredeemable problems inherent in their designs:
|
||||
% currency exchange and exacerbates the problems with currency fluctuations.
|
||||
\end{itemize}
|
||||
|
||||
Anonymity extensions for BitCoin such as Zerocoin~\cite{miers2013zerocoin}
|
||||
and BOLT~\cite{BOLT} are also limited to transactions with coins
|
||||
of fixed discrete value, creating problems with giving change we
|
||||
outlined in the introduction. Furthermore, these extensions have
|
||||
problems with aborted transactions, which can reduce the anonymity
|
||||
set. Taler's refresh protocol also addresses the problem of aborted
|
||||
transactions, ensuring that aborts cannot be used to attack the
|
||||
privacy assurances of the system.
|
||||
|
||||
%GreenCoinX\footnote{\url{https://www.greencoinx.com/}} is a more
|
||||
%recent AltCoin where the company promises to identify the owner of
|
||||
%each coin via e-mail addresses and phone numbers. While it is unclear
|
||||
@ -224,7 +233,7 @@ Yet, there are several major irredeemable problems inherent in their designs:
|
||||
%would also merely impose a financial panopticon on a BitCoin-style
|
||||
%money supply and transaction model.
|
||||
|
||||
\subsection{Chaum-style electronic cash}
|
||||
%\subsection{Chaum-style electronic cash}
|
||||
|
||||
Chaum~\cite{chaum1983blind} proposed a digital payment system that
|
||||
would provide some customer anonymity while disclosing the identity of
|
||||
@ -312,53 +321,64 @@ description of the Opencoin protocol is available to date.
|
||||
%macropayment. It is therefore unclear how Peppercoin would actually
|
||||
%reduce the computational burden on the exchange.
|
||||
|
||||
|
||||
%\vspace{-0.3cm}
|
||||
\section{Design}
|
||||
%\vspace{-0.3cm}
|
||||
|
||||
The Taler system comprises three principal types of actors
|
||||
(Figure~\ref{fig:cmm}): The \emph{customer} is interested in receiving
|
||||
goods or services from the \emph{merchant} in exchange for payment.
|
||||
When making a transaction, both the customer and the merchant use the
|
||||
same \emph{exchange}, which serves as a payment service provider for
|
||||
the financial transaction between the two. The exchange is
|
||||
responsible for allowing the customer to convert financial reserves to
|
||||
the anonymous digital coins, and for enabling the merchant to convert
|
||||
spent digital coins back to funds in a financial reserve. In
|
||||
addition, we describe an \emph{auditor} who assures customers and
|
||||
merchants that the exchange operates correctly.
|
||||
To pay, the customer {\em spends} digital coins at the merchant. When
|
||||
making a transaction, both the customer and the merchant use the same
|
||||
\emph{exchange}, which serves as a payment service provider for the
|
||||
financial transaction between the two. The exchange is responsible
|
||||
for allowing the customer to withdraw anonymous digital coins from the
|
||||
customer's financial reserves, and for enabling the merchant to
|
||||
deposit digital coins in return for receiving credit at the merchant's
|
||||
financial reserve. In addition, Taler includes an \emph{auditor} who
|
||||
assures customers and merchants that the exchange operates correctly.
|
||||
|
||||
%\vspace{-0.3cm}
|
||||
\subsection{Security model}
|
||||
%\vspace{-0.3cm}
|
||||
|
||||
Taler's security model assumes that cryptographic primitives are
|
||||
secure and that each participant is under full control of his system.
|
||||
The contact information of the exchange is known to both customer and
|
||||
merchant from the start. We further assume that the customer can
|
||||
authenticate the merchant, e.g. using X.509
|
||||
certificates~\cite{rfc5280}. Finally, we assume that customer has an
|
||||
anonymous bi-directional channel, such as Tor, to communicate with
|
||||
both the exchange and the merchant.
|
||||
Taler assumes that each participant has full control over their
|
||||
system. We assume the contact information of the exchange is known to
|
||||
both customer and merchant from the start, including that the customer
|
||||
can authenticate the merchant, for example by using X.509
|
||||
certificates~\cite{rfc6818}. A Taler merchant is trusted to deliver
|
||||
the service or goods to the customer upon receiving payment. The
|
||||
customer can seek legal relief to achieve this, as the customer
|
||||
receives cryptographic evidence of the contract and the associated
|
||||
payment. We assume each Taler customer has an anonymous
|
||||
bi-directional channel, such as Tor, to communicate with both the
|
||||
exchange and the merchant.
|
||||
|
||||
The exchange is trusted to hold funds of its customers and to forward
|
||||
them when receiving the respective deposit instructions from the
|
||||
merchants. Customer and merchant can have assurances about the
|
||||
A Taler exchange is trusted to hold funds of its customers and to
|
||||
forward them when receiving the respective deposit instructions from
|
||||
the merchants. Customer and merchant can have assurances about the
|
||||
exchange's liquidity and operation though published audits by
|
||||
financial regulators or other trusted third parties. If sufficently
|
||||
regular, audits of the exchange's accounts should reveal any possible
|
||||
fraud. Online signing keys expire regularly, allowing the exchange to
|
||||
destroy the corresponding accumulated cryptographic proofs.
|
||||
financial regulators or other trusted third parties. An exchange's
|
||||
signing keys expire regularly, allowing the exchange to eventually
|
||||
destroy the corresponding accumulated cryptographic proofs, and
|
||||
limiting the exchange's financial liability.
|
||||
|
||||
The merchant is trusted to deliver the service or goods to the
|
||||
customer upon receiving payment. The customer can seek legal relief
|
||||
to achieve this, as he receives cryptographic proofs of the contract
|
||||
and has proof that he paid his obligations.
|
||||
On the cryptographic side, a Taler exchange demands that coins use a
|
||||
full domain hash (FDH) to make so-called ``one-more forgery'' attacks
|
||||
provably hard, assuming the RSA known-target inversion problem is
|
||||
hard~\cite[Theorem 12]{RSA-HDF-KTIvCTI}. For a withdrawn coin,
|
||||
violating the customers anonymity cryptographily requires recognizing
|
||||
a random blinding factor from a random element of the group of
|
||||
integers modulo the denomination key's RSA modulus, which appears
|
||||
impossible even with a quantum computers. For a refreshed coin,
|
||||
unlinkabiltiy requires the hardness of the discrete logarithm for
|
||||
Curve25519.
|
||||
|
||||
The cut-and-choose protocol prevents merchants and customers from
|
||||
conspiring to conceal a merchants income. We assume that the maximum
|
||||
tax rate is below $1/\kappa$, and that expected transaction losses of
|
||||
a factor of $\kappa$ for tax evasion are thus unacceptable.
|
||||
|
||||
Neither the merchant nor the customer have any ability to {\em effectively}
|
||||
defraud the exchange or the state collecting taxes. Here, ``effectively''
|
||||
means that the expected return for fraud is negative.
|
||||
%
|
||||
Note that customers do not need to be trusted in any way, and that in
|
||||
particular it is never necessary for anyone to try to recover funds
|
||||
from customers using legal coersion.
|
||||
|
||||
\subsection{Taxability and Entities}
|
||||
|
||||
@ -396,15 +416,14 @@ could spend the associated funds. Assuming the payment system has
|
||||
effective double-spending detection, this means that either entity has
|
||||
to constantly fear that the funds might no longer be available to it.
|
||||
It follows that sharing coins by copying a private key implies mutual
|
||||
trust between the two parties, in which case we treat them as the same
|
||||
entity for taxability.
|
||||
trust between the two parties.
|
||||
|
||||
In Taler, making funds available by copying a private key and thus
|
||||
sharing control is {\bf not} considered a {\em transaction} and thus
|
||||
{\bf not} recorded for taxation. Taler does, however, ensure
|
||||
taxability when a merchant entity acquires exclusive control over the
|
||||
value represented by a digital coins. For such transactions, the state
|
||||
can obtain information from the exchange, or a bank, that identifies
|
||||
can obtain information from the exchange that identifies
|
||||
the entity that received the digital coins as well as the exact value
|
||||
of those coins. Taler also allows the exchange, and hence the state,
|
||||
to learn the value of digital coins withdrawn by a customer---but not
|
||||
@ -439,7 +458,7 @@ is unable to link the known identity of the customer that withdrew
|
||||
anonymous digital coins to the {\em purchase} performed later at the
|
||||
merchant.
|
||||
|
||||
While the customer thus has anonymity for purchases, the exchange will
|
||||
While the customer thus has untraceability for purchases, the exchange will
|
||||
always learn the merchant's identity in order to credit the merchant's
|
||||
account. This is also necessary for taxation, as Taler deliberately
|
||||
exposes these events as anchors for tax audits on income.
|
||||
@ -467,31 +486,30 @@ exposes these events as anchors for tax audits on income.
|
||||
|
||||
A \emph{coin} in Taler is a public-private key pair where the private
|
||||
key is only known to the owner of the coin. A coin derives its
|
||||
financial value from an RSA signature over a the full domain hash
|
||||
(FDH) of the coin's public key. An FDH is used so that ``one-more
|
||||
forgery'' is provably hard assuming the RSA known-target inversion
|
||||
problem is hard~cite[Theorem 12]{RSA-HDF-KTIvCTI}. The exchange has
|
||||
multiple RSA {\em denomination key} pairs available for blind-signing
|
||||
coins of different value.
|
||||
financial value from an RSA signature over the FDH
|
||||
of the coin's public key. The exchange has multiple RSA {\em
|
||||
denomination key} pairs available for blind-signing coins of
|
||||
different value.
|
||||
|
||||
Denomination keys have an expiration date, before which any coins
|
||||
signed with it must be spent or refreshed. This allows the exchange
|
||||
to eventually discard records of old transactions, thus limiting the
|
||||
records that the exchange must retain and search to detect
|
||||
double-spending attempts. Furthermore, the exchange uses each
|
||||
denomination key only for a limited number of coins. In this way, if
|
||||
a private denomination key were to be compromised, the exchange would
|
||||
detect this once more coins were redeemed than the total that was
|
||||
signed into existence using that denomination key. In this case, the
|
||||
exchange can allow authentic customers to exchange their unspent
|
||||
coins that were signed with the compromised private key, while
|
||||
refusing further anonymous transactions involving those coins. As a
|
||||
result, the financial damage of losing a private signing key can be
|
||||
limited to at most twice the amount originally signed with that key.
|
||||
double-spending attempts. If a private denomination key were to be
|
||||
compromised, the exchange can detect this once more coins are redeemed
|
||||
than the total that was signed into existence using that denomination
|
||||
key. In this case, the exchange can allow authentic customers to
|
||||
redeem their unspent coins that were signed with the compromised
|
||||
private key, while refusing further deposits involving coins signed by
|
||||
the compromised denomination key. As a result, the financial damage
|
||||
of losing a private signing key is limited to at most the amount
|
||||
originally signed with that key, and denomination key rotation can be
|
||||
used to bound that risk.
|
||||
|
||||
We also ensure that the exchange cannot deanonymize users by signing
|
||||
We ensure that the exchange cannot deanonymize users by signing
|
||||
each coin with a fresh denomination key. For this, exchanges are
|
||||
required to publicly announce their denomination keys in advance.
|
||||
required to publicly announce their denomination keys in advance
|
||||
with validity periods that imply sufficiently strong anonymity sets.
|
||||
These announcements are expected to be signed with an off-line
|
||||
long-term private {\em master signing key} of the exchange and the
|
||||
auditor. Additionally, customers should obtain these announcements
|
||||
@ -515,10 +533,12 @@ withdrawal message as proof that the reserve was debited correctly.
|
||||
|
||||
After a coin is issued, the customer is the only entity that knows the
|
||||
private key of the coin, making him the \emph{owner} of the coin. Due
|
||||
to the use of blind signatures, the exchange does not even learn the
|
||||
to the use of blind signatures, the exchange does not learn the
|
||||
public key during the withdrawal process. If the private key is
|
||||
shared with others, they become co-owners of the coin. Knowledge of
|
||||
the private key of the coin enables the owner to spent the coin.
|
||||
the private key of the coin and the signature over the coin's public
|
||||
key by an exchange's denomination key enables spending the
|
||||
coin.
|
||||
|
||||
|
||||
% \subsection{Coin spending}
|
||||
@ -612,9 +632,9 @@ purposes. The exchange's bank transfers dealing in traditional currency
|
||||
are expected to be recorded for tax authorities to ensure taxability.
|
||||
% FIXME: Auditor?
|
||||
|
||||
We use RSA for denomination keys and EdDSA over some eliptic curve
|
||||
$\mathbb{E}$ for all other keys. Let $G$ denote the generator of
|
||||
our elliptic curve $\mathbb{E}$.
|
||||
$S_K$ denotes RSA signing with denomination key $K$ and EdDSA
|
||||
over eliptic curve $\mathbb{E}$ for other types of keys.
|
||||
$G$ denotes the generator of elliptic curve $\mathbb{E}$.
|
||||
|
||||
\subsection{Withdrawal}
|
||||
|
||||
@ -639,25 +659,25 @@ Now the customer carries out the following interaction with the exchange:
|
||||
\item coin key $C := (c_s,C_p)$ with private key $c_s$ and public key $C_p := c_s G$,
|
||||
\item blinding factor $b$, and commits $\langle W, C, b \rangle$ to disk.
|
||||
\end{itemize}
|
||||
\item[SEPA Send]
|
||||
\item[Wire transfer send]
|
||||
The customer transfers an amount of money corresponding to
|
||||
at least $K_v$ to the exchange, with $W_p$ in the subject line
|
||||
of the transaction.
|
||||
\item[SEPA Recieve]
|
||||
\item[Wire transfer recieve]
|
||||
The exchange receives the transaction and credits the reserve $W_p$
|
||||
with the respective amount in its database.
|
||||
\item[POST {\tt /withdraw/sign}]
|
||||
The customer sends $S_W(B)$ where $B := B_b(\FDH_K(C_p))$ to
|
||||
the exchange to request withdrawal of $C$; here, $B_b$ denotes
|
||||
Chaum-style blinding with blinding factor $b$.
|
||||
\item[200 OK / 402 PAYMENT REQUIRED]
|
||||
\item[200 OK / 403 FORBIDDEN]
|
||||
The exchange checks if the same withdrawal request was issued before;
|
||||
in this case, it sends a Chaum-style blind signature $S_K(B)$ with
|
||||
private key $K_s$ to the customer. \\
|
||||
If this is a fresh withdrawal request, the exchange performs the following transaction:
|
||||
\begin{enumerate}
|
||||
\item checks if the reserve $W_p$ has sufficient funds
|
||||
for a coin of value corresponding to $K$
|
||||
for a coin of value corresponding to $K$,
|
||||
\item stores the withdrawal request and response
|
||||
$\langle S_W(B), S_K(B) \rangle$ in its database
|
||||
for future reference,
|
||||
@ -668,9 +688,8 @@ Now the customer carries out the following interaction with the exchange:
|
||||
error back to the customer, with proof that it operated correctly.
|
||||
Assuming the signature was valid, this would involve showing the transaction
|
||||
history for the reserve.
|
||||
% FIXME: Is it really the whole history?
|
||||
\item[Done] The customer computes and verifies the unblinded signature
|
||||
$S_K(\FDH_K{C_p}) = U_b(S_K(B))$.
|
||||
$S_K(\FDH_K(C_p)) = U_b(S_K(B))$.
|
||||
Finally the customer saves the coin $\langle S_K(\FDH_K(C_p)), c_s \rangle$
|
||||
to their local wallet on disk.
|
||||
\end{description}
|
||||
@ -681,9 +700,9 @@ Now the customer carries out the following interaction with the exchange:
|
||||
A customer can spend coins at a merchant, under the condition that the
|
||||
merchant trusts the exchange that issued the coin.
|
||||
% FIXME: Auditor here?
|
||||
Merchants are identified by their public key $M_p = m_s G$ which the
|
||||
Merchants are identified by their public key $M_p$ which the
|
||||
customer's wallet learns through the merchant's webpage, which itself
|
||||
must be authenticated with X.509c.
|
||||
should be authenticated with X.509c.
|
||||
% FIXME: Is this correct?
|
||||
|
||||
We now describe the protocol between the customer, merchant, and exchange
|
||||
@ -702,35 +721,37 @@ with signature $\widetilde{C} := S_K(\FDH_K(C_p))$
|
||||
\item[Proposal]
|
||||
The merchant creates a digitally signed contract
|
||||
$\mathcal{A} := S_M(m, f, a, H(p, r), \vec{X})$
|
||||
where $m$ is an identifier for this transaction, $a$ is data relevant
|
||||
where $m$ is an identifier for this transaction, $f$ is the price of the offer,
|
||||
and $a$ is data relevant
|
||||
to the contract indicating which services or goods the merchant will
|
||||
deliver to the customer, $f$ is the price of the offer, and
|
||||
deliver to the customer, including the {\tt /merchant-specific} URI for the payment.
|
||||
$p$ is the merchant's payment information (e.g. his IBAN number), and
|
||||
$r$ is a random nonce. The merchant commits $\langle \mathcal{A} \rangle$
|
||||
to disk and sends $\mathcal{A}$ to the customer.
|
||||
\item[Customer Setup]
|
||||
The customer should already possess a coin issued by a exchange that is
|
||||
accepted by the merchant, meaning $K$ should be publicly signed by
|
||||
The customer should already possess a coin $\widetilde{C}$ issued by a exchange that is
|
||||
accepted by the merchant, meaning $K$ of $\widetilde{C}$ should be publicly signed by
|
||||
some $X_j$ from $\vec{X}$, and has a value $\geq f$.
|
||||
\item[POST {\tt /???}] \label{deposit}
|
||||
\item[POST {\tt /merchant-specific}]
|
||||
Let $X_j$ be the exchange which signed $\widetilde{C}$ with $K$.
|
||||
The customer generates a \emph{deposit-permission}
|
||||
$\mathcal{D} := S_c(\widetilde{C}, m, f, H(a), H(p,r), M_p)$
|
||||
and sends $\langle \mathcal{D}, X_j\rangle$ to the merchant,
|
||||
where $X_j$ is the exchange which signed $K$.
|
||||
and sends $\langle \mathcal{D}, X_j\rangle$ to the merchant.
|
||||
\item[POST {\tt/deposit}]
|
||||
The merchant gives $(\mathcal{D}, p, r)$ to the exchange, thereby
|
||||
revealing $p$ only to the exchange.
|
||||
\item[200 OK / 409 CONFLICT]
|
||||
\item[200 OK / 403 FORBIDDEN]
|
||||
The exchange validates $\mathcal{D}$ and checks for double spending.
|
||||
If the coin has been involved in previous transactions and the new
|
||||
one would exceed its remaining value, it sends an error
|
||||
one would exceed its remaining value, it sends a ``403 FORBIDDEN'' error
|
||||
with the records from the previous transactions back to the merchant. \\
|
||||
%
|
||||
If double spending is not found, the exchange commits $\langle \mathcal{D} \rangle$ to disk
|
||||
and notifies the merchant that the deposit operation was successful.
|
||||
\item[200 OK / ???]
|
||||
and signs a ``200 OK'' message affirming the deposit operation was successful.
|
||||
\item[200 OK / 424 FAILED DEPENDENCY]
|
||||
The merchant commits and forwards the notification from the exchange to the
|
||||
customer, confirming the success or failure of the operation.
|
||||
customer, confirming the success (``200 OK'') or failure (``424 FAILED DEPENDENCY'')
|
||||
of the operation.
|
||||
\end{description}
|
||||
|
||||
We have simplified the exposition by assuming that one coin suffices,
|
||||
@ -738,12 +759,12 @@ but in practice a customer can use multiple coins from the same
|
||||
exchange where the total value adds up to $f$ by running the above
|
||||
steps for each of the coins.
|
||||
|
||||
If a transaction is aborted after Step~\ref{deposit},
|
||||
subsequent transactions with the same coin could be linked to the coin,
|
||||
but not directly to the coin's owner. The same applies to partially
|
||||
spent coins where $f$ is smaller than the actual value of the coin.
|
||||
To unlink subsequent transactions from a coin, the customer has to
|
||||
execute the coin refreshing protocol with the exchange.
|
||||
If a transaction is aborted after the first POST, subsequent
|
||||
transactions with the same coin could be linked to this operation.
|
||||
The same applies to partially spent coins where $f$ is smaller than
|
||||
the actual value of the coin. To unlink subsequent transactions from
|
||||
a coin, the customer has to execute the following coin refreshing
|
||||
protocol with the exchange.
|
||||
|
||||
%\begin{figure}[h]
|
||||
%\centering
|
||||
@ -785,17 +806,17 @@ denomination $K$ is melted to obtain a fresh coin $\widetilde{C}$
|
||||
with the same denomination. In practice, Taler uses a natural
|
||||
extension where multiple fresh coins are generated a the same time to
|
||||
enable giving precise change matching any amount.
|
||||
In the protocol, $\kappa \ge 3$ is a security parameter for the
|
||||
cut-and-choose part of the protocol and $G$ is the
|
||||
generator of the elliptic curve.
|
||||
|
||||
We note that $\kappa = 3$ is actually perfectly sufficient in most
|
||||
cases in practice, as the cut-and-choose protocol does not need to
|
||||
provide cryptographic security: If the maximum applicable tax is less
|
||||
than $\frac{2}{3}$, then detecting $\kappa = 3$ ensures that cheating
|
||||
results in a negative return on average as $\kappa - 1$ out of
|
||||
$\kappa$ attempts to cheat are detected. This makes the use of
|
||||
cut-and-choose practical and efficient in this context.
|
||||
In the protocol, $\kappa \ge 2$ is a security parameter for the
|
||||
cut-and-choose part of the protocol. $\kappa = 3$ is actually
|
||||
perfectly sufficient in most cases in practice, as the cut-and-choose
|
||||
protocol does not need to provide cryptographic security: If the
|
||||
maximum applicable tax is less than $\frac{2}{3}$, then $\kappa = 3$
|
||||
ensures that cheating results in a negative financial return on
|
||||
average as $\kappa - 1$ out of $\kappa$ attempts to hide from taxation
|
||||
are detected and penalized by a total loss. This makes our use of
|
||||
cut-and-choose practical and efficient, and in particularly faster
|
||||
than the comparable use of zk-SNARKs in ZeroCash~\cite{zerocash}.
|
||||
|
||||
% FIXME: I'm explicit about the rounds in postquantum.tex
|
||||
|
||||
@ -805,16 +826,16 @@ cut-and-choose practical and efficient in this context.
|
||||
a transfer private key $t^{(i)}_s$ and computes
|
||||
\begin{itemize}
|
||||
\item the transfer public key $T^{(i)}_p := t^{(i)}_s G$ and
|
||||
\item the new coin secret seed $L_i := H(c'_s T_p^{(i)})$.
|
||||
\item the new coin secret seed $L^{(i)} := H(c'_s T_p^{(i)})$.
|
||||
\end{itemize}
|
||||
We have computed $L_i$ as a Diffie-Hellman shared secret between
|
||||
the transfer key pair $T^{(i)} := \left(t^{(i)}_s,T^{(i)}_p\right)$
|
||||
and old coin key pair $C' := \left(c_s', C_p'\right)$;
|
||||
as a result, $L_i = H(t^{(i)}_s C'_p)$ also holds.
|
||||
Now the customer applies key derivation functions $\KDF_?$ to $L_i$ to generate
|
||||
as a result, $L^{(i)} = H(t^{(i)}_s C'_p)$ also holds.
|
||||
Now the customer applies key derivation functions $\KDF_{\textrm{blinding}}$ and $\KDF_{\textrm{Ed25519}}$ to $L^{(i)}$ to generate
|
||||
\begin{itemize}
|
||||
\item a blinding factor $b^{(i)} = \FDH_K(\KDF_{\textrm{blinding}}(L_i))$.
|
||||
\item $c_s^{(i)} = \KDF_{\textrm{Ed25519}}(L_i)$
|
||||
\item a blinding factor $b^{(i)} = \FDH_K(\KDF_{\textrm{blinding}}(L^{(i)}))$.
|
||||
\item $c_s^{(i)} = \KDF_{\textrm{Ed25519}}(L^{(i)})$
|
||||
\end{itemize}
|
||||
Now the customer can compute her new coin key pair
|
||||
$C^{(i)} := \left(c_s^{(i)}, C_p^{(i)}\right)$
|
||||
@ -837,7 +858,7 @@ cut-and-choose practical and efficient in this context.
|
||||
this time to prevent the exchange from assisting tax evasion. \\
|
||||
%
|
||||
The exchange sends $S_{K'}(C'_p, \gamma)$ to the customer where
|
||||
$K'$ is the exchange's message signing key.
|
||||
$K'$ is the exchange's message signing key, thereby commmitting the exchange to $\gamma$.
|
||||
\item[POST {\tt /refresh/reveal}]
|
||||
The customer commits $\langle C', S_K(C'_p, \gamma) \rangle$ to disk.
|
||||
Also, the customer assembles
|
||||
@ -850,16 +871,16 @@ cut-and-choose practical and efficient in this context.
|
||||
\vspace{-2ex}
|
||||
\begin{minipage}{5cm}
|
||||
\begin{align*}
|
||||
\overline{L}_i :&= H(t_s^{(i)} C_p') \\
|
||||
\overline{c}_s^{(i)} :&= \KDF_{\textrm{Ed25519}}(\overline{L}_i) \\
|
||||
\overline{C^{(i)}_p} :&= \overline{c}_s^{(i)} G
|
||||
\overline{L^{(i)}} :&= H(t_s^{(i)} C_p') \\
|
||||
\overline{c_s^{(i)}} :&= \KDF_{\textrm{Ed25519}}(\overline{L^{(i)}}) \\
|
||||
\overline{C^{(i)}_p} :&= \overline{c_s^{(i)}} G
|
||||
\end{align*}
|
||||
\end{minipage}
|
||||
\begin{minipage}{5cm}
|
||||
\begin{align*}
|
||||
\overline{T_p^{(i)}} :&= t_s^{(i)} G \\
|
||||
\overline{b}^{(i)} :&= \FDH_K(\KDF_{\textrm{blinding}}(\overline{L}_i)) \\
|
||||
\overline{B^{(i)}} :&= B_{\overline{b_i}}(\overline{C_p^{(i)}})
|
||||
\overline{b^{(i)}} :&= \FDH_K(\KDF_{\textrm{blinding}}(\overline{L^{(i)}})) \\
|
||||
\overline{B^{(i)}} :&= B_{\overline{b^{(i)}}}(\overline{C_p^{(i)}})
|
||||
\end{align*}
|
||||
\end{minipage}
|
||||
|
||||
@ -909,7 +930,7 @@ taxation model as with such trust they are assumed to be the same
|
||||
entity.
|
||||
|
||||
The auditor can anonymously check if the exchange correctly implements the
|
||||
link request, thus preventing the exchange operator from legally disabling
|
||||
link request, thus preventing the exchange operator from secretly disabling
|
||||
this protocol component. Without the link operation, Taler would
|
||||
devolve into a payment system where both sides can be anonymous, and
|
||||
thus no longer provide taxability.
|
||||
@ -942,13 +963,12 @@ faulty exchange.
|
||||
The third case are transient failures, such as network failures or
|
||||
temporary hardware failures at the exchange service provider. Here, the
|
||||
client may receive an explicit protocol indication, such as an HTTP
|
||||
response code 500 ``internal server error'' or simply no response.
|
||||
response code ``500 INTERNAL SERVER ERROR'' or simply no response.
|
||||
The appropriate behavior for the client is to automatically retry
|
||||
after 1s, and twice more at randomized times within 1 minute.
|
||||
If those three attempts fail, the user should be informed about the
|
||||
delay. The client should then retry another three times within the
|
||||
next 24h, and after that time the auditor be informed about the outage.
|
||||
|
||||
next 24h, and after that time the auditor should be informed about the outage.
|
||||
Using this process, short term failures should be effectively obscured
|
||||
from the user, while malicious behavior is reported to the auditor who
|
||||
can then presumably rectify the situation, using methods such as
|
||||
@ -1041,7 +1061,7 @@ At network latencies above 10 ms, the delay
|
||||
for executing a transaction is dominated by the network latency, as
|
||||
local processing virtually always takes less than 10 ms.
|
||||
|
||||
Database transactions are dominated by writes
|
||||
Database transactions are dominated by writes%
|
||||
%(Figure~\ref{fig:read} vs. Figure~\ref{fig:write})
|
||||
, as Taler mostly needs to log
|
||||
transactions and occasionally needs to read to guard against
|
||||
@ -1092,7 +1112,7 @@ actually facilitates voluntary cooperation between the exchange and
|
||||
criminals~\cite{sander1999escrow} and where the state could
|
||||
deanonymize citizens.
|
||||
|
||||
\subsection{Offline Payments}
|
||||
%\subsection{Offline Payments}
|
||||
|
||||
Chaum's original proposals for anonymous digital cash avoided the need
|
||||
for online interactions with the exchange to detect double spending by
|
||||
@ -1115,7 +1135,7 @@ coin after restoring from backup.
|
||||
%subjected to financial penalties by the state in relation to the
|
||||
%amount transferred by the traditional currency transfer.
|
||||
|
||||
\subsection{Cryptographic proof vs. evidence}
|
||||
% \subsection{Cryptographic proof vs. evidence}
|
||||
|
||||
In this paper we have use the term ``proof'' in many places as the
|
||||
protocol provides cryptographic proofs of which parties behave
|
||||
@ -1167,11 +1187,11 @@ the participants have to disclose their core secrets.
|
||||
\bibliographystyle{alpha}
|
||||
\bibliography{taler,rfc}
|
||||
|
||||
\vfill
|
||||
\begin{center}
|
||||
\Large Demonstration available at \url{https://demo.taler.net/}
|
||||
\end{center}
|
||||
\vfill
|
||||
%\vfill
|
||||
%\begin{center}
|
||||
% \Large Demonstration available at \url{https://demo.taler.net/}
|
||||
%\end{center}
|
||||
%\vfill
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
@ -1241,13 +1261,13 @@ data being committed to disk are represented in between $\langle\rangle$.
|
||||
\item[$\vec{b}$]{Vector of $b^{(i)}$}
|
||||
\item[$B^{(i)}$]{Blinding of $C_p^{(i)}$}
|
||||
\item[$\vec{B}$]{Vector of $B^{(i)}$}
|
||||
\item[$L_i$]{Link secret derived from ECDH operation via hashing}
|
||||
% \item[$E_{L_i}()$]{Symmetric encryption using key $L_i$}
|
||||
\item[$L^{(i)}$]{Link secret derived from ECDH operation via hashing}
|
||||
% \item[$E_{L^{(i)}}()$]{Symmetric encryption using key $L^{(i)}$}
|
||||
% \item[$E^{(i)}$]{$i$-th encryption of the private information $(c_s^{(i)}, b_i)$}
|
||||
% \item[$\vec{E}$]{Vector of $E^{(i)}$}
|
||||
\item[$\cal{R}$]{Tuple of revealed vectors in cut-and-choose protocol,
|
||||
where the vectors exclude the selected index $\gamma$}
|
||||
\item[$\overline{L_i}$]{Link secrets derived by the verifier from DH}
|
||||
\item[$\overline{L^{(i)}}$]{Link secrets derived by the verifier from DH}
|
||||
\item[$\overline{B^{(i)}}$]{Blinded values derived by the verifier}
|
||||
\item[$\overline{T_p^{(i)}}$]{Public transfer keys derived by the verifier from revealed private keys}
|
||||
\item[$\overline{c_s^{(i)}}$]{Private keys obtained from decryption by the verifier}
|
||||
|
1
gnunet
Submodule
1
gnunet
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 674d59da9956998c0e33ad1a3aa9facc3ba66d10
|
122
m4/libgcrypt.m4
Normal file
122
m4/libgcrypt.m4
Normal file
@ -0,0 +1,122 @@
|
||||
dnl Autoconf macros for libgcrypt
|
||||
dnl Copyright (C) 2002, 2004, 2011 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This file is free software; as a special exception the author gives
|
||||
dnl unlimited permission to copy and/or distribute it, with or without
|
||||
dnl modifications, as long as this notice is preserved.
|
||||
dnl
|
||||
dnl This file is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
|
||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
|
||||
dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
|
||||
dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
|
||||
dnl with the API version to also check the API compatibility. Example:
|
||||
dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
|
||||
dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using
|
||||
dnl this features allows to prevent build against newer versions of libgcrypt
|
||||
dnl with a changed API.
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_LIBGCRYPT],
|
||||
[ AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_ARG_WITH(libgcrypt-prefix,
|
||||
AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
|
||||
[prefix where LIBGCRYPT is installed (optional)]),
|
||||
libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
|
||||
if test x$libgcrypt_config_prefix != x ; then
|
||||
if test x${LIBGCRYPT_CONFIG+set} != xset ; then
|
||||
LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no)
|
||||
tmp=ifelse([$1], ,1:1.2.0,$1)
|
||||
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
|
||||
req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
|
||||
min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
|
||||
else
|
||||
req_libgcrypt_api=0
|
||||
min_libgcrypt_version="$tmp"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
|
||||
ok=no
|
||||
if test "$LIBGCRYPT_CONFIG" != "no" ; then
|
||||
req_major=`echo $min_libgcrypt_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
|
||||
req_minor=`echo $min_libgcrypt_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
|
||||
req_micro=`echo $min_libgcrypt_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
|
||||
libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
|
||||
major=`echo $libgcrypt_config_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
|
||||
minor=`echo $libgcrypt_config_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
|
||||
micro=`echo $libgcrypt_config_version | \
|
||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
|
||||
if test "$major" -gt "$req_major"; then
|
||||
ok=yes
|
||||
else
|
||||
if test "$major" -eq "$req_major"; then
|
||||
if test "$minor" -gt "$req_minor"; then
|
||||
ok=yes
|
||||
else
|
||||
if test "$minor" -eq "$req_minor"; then
|
||||
if test "$micro" -ge "$req_micro"; then
|
||||
ok=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test $ok = yes; then
|
||||
AC_MSG_RESULT([yes ($libgcrypt_config_version)])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
if test $ok = yes; then
|
||||
# If we have a recent libgcrypt, we should also check that the
|
||||
# API is compatible
|
||||
if test "$req_libgcrypt_api" -gt 0 ; then
|
||||
tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
|
||||
if test "$tmp" -gt 0 ; then
|
||||
AC_MSG_CHECKING([LIBGCRYPT API version])
|
||||
if test "$req_libgcrypt_api" -eq "$tmp" ; then
|
||||
AC_MSG_RESULT([okay])
|
||||
else
|
||||
ok=no
|
||||
AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test $ok = yes; then
|
||||
LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
|
||||
LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
|
||||
ifelse([$2], , :, [$2])
|
||||
libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
|
||||
if test x"$libgcrypt_config_host" != xnone ; then
|
||||
if test x"$libgcrypt_config_host" != x"$host" ; then
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** The config script $LIBGCRYPT_CONFIG was
|
||||
*** built for $libgcrypt_config_host and thus may not match the
|
||||
*** used host $host.
|
||||
*** You may want to use the configure option --with-libgcrypt-prefix
|
||||
*** to specify a matching config script.
|
||||
***]])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
LIBGCRYPT_CFLAGS=""
|
||||
LIBGCRYPT_LIBS=""
|
||||
ifelse([$3], , :, [$3])
|
||||
fi
|
||||
AC_SUBST(LIBGCRYPT_CFLAGS)
|
||||
AC_SUBST(LIBGCRYPT_LIBS)
|
||||
])
|
@ -12,7 +12,8 @@ pkgcfg_DATA = \
|
||||
auditordb-postgres.conf
|
||||
|
||||
EXTRA_DIST = \
|
||||
auditordb-postgres.conf
|
||||
auditordb-postgres.conf \
|
||||
test-auditor-db-postgres.conf
|
||||
|
||||
plugindir = $(libdir)/taler
|
||||
|
||||
@ -49,5 +50,21 @@ libtalerauditordb_la_LDFLAGS = \
|
||||
-no-undefined
|
||||
|
||||
|
||||
EXTRA_test_auditordb_postgres_DEPENDENCIES = \
|
||||
libtaler_plugin_auditordb_postgres.la
|
||||
#EXTRA_test_auditordb_postgres_DEPENDENCIES = \
|
||||
# libtaler_plugin_auditordb_postgres.la
|
||||
|
||||
|
||||
check_PROGRAMS = \
|
||||
test-auditordb-postgres
|
||||
|
||||
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
|
||||
TESTS = \
|
||||
test-auditordb-postgres
|
||||
|
||||
test_auditordb_postgres_SOURCES = \
|
||||
test_auditordb.c
|
||||
test_auditordb_postgres_LDADD = \
|
||||
libtalerauditordb.la \
|
||||
$(top_srcdir)/src/pq/libtalerpq.la \
|
||||
$(top_srcdir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil
|
||||
|
File diff suppressed because it is too large
Load Diff
7
src/auditordb/test-auditor-db-postgres.conf
Normal file
7
src/auditordb/test-auditor-db-postgres.conf
Normal file
@ -0,0 +1,7 @@
|
||||
[auditor]
|
||||
# Which database backend do we use for the auditor?
|
||||
DB = postgres
|
||||
|
||||
[auditordb-postgres]
|
||||
# Argument for Postgres for how to connect to the database.
|
||||
DB_CONN_STR = "postgres:///talercheck"
|
798
src/auditordb/test_auditordb.c
Normal file
798
src/auditordb/test_auditordb.c
Normal file
@ -0,0 +1,798 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016 GNUnet e.V. and INRIA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file auditordb/test_auditordb.c
|
||||
* @brief test cases for DB interaction functions
|
||||
* @author Gabor X Toth
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_auditordb_lib.h"
|
||||
#include "taler_auditordb_plugin.h"
|
||||
|
||||
|
||||
/**
|
||||
* Global result from the testcase.
|
||||
*/
|
||||
static int result = -1;
|
||||
|
||||
/**
|
||||
* Report line of error if @a cond is true, and jump to label "drop".
|
||||
*/
|
||||
#define FAILIF(cond) \
|
||||
do { \
|
||||
if (!(cond)){ break;} \
|
||||
GNUNET_break (0); \
|
||||
goto drop; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Initializes @a ptr with random data.
|
||||
*/
|
||||
#define RND_BLK(ptr) \
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
|
||||
|
||||
/**
|
||||
* Initializes @a ptr with zeros.
|
||||
*/
|
||||
#define ZR_BLK(ptr) \
|
||||
memset (ptr, 0, sizeof (*ptr))
|
||||
|
||||
|
||||
/**
|
||||
* Currency we use.
|
||||
*/
|
||||
#define CURRENCY "EUR"
|
||||
|
||||
/**
|
||||
* Database plugin under test.
|
||||
*/
|
||||
static struct TALER_AUDITORDB_Plugin *plugin;
|
||||
|
||||
|
||||
/**
|
||||
* Main function that will be run by the scheduler.
|
||||
*
|
||||
* @param cls closure with config
|
||||
*/
|
||||
static void
|
||||
run (void *cls)
|
||||
{
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
|
||||
struct TALER_AUDITORDB_Session *session;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"loading database plugin\n");
|
||||
|
||||
if (NULL ==
|
||||
(plugin = TALER_AUDITORDB_plugin_load (cfg)))
|
||||
{
|
||||
result = 77;
|
||||
return;
|
||||
}
|
||||
|
||||
(void) plugin->drop_tables (plugin->cls);
|
||||
if (GNUNET_OK !=
|
||||
plugin->create_tables (plugin->cls))
|
||||
{
|
||||
result = 77;
|
||||
goto drop;
|
||||
}
|
||||
if (NULL ==
|
||||
(session = plugin->get_session (plugin->cls)))
|
||||
{
|
||||
result = 77;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"initializing\n");
|
||||
|
||||
struct TALER_Amount value, fee_withdraw, fee_deposit, fee_refresh, fee_refund;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
||||
&value));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000011",
|
||||
&fee_withdraw));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000012",
|
||||
&fee_deposit));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000013",
|
||||
&fee_refresh));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":0.000014",
|
||||
&fee_refund));
|
||||
|
||||
struct TALER_MasterPublicKeyP master_pub;
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
struct GNUNET_HashCode rnd_hash;
|
||||
RND_BLK (&master_pub);
|
||||
RND_BLK (&reserve_pub);
|
||||
RND_BLK (&rnd_hash);
|
||||
|
||||
struct TALER_DenominationPrivateKey denom_priv;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
struct GNUNET_HashCode denom_pub_hash;
|
||||
denom_priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (1024);
|
||||
denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (denom_priv.rsa_private_key);
|
||||
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, &denom_pub_hash);
|
||||
|
||||
struct GNUNET_TIME_Absolute now, past, future, date;
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
past = GNUNET_TIME_absolute_subtract (now,
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
|
||||
4));
|
||||
future = GNUNET_TIME_absolute_add (now,
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
|
||||
4));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_denomination_info\n");
|
||||
|
||||
struct TALER_DenominationKeyValidityPS issue = { 0 };
|
||||
issue.master = master_pub;
|
||||
issue.denom_hash = denom_pub_hash;
|
||||
|
||||
issue.start = GNUNET_TIME_absolute_hton (now);
|
||||
issue.expire_withdraw = GNUNET_TIME_absolute_hton
|
||||
(GNUNET_TIME_absolute_add (now,
|
||||
GNUNET_TIME_UNIT_HOURS));
|
||||
issue.expire_deposit = GNUNET_TIME_absolute_hton
|
||||
(GNUNET_TIME_absolute_add
|
||||
(now,
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 2)));
|
||||
issue.expire_legal = GNUNET_TIME_absolute_hton
|
||||
(GNUNET_TIME_absolute_add
|
||||
(now,
|
||||
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3)));
|
||||
TALER_amount_hton (&issue.value, &value);
|
||||
TALER_amount_hton (&issue.fee_withdraw, &fee_withdraw);
|
||||
TALER_amount_hton (&issue.fee_deposit, &fee_deposit);
|
||||
TALER_amount_hton (&issue.fee_refresh, &fee_refresh);
|
||||
TALER_amount_hton (&issue.fee_refund, &fee_refund);
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_denomination_info (plugin->cls,
|
||||
session,
|
||||
&issue));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: select_denomination_info\n");
|
||||
|
||||
int
|
||||
select_denomination_info_result (void *cls,
|
||||
const struct TALER_DenominationKeyValidityPS *issue2)
|
||||
{
|
||||
const struct TALER_DenominationKeyValidityPS *issue1 = cls;
|
||||
|
||||
if (0 != memcmp (issue1, issue2, sizeof (*issue2)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"select_denomination_info_result: issue does not match\n");
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_denomination_info (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
select_denomination_info_result,
|
||||
&issue));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_auditor_progress\n");
|
||||
|
||||
uint64_t
|
||||
last_reserve_in_serial_id = 1234,
|
||||
last_reserve_out_serial_id = 5678,
|
||||
last_deposit_serial_id = 123,
|
||||
last_melt_serial_id = 456,
|
||||
last_refund_serial_id = 789,
|
||||
last_prewire_serial_id = 555,
|
||||
|
||||
last_reserve_in_serial_id2 = 0,
|
||||
last_reserve_out_serial_id2 = 0,
|
||||
last_deposit_serial_id2 = 0,
|
||||
last_melt_serial_id2 = 0,
|
||||
last_refund_serial_id2 = 0,
|
||||
last_prewire_serial_id2 = 0;
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_auditor_progress (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
last_reserve_in_serial_id,
|
||||
last_reserve_out_serial_id,
|
||||
last_deposit_serial_id,
|
||||
last_melt_serial_id,
|
||||
last_refund_serial_id,
|
||||
last_prewire_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_auditor_progress\n");
|
||||
|
||||
last_reserve_in_serial_id++;
|
||||
last_reserve_out_serial_id++;
|
||||
last_deposit_serial_id2++;
|
||||
last_melt_serial_id2++;
|
||||
last_refund_serial_id2++;
|
||||
last_prewire_serial_id2++;
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_auditor_progress (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
last_reserve_in_serial_id,
|
||||
last_reserve_out_serial_id,
|
||||
last_deposit_serial_id,
|
||||
last_melt_serial_id,
|
||||
last_refund_serial_id,
|
||||
last_prewire_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_auditor_progress\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_auditor_progress (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&last_reserve_in_serial_id2,
|
||||
&last_reserve_out_serial_id2,
|
||||
&last_deposit_serial_id2,
|
||||
&last_melt_serial_id2,
|
||||
&last_refund_serial_id2,
|
||||
&last_prewire_serial_id2));
|
||||
|
||||
FAILIF (last_reserve_in_serial_id2 != last_reserve_in_serial_id
|
||||
|| last_reserve_out_serial_id2 != last_reserve_out_serial_id
|
||||
|| last_deposit_serial_id2 != last_deposit_serial_id
|
||||
|| last_melt_serial_id2 != last_melt_serial_id
|
||||
|| last_refund_serial_id2 != last_refund_serial_id
|
||||
|| last_prewire_serial_id2 != last_prewire_serial_id);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_reserve_info\n");
|
||||
|
||||
struct TALER_Amount reserve_balance, withdraw_fee_balance;
|
||||
struct TALER_Amount reserve_balance2 = {}, withdraw_fee_balance2 = {};
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":12.345678",
|
||||
&reserve_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":23.456789",
|
||||
&withdraw_fee_balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_reserve_info (plugin->cls,
|
||||
session,
|
||||
&reserve_pub,
|
||||
&master_pub,
|
||||
&reserve_balance,
|
||||
&withdraw_fee_balance,
|
||||
past,
|
||||
last_reserve_in_serial_id,
|
||||
last_reserve_out_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_reserve_info\n");
|
||||
|
||||
last_reserve_in_serial_id++;
|
||||
last_reserve_out_serial_id++;
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_reserve_info (plugin->cls,
|
||||
session,
|
||||
&reserve_pub,
|
||||
&master_pub,
|
||||
&reserve_balance,
|
||||
&withdraw_fee_balance,
|
||||
future,
|
||||
last_reserve_in_serial_id,
|
||||
last_reserve_out_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_reserve_info\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_reserve_info (plugin->cls,
|
||||
session,
|
||||
&reserve_pub,
|
||||
&master_pub,
|
||||
&reserve_balance2,
|
||||
&withdraw_fee_balance2,
|
||||
&date,
|
||||
&last_reserve_in_serial_id2,
|
||||
&last_reserve_out_serial_id2));
|
||||
|
||||
FAILIF (0 != memcmp (&date, &future, sizeof (future))
|
||||
|| 0 != memcmp (&reserve_balance2, &reserve_balance, sizeof (reserve_balance))
|
||||
|| 0 != memcmp (&withdraw_fee_balance2, &withdraw_fee_balance, sizeof (withdraw_fee_balance))
|
||||
|| last_reserve_in_serial_id2 != last_reserve_in_serial_id
|
||||
|| last_reserve_out_serial_id2 != last_reserve_out_serial_id);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_reserve_summary\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_reserve_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&withdraw_fee_balance,
|
||||
&reserve_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_reserve_summary\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_reserve_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&reserve_balance,
|
||||
&withdraw_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_reserve_summary\n");
|
||||
|
||||
ZR_BLK (&reserve_balance2);
|
||||
ZR_BLK (&withdraw_fee_balance2);
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_reserve_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&reserve_balance2,
|
||||
&withdraw_fee_balance2));
|
||||
|
||||
FAILIF (0 != memcmp (&reserve_balance2, &reserve_balance, sizeof (reserve_balance))
|
||||
|| 0 != memcmp (&withdraw_fee_balance2, &withdraw_fee_balance, sizeof (withdraw_fee_balance)));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_denomination_balance\n");
|
||||
|
||||
struct TALER_Amount denom_balance, deposit_fee_balance, melt_fee_balance, refund_fee_balance;
|
||||
struct TALER_Amount denom_balance2, deposit_fee_balance2, melt_fee_balance2, refund_fee_balance2;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":12.345678",
|
||||
&denom_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":23.456789",
|
||||
&deposit_fee_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":34.567890",
|
||||
&melt_fee_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":45.678901",
|
||||
&refund_fee_balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_denomination_balance (plugin->cls,
|
||||
session,
|
||||
&denom_pub_hash,
|
||||
&refund_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&deposit_fee_balance,
|
||||
&denom_balance,
|
||||
last_reserve_out_serial_id,
|
||||
last_deposit_serial_id,
|
||||
last_melt_serial_id,
|
||||
last_refund_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_denomination_balance\n");
|
||||
|
||||
last_reserve_out_serial_id++;
|
||||
last_deposit_serial_id++;
|
||||
last_melt_serial_id++;
|
||||
last_refund_serial_id++;
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_denomination_balance (plugin->cls,
|
||||
session,
|
||||
&denom_pub_hash,
|
||||
&denom_balance,
|
||||
&deposit_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&refund_fee_balance,
|
||||
last_reserve_out_serial_id,
|
||||
last_deposit_serial_id,
|
||||
last_melt_serial_id,
|
||||
last_refund_serial_id));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_denomination_balance\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_denomination_balance (plugin->cls,
|
||||
session,
|
||||
&denom_pub_hash,
|
||||
&denom_balance2,
|
||||
&deposit_fee_balance2,
|
||||
&melt_fee_balance2,
|
||||
&refund_fee_balance2,
|
||||
&last_reserve_out_serial_id2,
|
||||
&last_deposit_serial_id2,
|
||||
&last_melt_serial_id2,
|
||||
&last_refund_serial_id2));
|
||||
|
||||
FAILIF (0 != memcmp (&denom_balance2, &denom_balance, sizeof (denom_balance))
|
||||
|| 0 != memcmp (&deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance))
|
||||
|| 0 != memcmp (&melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance))
|
||||
|| 0 != memcmp (&refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance))
|
||||
|| last_reserve_out_serial_id2 != last_reserve_out_serial_id
|
||||
|| last_deposit_serial_id2 != last_deposit_serial_id
|
||||
|| last_melt_serial_id2 != last_melt_serial_id
|
||||
|| last_refund_serial_id2 != last_refund_serial_id);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_denomination_summary\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_denomination_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&refund_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&deposit_fee_balance,
|
||||
&denom_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_denomination_summary\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_denomination_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&denom_balance,
|
||||
&deposit_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&refund_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_denomination_summary\n");
|
||||
|
||||
ZR_BLK (&denom_balance2);
|
||||
ZR_BLK (&deposit_fee_balance2);
|
||||
ZR_BLK (&melt_fee_balance2);
|
||||
ZR_BLK (&refund_fee_balance2);
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_denomination_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&denom_balance2,
|
||||
&deposit_fee_balance2,
|
||||
&melt_fee_balance2,
|
||||
&refund_fee_balance2));
|
||||
|
||||
FAILIF (0 != memcmp (&denom_balance2, &denom_balance, sizeof (denom_balance))
|
||||
|| 0 != memcmp (&deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance))
|
||||
|| 0 != memcmp (&melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance))
|
||||
|| 0 != memcmp (&refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance)));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_risk_summary\n");
|
||||
|
||||
struct TALER_Amount balance, balance2;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":13.57986",
|
||||
&balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_risk_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_risk_summary\n");
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":57.310986",
|
||||
&balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_risk_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_risk_summary\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_risk_summary (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance2));
|
||||
|
||||
FAILIF (0 != memcmp (&balance2, &balance, sizeof (balance)));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_historic_denom_revenue\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_denom_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&denom_pub_hash,
|
||||
past,
|
||||
&balance,
|
||||
&deposit_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&refund_fee_balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_denom_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&rnd_hash,
|
||||
now,
|
||||
&balance,
|
||||
&deposit_fee_balance,
|
||||
&melt_fee_balance,
|
||||
&refund_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: select_historic_denom_revenue\n");
|
||||
|
||||
int
|
||||
select_historic_denom_revenue_result (void *cls,
|
||||
const struct GNUNET_HashCode *denom_pub_hash2,
|
||||
struct GNUNET_TIME_Absolute revenue_timestamp2,
|
||||
const struct TALER_Amount *revenue_balance2,
|
||||
const struct TALER_Amount *deposit_fee_balance2,
|
||||
const struct TALER_Amount *melt_fee_balance2,
|
||||
const struct TALER_Amount *refund_fee_balance2)
|
||||
{
|
||||
static int n = 0;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_historic_denom_revenue_result: row %u\n", n);
|
||||
|
||||
if (2 <= n++
|
||||
|| cls != NULL
|
||||
|| (0 != memcmp (&revenue_timestamp2, &past, sizeof (past))
|
||||
&& 0 != memcmp (&revenue_timestamp2, &now, sizeof (now)))
|
||||
|| (0 != memcmp (denom_pub_hash2, &denom_pub_hash, sizeof (denom_pub_hash))
|
||||
&& 0 != memcmp (denom_pub_hash2, &rnd_hash, sizeof (rnd_hash)))
|
||||
|| 0 != memcmp (revenue_balance2, &balance, sizeof (balance))
|
||||
|| 0 != memcmp (deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance))
|
||||
|| 0 != memcmp (melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance))
|
||||
|| 0 != memcmp (refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"select_historic_denom_revenue_result: result does not match\n");
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_historic_denom_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
select_historic_denom_revenue_result,
|
||||
NULL));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_historic_losses\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_losses (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&denom_pub_hash,
|
||||
past,
|
||||
&balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_losses (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&rnd_hash,
|
||||
past,
|
||||
&balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: select_historic_losses\n");
|
||||
|
||||
int
|
||||
select_historic_losses_result (void *cls,
|
||||
const struct GNUNET_HashCode *denom_pub_hash2,
|
||||
struct GNUNET_TIME_Absolute loss_timestamp2,
|
||||
const struct TALER_Amount *loss_balance2)
|
||||
{
|
||||
static int n = 0;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_historic_losses_result: row %u\n", n);
|
||||
|
||||
if (2 <= n++
|
||||
|| cls != NULL
|
||||
|| (0 != memcmp (&loss_timestamp2, &past, sizeof (past))
|
||||
&& 0 != memcmp (&loss_timestamp2, &now, sizeof (now)))
|
||||
|| (0 != memcmp (denom_pub_hash2, &denom_pub_hash, sizeof (denom_pub_hash))
|
||||
&& 0 != memcmp (denom_pub_hash2, &rnd_hash, sizeof (rnd_hash)))
|
||||
|| 0 != memcmp (loss_balance2, &balance, sizeof (balance)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"select_historic_denom_revenue_result: result does not match\n");
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_historic_losses (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
select_historic_losses_result,
|
||||
NULL));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_historic_reserve_revenue\n");
|
||||
|
||||
struct TALER_Amount reserve_profits;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":56.789012",
|
||||
&reserve_profits));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_reserve_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
past,
|
||||
future,
|
||||
&reserve_profits));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_historic_reserve_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
now,
|
||||
future,
|
||||
&reserve_profits));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: select_historic_reserve_revenue\n");
|
||||
|
||||
int
|
||||
select_historic_reserve_revenue_result (void *cls,
|
||||
struct GNUNET_TIME_Absolute start_time2,
|
||||
struct GNUNET_TIME_Absolute end_time2,
|
||||
const struct TALER_Amount *reserve_profits2)
|
||||
{
|
||||
static int n = 0;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_historic_reserve_revenue_result: row %u\n", n);
|
||||
|
||||
if (2 <= n++
|
||||
|| cls != NULL
|
||||
|| (0 != memcmp (&start_time2, &past, sizeof (past))
|
||||
&& 0 != memcmp (&start_time2, &now, sizeof (now)))
|
||||
|| 0 != memcmp (&end_time2, &future, sizeof (future))
|
||||
|| 0 != memcmp (reserve_profits2, &reserve_profits, sizeof (reserve_profits)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"select_historic_reserve_revenue_result: result does not match\n");
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_historic_reserve_revenue (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
select_historic_reserve_revenue_result,
|
||||
NULL));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_predicted_result\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->insert_predicted_result (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_predicted_result\n");
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":78.901234",
|
||||
&balance));
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->update_predicted_result (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_predicted_balance\n");
|
||||
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->get_predicted_balance (plugin->cls,
|
||||
session,
|
||||
&master_pub,
|
||||
&balance2));
|
||||
|
||||
FAILIF (0 != memcmp (&balance2, &balance, sizeof (balance)));
|
||||
|
||||
result = 0;
|
||||
|
||||
drop:
|
||||
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
plugin->drop_tables (plugin->cls));
|
||||
TALER_AUDITORDB_plugin_unload (plugin);
|
||||
plugin = NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
const char *plugin_name;
|
||||
char *config_filename;
|
||||
char *testname;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
|
||||
result = -1;
|
||||
if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return -1;
|
||||
}
|
||||
GNUNET_log_setup (argv[0],
|
||||
"WARNING",
|
||||
NULL);
|
||||
plugin_name++;
|
||||
(void) GNUNET_asprintf (&testname,
|
||||
"test-auditor-db-%s", plugin_name);
|
||||
(void) GNUNET_asprintf (&config_filename,
|
||||
"%s.conf", testname);
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_parse (cfg,
|
||||
config_filename))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (config_filename);
|
||||
GNUNET_free (testname);
|
||||
return 2;
|
||||
}
|
||||
GNUNET_SCHEDULER_run (&run, cfg);
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
GNUNET_free (config_filename);
|
||||
GNUNET_free (testname);
|
||||
return result;
|
||||
}
|
@ -67,22 +67,35 @@ main (int argc,
|
||||
char * const *argv)
|
||||
{
|
||||
struct GNUNET_OS_Process *bankd;
|
||||
struct GNUNET_OS_Process *bankd_admin;
|
||||
unsigned int cnt;
|
||||
int result;
|
||||
|
||||
GNUNET_log_setup ("test-bank-api",
|
||||
"WARNING",
|
||||
NULL);
|
||||
bankd_admin = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-bank-manage",
|
||||
"taler-bank-manage",
|
||||
"--admin",
|
||||
"serve-http",
|
||||
"--port", "8081",
|
||||
NULL);
|
||||
bankd = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-bank-manage",
|
||||
"taler-bank-manage",
|
||||
"serve-http",
|
||||
"--port", "8081",
|
||||
"--port", "8080",
|
||||
NULL);
|
||||
if (NULL == bankd)
|
||||
|
||||
|
||||
if ((NULL == bankd_admin) || (NULL == bankd))
|
||||
{
|
||||
/*FIXME: More accurate error message?*/
|
||||
fprintf (stderr,
|
||||
"taler-bank-manage not found, skipping test\n");
|
||||
return 77; /* report 'skip' */
|
||||
@ -99,13 +112,26 @@ main (int argc,
|
||||
if (cnt > 30)
|
||||
break;
|
||||
}
|
||||
while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/ -o /dev/null -O /dev/null"));
|
||||
while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8080/ -o /dev/null -O /dev/null"));
|
||||
|
||||
do
|
||||
{
|
||||
fprintf (stderr, ".");
|
||||
sleep (1);
|
||||
cnt++;
|
||||
if (cnt > 30)
|
||||
break;
|
||||
}
|
||||
while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/admin/add/incoming -o /dev/null -O /dev/null"));
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
result = GNUNET_SYSERR;
|
||||
if (cnt <= 30)
|
||||
GNUNET_SCHEDULER_run (&run, &result);
|
||||
GNUNET_OS_process_kill (bankd,
|
||||
SIGTERM);
|
||||
GNUNET_OS_process_kill (bankd_admin,
|
||||
SIGTERM);
|
||||
GNUNET_OS_process_wait (bankd);
|
||||
GNUNET_OS_process_destroy (bankd);
|
||||
if (cnt > 30)
|
||||
|
@ -541,6 +541,7 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
* @param cls closure with the `struct Coin *`
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
@ -549,6 +550,7 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
static void
|
||||
reveal_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
@ -617,6 +619,7 @@ reveal_cb (void *cls,
|
||||
* @param cls closure with the `struct Coin *`
|
||||
* @param http_status HTTP response code, never #MHD_HTTP_OK (200) as for successful intermediate response this callback is skipped.
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT16_MAX on error
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
@ -625,6 +628,7 @@ reveal_cb (void *cls,
|
||||
static void
|
||||
melt_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *full_response)
|
||||
@ -776,6 +780,7 @@ refresh_coin (struct Coin *coin)
|
||||
* @param cls closure with the `struct Coin` that we are processing
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key used by the exchange for signing
|
||||
* @param obj the received JSON reply, should be kept as proof (and, in case of errors,
|
||||
* be forwarded to the customer)
|
||||
@ -783,6 +788,7 @@ refresh_coin (struct Coin *coin)
|
||||
static void
|
||||
deposit_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *obj)
|
||||
{
|
||||
@ -935,12 +941,14 @@ spend_coin (struct Coin *coin,
|
||||
* @param cls closure with our `struct Coin`
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sig signature over the coin, NULL on error
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
reserve_withdraw_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_DenominationSignature *sig,
|
||||
const json_t *full_response)
|
||||
{
|
||||
@ -1027,11 +1035,13 @@ withdraw_coin (struct Coin *coin)
|
||||
* @param cls closure with the `struct Reserve *`
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
add_incoming_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *full_response)
|
||||
{
|
||||
struct Reserve *r = cls;
|
||||
|
@ -14,7 +14,7 @@ libtalerexchange_la_LDFLAGS = \
|
||||
-no-undefined
|
||||
|
||||
libtalerexchange_la_SOURCES = \
|
||||
exchange_api_common.c exchange_api_common.h \
|
||||
exchange_api_common.c \
|
||||
exchange_api_handle.c exchange_api_handle.h \
|
||||
exchange_api_admin.c \
|
||||
exchange_api_deposit.c \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
||||
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -129,6 +129,7 @@ handle_admin_add_incoming_finished (void *cls,
|
||||
}
|
||||
aai->cb (aai->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
json);
|
||||
TALER_EXCHANGE_admin_add_incoming_cancel (aai);
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
@ -38,8 +37,8 @@
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGE_verify_coin_history (const char *currency,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
json_t *history,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
json_t *history,
|
||||
struct TALER_Amount *total)
|
||||
{
|
||||
size_t len;
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
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 General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchange-lib/exchange_api_common.h
|
||||
* @brief common functions for the exchange API
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include <jansson.h>
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include "taler_exchange_service.h"
|
||||
|
||||
/**
|
||||
* Verify a coins transaction history as returned by the exchange.
|
||||
*
|
||||
* @param currency expected currency for the coin
|
||||
* @param coin_pub public key of the coin
|
||||
* @param history history of the coin in json encoding
|
||||
* @param[out] total how much of the coin has been spent according to @a history
|
||||
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGE_verify_coin_history (const char *currency,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
json_t *history,
|
||||
struct TALER_Amount *total);
|
||||
|
||||
/* end of exchange_api_common.h */
|
@ -29,7 +29,6 @@
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
@ -262,6 +261,7 @@ handle_deposit_finished (void *cls,
|
||||
}
|
||||
dh->cb (dh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
ep,
|
||||
json);
|
||||
TALER_EXCHANGE_deposit_cancel (dh);
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
@ -1115,6 +1114,7 @@ handle_refresh_melt_finished (void *cls,
|
||||
{
|
||||
rmh->melt_cb (rmh->melt_cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
noreveal_index,
|
||||
(0 == response_code) ? NULL : &exchange_pub,
|
||||
json);
|
||||
@ -1160,6 +1160,7 @@ handle_refresh_melt_finished (void *cls,
|
||||
if (NULL != rmh->melt_cb)
|
||||
rmh->melt_cb (rmh->melt_cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
UINT16_MAX,
|
||||
NULL,
|
||||
json);
|
||||
@ -1598,6 +1599,7 @@ handle_refresh_reveal_finished (void *cls,
|
||||
{
|
||||
rrh->reveal_cb (rrh->reveal_cb_cls,
|
||||
MHD_HTTP_OK,
|
||||
TALER_EC_NONE,
|
||||
rrh->md->num_fresh_coins,
|
||||
coin_privs,
|
||||
sigs,
|
||||
@ -1634,7 +1636,10 @@ handle_refresh_reveal_finished (void *cls,
|
||||
if (NULL != rrh->reveal_cb)
|
||||
rrh->reveal_cb (rrh->reveal_cb_cls,
|
||||
response_code,
|
||||
0, NULL, NULL,
|
||||
TALER_JSON_get_error_code (json),
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
json);
|
||||
TALER_EXCHANGE_refresh_reveal_cancel (rrh);
|
||||
}
|
||||
|
@ -265,6 +265,7 @@ parse_refresh_link_ok (struct TALER_EXCHANGE_RefreshLinkHandle *rlh,
|
||||
{
|
||||
rlh->link_cb (rlh->link_cb_cls,
|
||||
MHD_HTTP_OK,
|
||||
TALER_EC_NONE,
|
||||
num_coins,
|
||||
coin_privs,
|
||||
sigs,
|
||||
@ -345,7 +346,11 @@ handle_refresh_link_finished (void *cls,
|
||||
if (NULL != rlh->link_cb)
|
||||
rlh->link_cb (rlh->link_cb_cls,
|
||||
response_code,
|
||||
0, NULL, NULL, NULL,
|
||||
TALER_JSON_get_error_code (json),
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
json);
|
||||
TALER_EXCHANGE_refresh_link_cancel (rlh);
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
@ -196,6 +195,7 @@ handle_refund_finished (void *cls,
|
||||
}
|
||||
rh->cb (rh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
ep,
|
||||
json);
|
||||
TALER_EXCHANGE_refund_cancel (rh);
|
||||
|
@ -314,7 +314,8 @@ handle_reserve_status_finished (void *cls,
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
response_code = 0;
|
||||
@ -355,6 +356,7 @@ handle_reserve_status_finished (void *cls,
|
||||
}
|
||||
wsh->cb (wsh->cb_cls,
|
||||
response_code,
|
||||
TALER_EC_NONE,
|
||||
json,
|
||||
&balance,
|
||||
len,
|
||||
@ -387,6 +389,7 @@ handle_reserve_status_finished (void *cls,
|
||||
if (NULL != wsh->cb)
|
||||
wsh->cb (wsh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
json,
|
||||
NULL,
|
||||
0, NULL);
|
||||
@ -589,6 +592,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
|
||||
dsig.rsa_signature = sig;
|
||||
wsh->cb (wsh->cb_cls,
|
||||
MHD_HTTP_OK,
|
||||
TALER_EC_NONE,
|
||||
&dsig,
|
||||
json);
|
||||
/* make sure callback isn't called again after return */
|
||||
@ -599,7 +603,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
|
||||
|
||||
|
||||
/**
|
||||
* We got a 402 PAYMENT REQUIRED response for the /reserve/withdraw operation.
|
||||
* We got a 403 FORBIDDEN 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.
|
||||
@ -723,7 +727,7 @@ handle_reserve_withdraw_finished (void *cls,
|
||||
/* This should never happen, either us or the exchange is buggy
|
||||
(or API version conflict); just pass JSON reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_PAYMENT_REQUIRED:
|
||||
case MHD_HTTP_FORBIDDEN:
|
||||
/* The exchange says that the reserve has insufficient funds;
|
||||
check the signatures in the history... */
|
||||
if (GNUNET_OK !=
|
||||
@ -762,6 +766,7 @@ handle_reserve_withdraw_finished (void *cls,
|
||||
if (NULL != wsh->cb)
|
||||
wsh->cb (wsh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
NULL,
|
||||
json);
|
||||
TALER_EXCHANGE_reserve_withdraw_cancel (wsh);
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
@ -239,6 +238,7 @@ handle_deposit_wtid_finished (void *cls,
|
||||
}
|
||||
dwh->cb (dwh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
ep,
|
||||
json,
|
||||
wtid,
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_exchange_service.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
@ -183,6 +182,7 @@ check_track_transfer_response_ok (struct TALER_EXCHANGE_TrackTransferHandle *wdh
|
||||
}
|
||||
wdh->cb (wdh->cb_cls,
|
||||
MHD_HTTP_OK,
|
||||
TALER_EC_NONE,
|
||||
&exchange_pub,
|
||||
json,
|
||||
&h_wire,
|
||||
@ -253,6 +253,7 @@ handle_track_transfer_finished (void *cls,
|
||||
}
|
||||
wdh->cb (wdh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
NULL,
|
||||
json,
|
||||
NULL,
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_wire_plugin.h"
|
||||
#include "exchange_api_common.h"
|
||||
#include "exchange_api_handle.h"
|
||||
|
||||
|
||||
@ -210,6 +209,7 @@ handle_wire_finished (void *cls,
|
||||
}
|
||||
wh->cb (wh->cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
(NULL != keep) ? keep : json);
|
||||
if (NULL != keep)
|
||||
json_decref (keep);
|
||||
|
@ -761,11 +761,13 @@ next_command (struct InterpreterState *is)
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
add_incoming_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *full_response)
|
||||
{
|
||||
struct InterpreterState *is = cls;
|
||||
@ -857,6 +859,7 @@ compare_reserve_withdraw_history (const struct TALER_EXCHANGE_ReserveHistory *h,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param[in] json original response in JSON format (useful only for diagnostics)
|
||||
* @param balance current balance in the reserve, NULL on error
|
||||
* @param history_length number of entries in the transaction history, 0 on error
|
||||
@ -865,6 +868,7 @@ compare_reserve_withdraw_history (const struct TALER_EXCHANGE_ReserveHistory *h,
|
||||
static void
|
||||
reserve_status_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
@ -924,7 +928,7 @@ reserve_status_cb (void *cls,
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
compare_reserve_withdraw_history (&history[j],
|
||||
rel))
|
||||
rel))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
fail (is);
|
||||
@ -973,12 +977,14 @@ reserve_status_cb (void *cls,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sig signature over the coin, NULL on error
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
reserve_withdraw_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_DenominationSignature *sig,
|
||||
const json_t *full_response)
|
||||
{
|
||||
@ -1009,7 +1015,7 @@ reserve_withdraw_cb (void *cls,
|
||||
cmd->details.reserve_withdraw.sig.rsa_signature
|
||||
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
|
||||
break;
|
||||
case MHD_HTTP_PAYMENT_REQUIRED:
|
||||
case MHD_HTTP_FORBIDDEN:
|
||||
/* nothing to check */
|
||||
break;
|
||||
default:
|
||||
@ -1027,6 +1033,7 @@ reserve_withdraw_cb (void *cls,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param obj the received JSON reply, should be kept as proof (and, in case of errors,
|
||||
* be forwarded to the customer)
|
||||
@ -1034,6 +1041,7 @@ reserve_withdraw_cb (void *cls,
|
||||
static void
|
||||
deposit_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *obj)
|
||||
{
|
||||
@ -1061,6 +1069,7 @@ deposit_cb (void *cls,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, never #MHD_HTTP_OK (200) as for successful intermediate response this callback is skipped.
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT16_MAX on error
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
@ -1069,6 +1078,7 @@ deposit_cb (void *cls,
|
||||
static void
|
||||
melt_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *full_response)
|
||||
@ -1098,6 +1108,7 @@ melt_cb (void *cls,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
@ -1106,6 +1117,7 @@ melt_cb (void *cls,
|
||||
static void
|
||||
reveal_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
@ -1160,6 +1172,7 @@ reveal_cb (void *cls,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
@ -1169,6 +1182,7 @@ reveal_cb (void *cls,
|
||||
static void
|
||||
link_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
@ -1336,12 +1350,14 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param obj the received JSON reply, if successful this should be the wire
|
||||
* format details as provided by /wire.
|
||||
*/
|
||||
static void
|
||||
wire_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *obj)
|
||||
{
|
||||
struct InterpreterState *is = cls;
|
||||
@ -1391,6 +1407,7 @@ wire_cb (void *cls,
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP status code we got, 0 on exchange protocol violation
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param json original json reply (may include signatures, those have then been
|
||||
* validated already)
|
||||
@ -1404,6 +1421,7 @@ wire_cb (void *cls,
|
||||
static void
|
||||
wire_deposits_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *json,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
@ -1521,6 +1539,7 @@ wire_deposits_cb (void *cls,
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP status code we got, 0 on exchange protocol violation
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param json original json reply (may include signatures, those have then been
|
||||
* validated already)
|
||||
@ -1534,6 +1553,7 @@ wire_deposits_cb (void *cls,
|
||||
static void
|
||||
deposit_wtid_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *json,
|
||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||
@ -1588,6 +1608,7 @@ deposit_wtid_cb (void *cls,
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing @a obj
|
||||
* @param obj the received JSON reply, should be kept as proof (and, in particular,
|
||||
* be forwarded to the customer)
|
||||
@ -1595,6 +1616,7 @@ deposit_wtid_cb (void *cls,
|
||||
static void
|
||||
refund_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *obj)
|
||||
{
|
||||
@ -1782,9 +1804,9 @@ interpreter_run (void *cls)
|
||||
&reserve_pub.eddsa_pub);
|
||||
cmd->details.reserve_status.wsh
|
||||
= TALER_EXCHANGE_reserve_status (exchange,
|
||||
&reserve_pub,
|
||||
&reserve_status_cb,
|
||||
is);
|
||||
&reserve_pub,
|
||||
&reserve_status_cb,
|
||||
is);
|
||||
return;
|
||||
case OC_WITHDRAW_SIGN:
|
||||
GNUNET_assert (NULL !=
|
||||
@ -2737,7 +2759,7 @@ run (void *cls)
|
||||
/* Try to overdraw funds ... */
|
||||
{ .oc = OC_WITHDRAW_SIGN,
|
||||
.label = "withdraw-coin-2",
|
||||
.expected_response_code = MHD_HTTP_PAYMENT_REQUIRED,
|
||||
.expected_response_code = MHD_HTTP_FORBIDDEN,
|
||||
.details.reserve_withdraw.reserve_reference = "create-reserve-1",
|
||||
.details.reserve_withdraw.amount = "EUR:5" },
|
||||
|
||||
@ -3051,8 +3073,11 @@ main (int argc,
|
||||
unsigned long code;
|
||||
|
||||
GNUNET_log_setup ("test-exchange-api",
|
||||
"WARNING",
|
||||
NULL);
|
||||
"DEBUG",
|
||||
"/tmp/logs");
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test log\n");
|
||||
return 0;
|
||||
|
||||
/* These might get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
|
@ -89,6 +89,7 @@ TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh,
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_ADMIN_ADD_INCOMING_WIREFORMAT_UNSUPPORTED,
|
||||
"sender_account_details");
|
||||
}
|
||||
if (0 != strcasecmp (amount.currency,
|
||||
@ -100,6 +101,7 @@ TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh,
|
||||
amount.currency);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_ADMIN_ADD_INCOMING_CURRENCY_UNSUPPORTED,
|
||||
"amount:currency");
|
||||
}
|
||||
res = TEH_DB_execute_admin_add_incoming (connection,
|
||||
|
@ -53,7 +53,8 @@ transaction_start_label: /* we will use goto for retries */ \
|
||||
session)) \
|
||||
{ \
|
||||
GNUNET_break (0); \
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection); \
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection, \
|
||||
TALER_EC_DB_START_FAILED); \
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,8 +74,9 @@ transaction_start_label: /* we will use goto for retries */ \
|
||||
if (GNUNET_SYSERR == transaction_commit_result) \
|
||||
{ \
|
||||
TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
|
||||
return TEH_RESPONSE_reply_commit_error (connection); \
|
||||
} \
|
||||
return TEH_RESPONSE_reply_commit_error (connection, \
|
||||
TALER_EC_DB_COMMIT_FAILED_HARD); \
|
||||
} \
|
||||
if (GNUNET_NO == transaction_commit_result) \
|
||||
{ \
|
||||
TALER_LOG_WARNING ("Transaction commit failed in %s\n", __FUNCTION__); \
|
||||
@ -83,7 +85,8 @@ transaction_start_label: /* we will use goto for retries */ \
|
||||
TALER_LOG_WARNING ("Transaction commit failed %u times in %s\n", \
|
||||
transaction_retries, \
|
||||
__FUNCTION__); \
|
||||
return TEH_RESPONSE_reply_commit_error (connection); \
|
||||
return TEH_RESPONSE_reply_commit_error (connection, \
|
||||
TALER_EC_DB_COMMIT_FAILED_ON_RETRY); \
|
||||
} \
|
||||
} /* end of scope opened by BEGIN_TRANSACTION */
|
||||
|
||||
@ -197,7 +200,8 @@ TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
if (GNUNET_YES ==
|
||||
TEH_plugin->have_deposit (TEH_plugin->cls,
|
||||
@ -225,8 +229,8 @@ TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
||||
if (NULL == dki)
|
||||
{
|
||||
TEH_KS_release (mks);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
"denom_pub");
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DEPOSIT_DB_DENOMINATION_KEY_UNKNOWN);
|
||||
}
|
||||
TALER_amount_ntoh (&value,
|
||||
&dki->issue.properties.value);
|
||||
@ -249,7 +253,8 @@ TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
||||
session);
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DEPOSIT_HISTORY_DB_ERROR);
|
||||
}
|
||||
/* Check that cost of all transactions is smaller than
|
||||
the value of the coin. */
|
||||
@ -274,7 +279,8 @@ TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
||||
TALER_LOG_WARNING ("Failed to store /deposit information in database\n");
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DEPOSIT_STORE_DB_ERROR);
|
||||
}
|
||||
|
||||
COMMIT_TRANSACTION(session, connection);
|
||||
@ -324,7 +330,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
dep = NULL;
|
||||
ref = NULL;
|
||||
@ -337,7 +344,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_refund_failure (connection,
|
||||
MHD_HTTP_NOT_FOUND);
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_REFUND_COIN_NOT_FOUND);
|
||||
}
|
||||
deposit_found = GNUNET_NO;
|
||||
refund_found = GNUNET_NO;
|
||||
@ -411,7 +419,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
session);
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_transaction_unknown (connection);
|
||||
return TEH_RESPONSE_reply_transaction_unknown (connection,
|
||||
TALER_EC_REFUND_DEPOSIT_NOT_FOUND);
|
||||
}
|
||||
/* handle if conflicting refund found */
|
||||
if (GNUNET_SYSERR == refund_found)
|
||||
@ -449,7 +458,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_refund_failure (connection,
|
||||
MHD_HTTP_PRECONDITION_FAILED);
|
||||
MHD_HTTP_PRECONDITION_FAILED,
|
||||
TALER_EC_REFUND_CURRENCY_MISSMATCH);
|
||||
}
|
||||
|
||||
/* check if we already send the money for the /deposit */
|
||||
@ -466,6 +476,7 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFUND_DB_INCONSISTENT,
|
||||
"database inconsistent");
|
||||
}
|
||||
if (GNUNET_YES == done)
|
||||
@ -476,7 +487,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_refund_failure (connection,
|
||||
MHD_HTTP_GONE);
|
||||
MHD_HTTP_GONE,
|
||||
TALER_EC_REFUND_MERCHANT_ALREADY_PAID);
|
||||
}
|
||||
|
||||
/* check refund amount is sufficiently low */
|
||||
@ -487,7 +499,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_refund_failure (connection,
|
||||
MHD_HTTP_PRECONDITION_FAILED);
|
||||
MHD_HTTP_PRECONDITION_FAILED,
|
||||
TALER_EC_REFUND_INSUFFICIENT_FUNDS);
|
||||
}
|
||||
|
||||
/* Check refund fee matches fee of denomination key! */
|
||||
@ -504,6 +517,7 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFUND_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denomination key not found");
|
||||
}
|
||||
TALER_amount_ntoh (&expect_fee,
|
||||
@ -519,6 +533,7 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFUND_FEE_TOO_LOW,
|
||||
"refund_fee");
|
||||
}
|
||||
if (1 == fee_cmp)
|
||||
@ -538,7 +553,8 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
||||
TALER_LOG_WARNING ("Failed to store /refund information in database\n");
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFUND_STORE_DB_ERROR);
|
||||
}
|
||||
COMMIT_TRANSACTION(session, connection);
|
||||
|
||||
@ -566,7 +582,8 @@ TEH_DB_execute_reserve_status (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
rh = TEH_plugin->get_reserve_history (TEH_plugin->cls,
|
||||
session,
|
||||
@ -637,6 +654,7 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_WITHDRAW_RESERVE_UNKNOWN,
|
||||
"reserve_pub");
|
||||
}
|
||||
|
||||
@ -653,7 +671,8 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_AMOUNT_FEE_OVERFLOW);
|
||||
}
|
||||
|
||||
/* calculate balance of the reserve */
|
||||
@ -673,7 +692,8 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_AMOUNT_DEPOSITS_OVERFLOW);
|
||||
}
|
||||
res |= 1;
|
||||
break;
|
||||
@ -686,7 +706,8 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
GNUNET_break (0);
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_HISTORIC_DENOMINATION_KEY_NOT_FOUND);
|
||||
}
|
||||
TALER_amount_ntoh (&value,
|
||||
&tdki->issue.properties.value);
|
||||
@ -700,7 +721,8 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_AMOUNT_WITHDRAWALS_OVERFLOW);
|
||||
}
|
||||
res |= 2;
|
||||
break;
|
||||
@ -708,9 +730,10 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
}
|
||||
if (0 == (res & 1))
|
||||
{
|
||||
/* did not encounter any deposit operations, how can we have a reserve? */
|
||||
/* did not encounter any wire transfer operations, how can we have a reserve? */
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_RESERVE_WITHOUT_WIRE_TRANSFER);
|
||||
}
|
||||
if (0 == (res & 2))
|
||||
{
|
||||
@ -748,6 +771,7 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_WITHDRAW_SIGNATURE_FAILED,
|
||||
"Internal error");
|
||||
}
|
||||
collectable.sig = *denom_sig;
|
||||
@ -765,7 +789,8 @@ execute_reserve_withdraw_transaction (struct MHD_Connection *connection,
|
||||
GNUNET_break (0);
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_DB_STORE_ERROR);
|
||||
}
|
||||
COMMIT_TRANSACTION (session, connection);
|
||||
|
||||
@ -811,7 +836,8 @@ TEH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
res = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
|
||||
session,
|
||||
@ -820,7 +846,8 @@ TEH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_WITHDRAW_DB_FETCH_ERROR);
|
||||
}
|
||||
|
||||
/* Don't sign again if we have already signed the coin */
|
||||
@ -834,6 +861,7 @@ TEH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
|
||||
}
|
||||
GNUNET_assert (GNUNET_NO == res);
|
||||
|
||||
/* FIXME: do we have to do this a second time here? */
|
||||
key_state = TEH_KS_acquire ();
|
||||
dki = TEH_KS_denomination_key_lookup (key_state,
|
||||
denomination_pub,
|
||||
@ -843,9 +871,11 @@ TEH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"{s:s, s:I}",
|
||||
"error",
|
||||
"Denomination not found");
|
||||
"Denomination not found",
|
||||
"code",
|
||||
(json_int_t) TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND);
|
||||
}
|
||||
denom_sig.rsa_signature = NULL;
|
||||
res = execute_reserve_withdraw_transaction (connection,
|
||||
@ -901,8 +931,9 @@ refresh_check_melt (struct MHD_Connection *connection,
|
||||
TEH_KS_DKU_DEPOSIT);
|
||||
if (NULL == dk)
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
"denom_pub"))
|
||||
TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denomination key no longer available while executing transaction"))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
dki = &dk->issue;
|
||||
TALER_amount_ntoh (&coin_value,
|
||||
@ -922,7 +953,8 @@ refresh_check_melt (struct MHD_Connection *connection,
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_internal_db_error (connection))
|
||||
TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
/* Refuse to refresh when the coin's value is insufficient
|
||||
@ -995,7 +1027,8 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
START_TRANSACTION (session, connection);
|
||||
res = TEH_plugin->get_refresh_session (TEH_plugin->cls,
|
||||
@ -1015,14 +1048,15 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_FETCH_ERROR);
|
||||
}
|
||||
|
||||
/* store 'global' session data */
|
||||
refresh_session.num_newcoins = num_new_denoms;
|
||||
refresh_session.noreveal_index
|
||||
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
TALER_CNC_KAPPA);
|
||||
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
TALER_CNC_KAPPA);
|
||||
key_state = TEH_KS_acquire ();
|
||||
if (GNUNET_OK !=
|
||||
(res = refresh_check_melt (connection,
|
||||
@ -1047,7 +1081,8 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR);
|
||||
}
|
||||
|
||||
/* store requested new denominations */
|
||||
@ -1060,7 +1095,8 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR);
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
@ -1072,7 +1108,8 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_ORDER_ERROR);
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TEH_plugin->insert_refresh_transfer_public_key (TEH_plugin->cls,
|
||||
@ -1082,7 +1119,8 @@ TEH_DB_execute_refresh_melt (struct MHD_Connection *connection,
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls,
|
||||
session);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_TRANSFER_ERROR);
|
||||
}
|
||||
|
||||
COMMIT_TRANSACTION (session, connection);
|
||||
@ -1126,8 +1164,6 @@ check_commitment (struct MHD_Connection *connection,
|
||||
struct TALER_TransferSecretP transfer_secret;
|
||||
unsigned int j;
|
||||
|
||||
/* FIXME: instead of consulting DB, reconstruct everything
|
||||
from transfer_priv here! */
|
||||
TALER_link_reveal_transfer_secret (transfer_priv,
|
||||
&melt->coin.coin_pub,
|
||||
&transfer_secret);
|
||||
@ -1158,8 +1194,10 @@ check_commitment (struct MHD_Connection *connection,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Blind failed (bad denomination key!?)\n");
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_error (connection,
|
||||
"Blinding error"))
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_BLINDING_ERROR,
|
||||
"Blinding error"))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
@ -1274,7 +1312,8 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection,
|
||||
j);
|
||||
if (NULL == ev_sigs[j].rsa_signature)
|
||||
{
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_SIGNING_ERROR);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
@ -1323,7 +1362,8 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
|
||||
res = TEH_plugin->get_refresh_session (TEH_plugin->cls,
|
||||
@ -1332,10 +1372,12 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
&refresh_session);
|
||||
if (GNUNET_NO == res)
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN,
|
||||
"session_hash");
|
||||
if ( (GNUNET_SYSERR == res) ||
|
||||
(refresh_session.noreveal_index >= TALER_CNC_KAPPA) )
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR);
|
||||
denom_pubs = GNUNET_new_array (refresh_session.num_newcoins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
if (GNUNET_OK !=
|
||||
@ -1349,7 +1391,8 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
GNUNET_free (denom_pubs);
|
||||
GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection))
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
@ -1373,7 +1416,8 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection))
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
@ -1410,7 +1454,8 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection))
|
||||
return (MHD_YES == TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
for (i=0;i<refresh_session.num_newcoins;i++)
|
||||
@ -1463,7 +1508,8 @@ TEH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
|
||||
GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR);
|
||||
}
|
||||
/* add envelopes to hash_context */
|
||||
for (j=0;j<refresh_session.num_newcoins;j++)
|
||||
@ -1656,7 +1702,8 @@ TEH_DB_execute_refresh_link (struct MHD_Connection *connection,
|
||||
if (NULL == (ctx.session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
ctx.connection = connection;
|
||||
ctx.num_sessions = 0;
|
||||
@ -1680,6 +1727,7 @@ TEH_DB_execute_refresh_link (struct MHD_Connection *connection,
|
||||
GNUNET_assert (GNUNET_OK == ctx.status);
|
||||
if (0 == ctx.num_sessions)
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_REFRESH_LINK_COIN_UNKNOWN,
|
||||
"coin_pub");
|
||||
res = TEH_RESPONSE_reply_refresh_link_success (connection,
|
||||
ctx.num_sessions,
|
||||
@ -1720,7 +1768,8 @@ TEH_DB_execute_admin_add_incoming (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
ret = TEH_plugin->reserves_in_insert (TEH_plugin->cls,
|
||||
session,
|
||||
@ -1732,7 +1781,8 @@ TEH_DB_execute_admin_add_incoming (struct MHD_Connection *connection,
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_ADMIN_ADD_INCOMING_DB_STORE);
|
||||
}
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_OK,
|
||||
@ -1913,7 +1963,8 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
ctx.is_valid = GNUNET_NO;
|
||||
ctx.wdd_head = NULL;
|
||||
@ -1926,18 +1977,21 @@ TEH_DB_execute_track_transfer (struct MHD_Connection *connection,
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_TRACK_TRANSFER_DB_FETCH_FAILED);
|
||||
goto cleanup;
|
||||
}
|
||||
if (GNUNET_SYSERR == ctx.is_valid)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_TRACK_TRANSFER_DB_INCONSISTENT);
|
||||
goto cleanup;
|
||||
}
|
||||
if (GNUNET_NO == ctx.is_valid)
|
||||
{
|
||||
ret = TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_TRACK_TRANSFER_WTID_NOT_FOUND,
|
||||
"wtid");
|
||||
goto cleanup;
|
||||
}
|
||||
@ -2035,7 +2089,8 @@ handle_wtid_data (void *cls,
|
||||
coin_fee))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ctx->res = TEH_RESPONSE_reply_internal_db_error (ctx->connection);
|
||||
ctx->res = TEH_RESPONSE_reply_internal_db_error (ctx->connection,
|
||||
TALER_EC_TRACK_TRANSACTION_DB_FEE_INCONSISTENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2079,7 +2134,8 @@ TEH_DB_execute_track_transaction (struct MHD_Connection *connection,
|
||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DB_SETUP_FAILED);
|
||||
}
|
||||
ctx.connection = connection;
|
||||
ctx.h_contract = *h_contract;
|
||||
@ -2100,17 +2156,20 @@ TEH_DB_execute_track_transaction (struct MHD_Connection *connection,
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_break (GNUNET_SYSERR == ctx.res);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_TRACK_TRANSACTION_DB_FETCH_FAILED);
|
||||
}
|
||||
if (GNUNET_NO == ret)
|
||||
{
|
||||
GNUNET_break (GNUNET_SYSERR == ctx.res);
|
||||
return TEH_RESPONSE_reply_transaction_unknown (connection);
|
||||
return TEH_RESPONSE_reply_transaction_unknown (connection,
|
||||
TALER_EC_TRACK_TRANSACTION_NOT_FOUND);
|
||||
}
|
||||
if (GNUNET_SYSERR == ctx.res)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TRACK_TRANSACTION_WTID_RESOLUTION_ERROR,
|
||||
"bug resolving deposit wtid");
|
||||
}
|
||||
return ctx.res;
|
||||
|
@ -48,12 +48,9 @@
|
||||
*/
|
||||
static int
|
||||
verify_and_execute_deposit (struct MHD_Connection *connection,
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||
{
|
||||
struct TEH_KS_StateHandle *key_state;
|
||||
struct TALER_DepositRequestPS dr;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
struct TALER_Amount fee_deposit;
|
||||
|
||||
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
|
||||
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
|
||||
@ -76,39 +73,9 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
|
||||
{
|
||||
TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID,
|
||||
"coin_sig");
|
||||
}
|
||||
/* check denomination exists and is valid */
|
||||
key_state = TEH_KS_acquire ();
|
||||
dki = TEH_KS_denomination_key_lookup (key_state,
|
||||
&deposit->coin.denom_pub,
|
||||
TEH_KS_DKU_DEPOSIT);
|
||||
if (NULL == dki)
|
||||
{
|
||||
TEH_KS_release (key_state);
|
||||
TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n");
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
"denom_pub");
|
||||
}
|
||||
/* check coin signature */
|
||||
if (GNUNET_YES !=
|
||||
TALER_test_coin_valid (&deposit->coin))
|
||||
{
|
||||
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
"ub_sig");
|
||||
}
|
||||
TALER_amount_ntoh (&fee_deposit,
|
||||
&dki->issue.properties.fee_deposit);
|
||||
if (0 < TALER_amount_cmp (&fee_deposit,
|
||||
&deposit->amount_with_fee))
|
||||
{
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_external_error (connection,
|
||||
"deposited amount smaller than depositing fee");
|
||||
}
|
||||
TEH_KS_release (key_state);
|
||||
|
||||
return TEH_DB_execute_deposit (connection,
|
||||
deposit);
|
||||
@ -141,12 +108,11 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
||||
json_t *wire;
|
||||
struct TALER_EXCHANGEDB_Deposit deposit;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
struct TEH_KS_StateHandle *ks;
|
||||
struct TEH_KS_StateHandle *key_state;
|
||||
struct GNUNET_HashCode my_h_wire;
|
||||
struct TALER_Amount amount;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("wire", &wire),
|
||||
TALER_JSON_spec_amount ("f", &amount),
|
||||
TALER_JSON_spec_amount ("f", &deposit.amount_with_fee),
|
||||
TALER_JSON_spec_denomination_public_key ("denom_pub", &deposit.coin.denom_pub),
|
||||
TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub),
|
||||
@ -180,11 +146,13 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* failure */
|
||||
|
||||
deposit.receiver_wire_account = wire;
|
||||
if (deposit.refund_deadline.abs_value_us > deposit.wire_deadline.abs_value_us)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
|
||||
"refund_deadline");
|
||||
}
|
||||
|
||||
@ -194,6 +162,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT,
|
||||
"wire");
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
@ -203,6 +172,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
||||
TALER_LOG_WARNING ("Failed to parse JSON wire format specification for /deposit request\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON,
|
||||
"wire");
|
||||
}
|
||||
if (0 != memcmp (&deposit.h_wire,
|
||||
@ -212,32 +182,48 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
|
||||
/* Client hashed contract differently than we did, reject */
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT,
|
||||
"H_wire");
|
||||
}
|
||||
ks = TEH_KS_acquire ();
|
||||
dki = TEH_KS_denomination_key_lookup (ks,
|
||||
|
||||
/* check denomination exists and is valid */
|
||||
key_state = TEH_KS_acquire ();
|
||||
dki = TEH_KS_denomination_key_lookup (key_state,
|
||||
&deposit.coin.denom_pub,
|
||||
TEH_KS_DKU_DEPOSIT);
|
||||
if (NULL == dki)
|
||||
{
|
||||
TEH_KS_release (ks);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
TEH_KS_release (key_state);
|
||||
TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n");
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_DEPOSIT_DENOMINATION_KEY_UNKNOWN,
|
||||
"denom_pub");
|
||||
}
|
||||
TALER_amount_ntoh (&deposit.deposit_fee,
|
||||
&dki->issue.properties.fee_deposit);
|
||||
TEH_KS_release (ks);
|
||||
deposit.receiver_wire_account = wire;
|
||||
deposit.amount_with_fee = amount;
|
||||
if (-1 == TALER_amount_cmp (&deposit.amount_with_fee,
|
||||
&deposit.deposit_fee))
|
||||
/* check coin signature */
|
||||
if (GNUNET_YES !=
|
||||
TALER_test_coin_valid (&deposit.coin))
|
||||
{
|
||||
/* Total amount smaller than fee, invalid */
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
"f");
|
||||
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID,
|
||||
"ub_sig");
|
||||
}
|
||||
TALER_amount_ntoh (&deposit.deposit_fee,
|
||||
&dki->issue.properties.fee_deposit);
|
||||
TEH_KS_release (key_state);
|
||||
|
||||
if (0 < TALER_amount_cmp (&deposit.deposit_fee,
|
||||
&deposit.amount_with_fee))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
|
||||
"deposited amount smaller than depositing fee");
|
||||
}
|
||||
|
||||
res = verify_and_execute_deposit (connection,
|
||||
&deposit);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
|
@ -79,6 +79,7 @@ TEH_PARSE_post_json (struct MHD_Connection *connection,
|
||||
case GNUNET_JSON_PR_OUT_OF_MEMORY:
|
||||
return (MHD_NO ==
|
||||
TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_PARSER_OUT_OF_MEMORY,
|
||||
"out of memory"))
|
||||
? GNUNET_SYSERR : GNUNET_NO;
|
||||
case GNUNET_JSON_PR_CONTINUE:
|
||||
@ -144,7 +145,9 @@ TEH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection,
|
||||
if (NULL == str)
|
||||
{
|
||||
return (MHD_NO ==
|
||||
TEH_RESPONSE_reply_arg_missing (connection, param_name))
|
||||
TEH_RESPONSE_reply_arg_missing (connection,
|
||||
TALER_EC_PARAMETER_MISSING,
|
||||
param_name))
|
||||
? GNUNET_SYSERR : GNUNET_NO;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
@ -153,7 +156,9 @@ TEH_PARSE_mhd_request_arg_data (struct MHD_Connection *connection,
|
||||
out_data,
|
||||
out_size))
|
||||
return (MHD_NO ==
|
||||
TEH_RESPONSE_reply_arg_invalid (connection, param_name))
|
||||
TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_PARAMETER_MALFORMED,
|
||||
param_name))
|
||||
? GNUNET_SYSERR : GNUNET_NO;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
@ -193,8 +198,9 @@ TEH_PARSE_json_data (struct MHD_Connection *connection,
|
||||
ret = (MHD_YES ==
|
||||
TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:s, s:I}",
|
||||
"{s:s, s:I, s:s, s:I}",
|
||||
"error", "parse error",
|
||||
"code", (json_int_t) TALER_EC_JSON_INVALID_WITH_DETAILS,
|
||||
"field", error_json_name,
|
||||
"line", (json_int_t) error_line))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
|
@ -69,7 +69,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
struct TALER_Amount total_melt;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"melt request for session %s\n",
|
||||
"/refresh/melt request for session %s\n",
|
||||
GNUNET_h2s (session_hash));
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
@ -86,6 +86,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
GNUNET_break_op (0);
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND,
|
||||
"new_denoms");
|
||||
}
|
||||
dki = &dk->issue;
|
||||
@ -105,6 +106,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
GNUNET_break_op (0);
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW,
|
||||
"cost calculation failure");
|
||||
}
|
||||
}
|
||||
@ -115,8 +117,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
if (NULL == dk)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
"denom_pub");
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denom_pub");
|
||||
}
|
||||
dki = &dk->issue;
|
||||
TALER_amount_ntoh (&fee_melt,
|
||||
@ -129,6 +132,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
GNUNET_break_op (0);
|
||||
TEH_KS_release (key_state);
|
||||
return TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
|
||||
"Melt contribution below melting fee");
|
||||
}
|
||||
TEH_KS_release (key_state);
|
||||
@ -141,8 +145,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
||||
total value of coins being generated to match! */
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "value mismatch");
|
||||
"{s:s, s:I}",
|
||||
"error", "value mismatch",
|
||||
"code", (json_int_t) TALER_EC_REFRESH_MELT_FEES_MISSMATCH);
|
||||
}
|
||||
return TEH_DB_execute_refresh_melt (connection,
|
||||
session_hash,
|
||||
@ -203,6 +208,7 @@ get_coin_public_info (struct MHD_Connection *connection,
|
||||
r_melt_detail->coin_info.denom_pub.rsa_public_key = NULL;
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
|
||||
"denom_sig"))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
@ -237,6 +243,8 @@ verify_coin_public_info (struct MHD_Connection *connection,
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
struct TALER_Amount fee_refresh;
|
||||
|
||||
/* FIXME: we lookup the dki twice during /refresh/melt.
|
||||
This should be avoided. */
|
||||
key_state = TEH_KS_acquire ();
|
||||
dki = TEH_KS_denomination_key_lookup (key_state,
|
||||
&melt_detail->coin_info.denom_pub,
|
||||
@ -246,6 +254,7 @@ verify_coin_public_info (struct MHD_Connection *connection,
|
||||
TEH_KS_release (key_state);
|
||||
TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denom_pub");
|
||||
}
|
||||
TALER_amount_ntoh (&fee_refresh,
|
||||
@ -266,6 +275,7 @@ verify_coin_public_info (struct MHD_Connection *connection,
|
||||
TEH_KS_release (key_state);
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_REFRESH_MELT_AMOUNT_INSUFFICIENT,
|
||||
"melt amount smaller than melting fee"))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
@ -280,6 +290,7 @@ verify_coin_public_info (struct MHD_Connection *connection,
|
||||
GNUNET_break_op (0);
|
||||
if (MHD_YES !=
|
||||
TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
|
||||
"confirm_sig"))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_NO;
|
||||
@ -565,6 +576,7 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_CNC_COIN_ARRAY_SIZE_INVALID,
|
||||
"coin_evs");
|
||||
}
|
||||
if (TALER_CNC_KAPPA != json_array_size (transfer_pubs))
|
||||
@ -572,6 +584,7 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_CNC_TRANSFER_ARRAY_SIZE_INVALID,
|
||||
"transfer_pubs");
|
||||
}
|
||||
res = handle_refresh_melt_json (connection,
|
||||
@ -694,6 +707,7 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh,
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_break_op (0);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID,
|
||||
"transfer_privs");
|
||||
}
|
||||
res = handle_refresh_reveal_json (connection,
|
||||
|
@ -69,14 +69,16 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFUND_FEE_CURRENCY_MISSMATCH,
|
||||
"refund_fee");
|
||||
}
|
||||
if (-1 == TALER_amount_cmp (&refund->refund_amount,
|
||||
&refund->refund_fee) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
"refund_amount");
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFUND_FEE_ABOVE_AMOUNT,
|
||||
"refund_amount");
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
|
||||
@ -86,6 +88,7 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
||||
{
|
||||
TALER_LOG_WARNING ("Invalid signature on /refund request\n");
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFUND_MERCHANT_SIGNATURE_INVALID,
|
||||
"merchant_sig");
|
||||
}
|
||||
return TEH_DB_execute_refund (connection,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014,2015 GNUnet e.V.
|
||||
Copyright (C) 2014, 2015, 2016 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
|
||||
@ -138,6 +138,7 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
TEH_KS_release (ks);
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denom_pub");
|
||||
}
|
||||
TALER_amount_ntoh (&amount,
|
||||
@ -171,6 +172,7 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
|
||||
TALER_LOG_WARNING ("Client supplied invalid signature for /reserve/withdraw request\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_WITHDRAW_RESERVE_SIGNATURE_INVALID,
|
||||
"reserve_sig");
|
||||
}
|
||||
res = TEH_DB_execute_reserve_withdraw (connection,
|
||||
|
@ -132,17 +132,20 @@ TEH_RESPONSE_reply_json_pack (struct MHD_Connection *connection,
|
||||
* Send a response indicating an invalid argument.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "invalid parameter",
|
||||
"code", (json_int_t) ec,
|
||||
"parameter", param_name);
|
||||
}
|
||||
|
||||
@ -153,17 +156,20 @@ TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
|
||||
* denomination key).
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "unknown entity referenced",
|
||||
"code", (json_int_t) ec,
|
||||
"parameter", param_name);
|
||||
}
|
||||
|
||||
@ -172,17 +178,20 @@ TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection,
|
||||
* Send a response indicating an invalid signature.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "invalid signature",
|
||||
"code", (json_int_t) ec,
|
||||
"parameter", param_name);
|
||||
}
|
||||
|
||||
@ -191,17 +200,20 @@ TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection,
|
||||
* Send a response indicating a missing argument.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is missing
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{ s:s, s:s}",
|
||||
"{ s:s, s:I, s:s}",
|
||||
"error", "missing parameter",
|
||||
"code", (json_int_t) ec,
|
||||
"parameter", param_name);
|
||||
}
|
||||
|
||||
@ -210,17 +222,20 @@ TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
|
||||
* Send a response indicating permission denied.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about why access was denied
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "permission denied",
|
||||
"code", (json_int_t) ec,
|
||||
"hint", hint);
|
||||
}
|
||||
|
||||
@ -229,17 +244,20 @@ TEH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection,
|
||||
* Send a response indicating an internal error.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about the internal error's nature
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "internal error",
|
||||
"code", (json_int_t) ec,
|
||||
"hint", hint);
|
||||
}
|
||||
|
||||
@ -248,17 +266,20 @@ TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
|
||||
* Send a response indicating an external error.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about the error's nature
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:s}",
|
||||
"{s:s, s:I, s:s}",
|
||||
"error", "client error",
|
||||
"code", (json_int_t) ec,
|
||||
"hint", hint);
|
||||
}
|
||||
|
||||
@ -268,15 +289,18 @@ TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
|
||||
* transaction (concurrent interference).
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection)
|
||||
TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error", "commit failure");
|
||||
"{s:s, s:I}",
|
||||
"error", "commit failure",
|
||||
"code", (json_int_t) ec);
|
||||
}
|
||||
|
||||
|
||||
@ -285,12 +309,15 @@ TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection)
|
||||
* database.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection)
|
||||
TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec)
|
||||
{
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
ec,
|
||||
"Failed to connect to database");
|
||||
}
|
||||
|
||||
@ -332,9 +359,9 @@ TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"invalid json");
|
||||
"{s:s, s:I}",
|
||||
"error", "invalid json",
|
||||
"code", (json_int_t) TALER_EC_JSON_INVALID);
|
||||
}
|
||||
|
||||
|
||||
@ -556,11 +583,13 @@ TEH_RESPONSE_reply_deposit_insufficient_funds (struct MHD_Connection *connection
|
||||
|
||||
history = compile_transaction_history (tl);
|
||||
if (NULL == history)
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_DEPOSIT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
"{s:s, s:o}",
|
||||
"{s:s, s:I, s:o}",
|
||||
"error", "insufficient funds",
|
||||
"code", (json_int_t) TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
|
||||
"history", history);
|
||||
}
|
||||
|
||||
@ -696,8 +725,9 @@ TEH_RESPONSE_reply_refund_conflict (struct MHD_Connection *connection,
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_CONFLICT,
|
||||
"{s:s, s:o}",
|
||||
"{s:s, s:I, s:o}",
|
||||
"status", "conflicting refund",
|
||||
"code", (json_int_t) TALER_EC_REFUND_CONFLICT,
|
||||
"history", compile_transaction_history (tl));
|
||||
}
|
||||
|
||||
@ -708,17 +738,19 @@ TEH_RESPONSE_reply_refund_conflict (struct MHD_Connection *connection,
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param response_code response code to generate
|
||||
* @param ec taler error code to include
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_refund_failure (struct MHD_Connection *connection,
|
||||
unsigned int response_code)
|
||||
unsigned int response_code,
|
||||
enum TALER_ErrorCode ec)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
response_code,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"no details");
|
||||
"{s:s, s:I}",
|
||||
"status", "refund failure",
|
||||
"code", (json_int_t) ec);
|
||||
}
|
||||
|
||||
|
||||
@ -779,6 +811,7 @@ TEH_RESPONSE_reply_reserve_status_success (struct MHD_Connection *connection,
|
||||
&balance);
|
||||
if (NULL == json_history)
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_RESERVE_STATUS_DB_ERROR,
|
||||
"balance calculation failure");
|
||||
json_balance = TALER_JSON_from_amount (&balance);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
@ -810,12 +843,14 @@ TEH_RESPONSE_reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *c
|
||||
&balance);
|
||||
if (NULL == json_history)
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
|
||||
"balance calculation failure");
|
||||
json_balance = TALER_JSON_from_amount (&balance);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_PAYMENT_REQUIRED,
|
||||
"{s:s, s:o, s:o}",
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
"{s:s, s:I, s:o, s:o}",
|
||||
"error", "Insufficient funds",
|
||||
"code", (json_int_t) TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS,
|
||||
"balance", json_balance,
|
||||
"history", json_history);
|
||||
}
|
||||
@ -830,7 +865,7 @@ TEH_RESPONSE_reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *c
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_reserve_withdraw_success (struct MHD_Connection *connection,
|
||||
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
|
||||
const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
|
||||
{
|
||||
json_t *sig_json;
|
||||
|
||||
@ -869,12 +904,15 @@ TEH_RESPONSE_reply_refresh_melt_insufficient_funds (struct MHD_Connection *conne
|
||||
|
||||
history = compile_transaction_history (tl);
|
||||
if (NULL == history)
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection);
|
||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||
TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS);
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
"{s:s, s:o, s:o, s:o, s:o, s:o}",
|
||||
"{s:s, s:I, s:o, s:o, s:o, s:o, s:o}",
|
||||
"error",
|
||||
"insufficient funds",
|
||||
"insufficient funds",
|
||||
"code",
|
||||
(json_int_t) TALER_EC_REFRESH_MELT_INSUFFICIENT_FUNDS,
|
||||
"coin_pub",
|
||||
GNUNET_JSON_from_data_auto (coin_pub),
|
||||
"original_value",
|
||||
@ -1011,8 +1049,9 @@ TEH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
|
||||
}
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_CONFLICT,
|
||||
"{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:i}",
|
||||
"{s:s, s:I, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:i}",
|
||||
"error", "commitment violation",
|
||||
"code", (json_int_t) TALER_EC_REFRESH_REVEAL_COMMITMENT_VIOLATION,
|
||||
"coin_sig", GNUNET_JSON_from_data_auto (&session->melt.coin_sig),
|
||||
"coin_pub", GNUNET_JSON_from_data_auto (&session->melt.coin.coin_pub),
|
||||
"melt_amount_with_fee", TALER_JSON_from_amount (&session->melt.amount_with_fee),
|
||||
@ -1089,15 +1128,18 @@ TEH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection,
|
||||
* 404 reply.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param ec Taler error code
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection)
|
||||
TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec)
|
||||
{
|
||||
return TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error", "Deposit unknown");
|
||||
"{s:s, s:I}",
|
||||
"error", "Deposit unknown",
|
||||
"code", (json_int_t) ec);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <jansson.h>
|
||||
#include <microhttpd.h>
|
||||
#include <pthread.h>
|
||||
#include "taler_error_codes.h"
|
||||
#include "taler-exchange-httpd.h"
|
||||
#include "taler-exchange-httpd_db.h"
|
||||
|
||||
@ -78,11 +79,13 @@ TEH_RESPONSE_reply_json_pack (struct MHD_Connection *connection,
|
||||
* Send a response indicating an invalid signature.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name);
|
||||
|
||||
|
||||
@ -90,11 +93,13 @@ TEH_RESPONSE_reply_signature_invalid (struct MHD_Connection *connection,
|
||||
* Send a response indicating an invalid argument.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name);
|
||||
|
||||
|
||||
@ -104,11 +109,13 @@ TEH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection,
|
||||
* denomination key).
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is invalid
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name);
|
||||
|
||||
|
||||
@ -116,11 +123,13 @@ TEH_RESPONSE_reply_arg_unknown (struct MHD_Connection *connection,
|
||||
* Send a response indicating a missing argument.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param param_name the parameter that is missing
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *param_name);
|
||||
|
||||
|
||||
@ -128,11 +137,13 @@ TEH_RESPONSE_reply_arg_missing (struct MHD_Connection *connection,
|
||||
* Send a response indicating permission denied.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about why access was denied
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint);
|
||||
|
||||
|
||||
@ -140,11 +151,13 @@ TEH_RESPONSE_reply_permission_denied (struct MHD_Connection *connection,
|
||||
* Send a response indicating an internal error.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about the internal error's nature
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint);
|
||||
|
||||
|
||||
@ -152,11 +165,13 @@ TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
|
||||
* Send a response indicating an external error.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @param hint hint about the error's nature
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec,
|
||||
const char *hint);
|
||||
|
||||
|
||||
@ -165,21 +180,24 @@ TEH_RESPONSE_reply_external_error (struct MHD_Connection *connection,
|
||||
* transaction (concurrent interference).
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection);
|
||||
|
||||
TEH_RESPONSE_reply_commit_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec);
|
||||
|
||||
/**
|
||||
* Send a response indicating a failure to talk to the Exchange's
|
||||
* database.
|
||||
*
|
||||
* @param connection the MHD connection to use
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection);
|
||||
TEH_RESPONSE_reply_internal_db_error (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec);
|
||||
|
||||
|
||||
/**
|
||||
@ -199,7 +217,7 @@ TEH_RESPONSE_reply_request_too_large (struct MHD_Connection *connection);
|
||||
* @return a MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection);
|
||||
TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connectionx);
|
||||
|
||||
|
||||
/**
|
||||
@ -266,11 +284,13 @@ TEH_RESPONSE_reply_refund_conflict (struct MHD_Connection *connection,
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param response_code response code to generate
|
||||
* @param ec error code uniquely identifying the error
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_refund_failure (struct MHD_Connection *connection,
|
||||
unsigned int response_code);
|
||||
unsigned int response_code,
|
||||
enum TALER_ErrorCode ec);
|
||||
|
||||
|
||||
/**
|
||||
@ -291,10 +311,12 @@ TEH_RESPONSE_reply_refund_success (struct MHD_Connection *connection,
|
||||
* 404 reply.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param ec Taler error code
|
||||
* @return MHD result code
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection);
|
||||
TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection,
|
||||
enum TALER_ErrorCode ec);
|
||||
|
||||
|
||||
/**
|
||||
@ -307,7 +329,7 @@ TEH_RESPONSE_reply_transaction_unknown (struct MHD_Connection *connection);
|
||||
*/
|
||||
int
|
||||
TEH_RESPONSE_reply_transfer_pending (struct MHD_Connection *connection,
|
||||
struct GNUNET_TIME_Absolute planned_exec_time);
|
||||
struct GNUNET_TIME_Absolute planned_exec_time);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -295,6 +295,7 @@ TEH_TEST_handler_test_ecdhe (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_ECDH_ERROR,
|
||||
"Failed to perform ECDH");
|
||||
}
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
@ -365,6 +366,7 @@ TEH_TEST_handler_test_eddsa (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_TEST_EDDSA_INVALID,
|
||||
"eddsa_sig");
|
||||
}
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
@ -377,6 +379,7 @@ TEH_TEST_handler_test_eddsa (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_free (pk);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_EDDSA_ERROR,
|
||||
"Failed to EdDSA-sign");
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (pk,
|
||||
@ -419,6 +422,7 @@ TEH_TEST_handler_test_rsa_get (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_RSA_GEN_ERROR,
|
||||
"Failed to create RSA key");
|
||||
}
|
||||
pub = GNUNET_CRYPTO_rsa_private_key_get_public (rsa_pk);
|
||||
@ -426,6 +430,7 @@ TEH_TEST_handler_test_rsa_get (struct TEH_RequestHandler *rh,
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_RSA_PUB_ERROR,
|
||||
"Failed to get public RSA key");
|
||||
}
|
||||
res = TEH_RESPONSE_reply_json_pack (connection,
|
||||
@ -489,6 +494,7 @@ TEH_TEST_handler_test_rsa_sign (struct TEH_RequestHandler *rh,
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_RSA_GEN_ERROR,
|
||||
"Failed to create RSA key");
|
||||
}
|
||||
sig = GNUNET_CRYPTO_rsa_sign_blinded (rsa_pk,
|
||||
@ -499,6 +505,7 @@ TEH_TEST_handler_test_rsa_sign (struct TEH_RequestHandler *rh,
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_TEST_RSA_SIGN_ERROR,
|
||||
"Failed to RSA-sign");
|
||||
}
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
|
@ -88,6 +88,7 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection,
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_TRACK_TRANSACTION_MERCHANT_SIGNATURE_INVALID,
|
||||
"merchant_sig");
|
||||
}
|
||||
return TEH_DB_execute_track_transaction (connection,
|
||||
|
@ -20,6 +20,7 @@
|
||||
* @author Florian Dold
|
||||
* @author Christian Grothoff
|
||||
* @author Sree Harsha Totakura
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_pq_lib.h"
|
||||
@ -627,6 +628,23 @@ postgres_prepare (PGconn *db_conn)
|
||||
"($1, $2, $3, $4, $5, $6, $7);",
|
||||
7, NULL);
|
||||
|
||||
|
||||
/* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
|
||||
transactions for reserves with serial id '\geq' the given parameter */
|
||||
PREPARE ("audit_reserves_in_get_transactions_incr",
|
||||
"SELECT"
|
||||
" reserve_pub"
|
||||
",credit_val"
|
||||
",credit_frac"
|
||||
",credit_curr"
|
||||
",execution_date"
|
||||
",sender_account_details"
|
||||
",transfer_details"
|
||||
" FROM reserves_in"
|
||||
" WHERE reserve_in_serial_id>=$1"
|
||||
" ORDER BY reserve_in_serial_id",
|
||||
1, NULL);
|
||||
|
||||
/* Used in #postgres_get_reserve_history() to obtain inbound transactions
|
||||
for a reserve */
|
||||
PREPARE ("reserves_in_get_transactions",
|
||||
@ -707,6 +725,23 @@ postgres_prepare (PGconn *db_conn)
|
||||
" WHERE reserve_pub=$1;",
|
||||
1, NULL);
|
||||
|
||||
/* Used in #postgres_select_reserves_out_above_serial_id() */
|
||||
PREPARE ("audit_get_reserves_out_incr",
|
||||
"SELECT"
|
||||
" h_blind_ev"
|
||||
",denom_pub"
|
||||
",denom_sig"
|
||||
",reserve_sig"
|
||||
",reserve_pub"
|
||||
",execution_date"
|
||||
",amount_with_fee_val"
|
||||
",amount_with_fee_frac"
|
||||
",amount_with_fee_curr"
|
||||
" FROM reserves_out"
|
||||
" WHERE reserve_out_serial_id>=$1"
|
||||
" ORDER BY reserve_out_serial_id ASC",
|
||||
1, NULL);
|
||||
|
||||
/* Used in #postgres_get_refresh_session() to fetch
|
||||
high-level information about a refresh session */
|
||||
PREPARE ("get_refresh_session",
|
||||
@ -727,6 +762,22 @@ postgres_prepare (PGconn *db_conn)
|
||||
" WHERE session_hash=$1 ",
|
||||
1, NULL);
|
||||
|
||||
/* Used in #postgres_select_refreshs_above_serial_id() to fetch
|
||||
refresh session with id '\geq' the given parameter */
|
||||
PREPARE ("audit_get_refresh_sessions_incr",
|
||||
"SELECT"
|
||||
" old_coin_pub"
|
||||
",old_coin_sig"
|
||||
",amount_with_fee_val"
|
||||
",amount_with_fee_frac"
|
||||
",amount_with_fee_curr"
|
||||
",num_newcoins"
|
||||
",noreveal_index"
|
||||
" FROM refresh_sessions"
|
||||
" WHERE melt_serial_id>=$1"
|
||||
" ORDER BY melt_serial_id ASC",
|
||||
1, NULL);
|
||||
|
||||
/* Used in #postgres_create_refresh_session() to store
|
||||
high-level information about a refresh session */
|
||||
PREPARE ("insert_refresh_session",
|
||||
@ -802,6 +853,23 @@ postgres_prepare (PGconn *db_conn)
|
||||
" WHERE old_coin_pub=$1",
|
||||
1, NULL);
|
||||
|
||||
/* Fetch refunds with rowid '\geq' the given parameter */
|
||||
PREPARE ("audit_get_refunds_incr",
|
||||
"SELECT"
|
||||
" merchant_pub"
|
||||
",merchant_sig"
|
||||
",h_contract"
|
||||
",transaction_id"
|
||||
",rtransaction_id"
|
||||
",coin_pub"
|
||||
",amount_with_fee_val"
|
||||
",amount_with_fee_frac"
|
||||
",amount_with_fee_curr"
|
||||
" FROM refunds"
|
||||
" WHERE refund_serial_id>=$1"
|
||||
" ORDER BY refund_serial_id ASC",
|
||||
1, NULL);
|
||||
|
||||
/* Query the 'refunds' by coin public key */
|
||||
PREPARE ("get_refunds_by_coin",
|
||||
"SELECT"
|
||||
@ -823,6 +891,7 @@ postgres_prepare (PGconn *db_conn)
|
||||
1, NULL);
|
||||
|
||||
|
||||
|
||||
/* Used in #postgres_insert_transfer_public_key() to
|
||||
store commitments */
|
||||
PREPARE ("insert_transfer_public_key",
|
||||
@ -921,8 +990,7 @@ postgres_prepare (PGconn *db_conn)
|
||||
" )",
|
||||
3, NULL);
|
||||
|
||||
/* Fetch an existing deposit request, used to ensure idempotency
|
||||
during /deposit processing. Used in #postgres_have_deposit(). */
|
||||
/* Fetch deposits with rowid '\geq' the given parameter */
|
||||
PREPARE ("audit_get_deposits_incr",
|
||||
"SELECT"
|
||||
" amount_with_fee_val"
|
||||
@ -937,11 +1005,12 @@ postgres_prepare (PGconn *db_conn)
|
||||
",wire_deadline"
|
||||
",h_contract"
|
||||
",wire"
|
||||
",done"
|
||||
" FROM deposits"
|
||||
" WHERE ("
|
||||
" (deposit_serial_id>=$1)"
|
||||
" )"
|
||||
" ORDER BY deposit_serial_id",
|
||||
" ORDER BY deposit_serial_id ASC",
|
||||
1, NULL);
|
||||
|
||||
/* Fetch an existing deposit request.
|
||||
@ -1207,6 +1276,18 @@ postgres_prepare (PGconn *db_conn)
|
||||
" FROM prewire"
|
||||
" WHERE finished=true",
|
||||
0, NULL);
|
||||
|
||||
/* Used in #postgres_select_prepare_above_serial_id() */
|
||||
PREPARE ("audit_get_wire_incr",
|
||||
"SELECT"
|
||||
" type"
|
||||
",buf"
|
||||
",finished"
|
||||
" FROM prewire"
|
||||
" WHERE prewire_uuid>=$1"
|
||||
" ORDER BY prewire_uuid ASC",
|
||||
1, NULL);
|
||||
|
||||
PREPARE ("gc_denominations",
|
||||
"DELETE"
|
||||
" FROM denominations"
|
||||
@ -4291,9 +4372,9 @@ postgres_select_deposits_above_serial_id (void *cls,
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_get_deposits_incr",
|
||||
params);
|
||||
if (PGRES_COMMAND_OK !=
|
||||
"audit_get_deposits_incr",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
@ -4307,20 +4388,62 @@ postgres_select_deposits_above_serial_id (void *cls,
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"audit_get_deposit_incr() returned 0 matching rows\n");
|
||||
"select_deposits_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_Deposit deposit;
|
||||
uint8_t done = 0;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||
&deposit.amount_with_fee),
|
||||
GNUNET_PQ_result_spec_absolute_time ("timestamp",
|
||||
&deposit.timestamp),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||
&deposit.merchant_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
|
||||
&deposit.coin.coin_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
|
||||
&deposit.csig),
|
||||
GNUNET_PQ_result_spec_uint64 ("transaction_id",
|
||||
&deposit.transaction_id),
|
||||
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
|
||||
&deposit.refund_deadline),
|
||||
GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
|
||||
&deposit.wire_deadline),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_contract",
|
||||
&deposit.h_contract),
|
||||
TALER_PQ_result_spec_json ("wire",
|
||||
&deposit.receiver_wire_account),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("done",
|
||||
&done),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
&deposit.merchant_pub,
|
||||
&deposit.coin.coin_pub,
|
||||
&deposit.csig,
|
||||
&deposit.amount_with_fee,
|
||||
deposit.transaction_id,
|
||||
&deposit.h_contract,
|
||||
deposit.refund_deadline,
|
||||
deposit.wire_deadline,
|
||||
deposit.receiver_wire_account,
|
||||
done);
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
@ -4343,8 +4466,72 @@ postgres_select_refreshs_above_serial_id (void *cls,
|
||||
TALER_EXCHANGEDB_RefreshSessionCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_get_refresh_sessions_incr",
|
||||
params);
|
||||
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
int nrows;
|
||||
int i;
|
||||
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_refreshs_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
struct TALER_Amount amount_with_fee;
|
||||
uint16_t num_newcoins;
|
||||
uint16_t noreveal_index;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
|
||||
&coin_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
|
||||
&coin_sig),
|
||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||
&amount_with_fee),
|
||||
GNUNET_PQ_result_spec_uint16 ("num_newcoins",
|
||||
&num_newcoins),
|
||||
GNUNET_PQ_result_spec_uint16 ("noreveal_index",
|
||||
&noreveal_index),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
&coin_pub,
|
||||
&coin_sig,
|
||||
&amount_with_fee,
|
||||
num_newcoins,
|
||||
noreveal_index);
|
||||
}
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -4367,8 +4554,72 @@ postgres_select_refunds_above_serial_id (void *cls,
|
||||
TALER_EXCHANGEDB_RefundCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_get_refunds_incr",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
int nrows;
|
||||
int i;
|
||||
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_refunds_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_Refund refund;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
|
||||
&refund.merchant_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
|
||||
&refund.merchant_sig),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_contract",
|
||||
&refund.h_contract),
|
||||
GNUNET_PQ_result_spec_uint64 ("transaction_id",
|
||||
&refund.transaction_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
|
||||
&refund.rtransaction_id),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
|
||||
&refund.coin.coin_pub),
|
||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||
&refund.refund_amount),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
&refund.coin.coin_pub,
|
||||
&refund.merchant_pub,
|
||||
&refund.merchant_sig,
|
||||
&refund.h_contract,
|
||||
refund.transaction_id,
|
||||
refund.rtransaction_id,
|
||||
&refund.refund_amount);
|
||||
}
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -4391,8 +4642,73 @@ postgres_select_reserves_in_above_serial_id (void *cls,
|
||||
TALER_EXCHANGEDB_ReserveInCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_reserves_in_get_transactions_incr",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
int nrows;
|
||||
int i;
|
||||
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_reserves_in_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
struct TALER_Amount credit;
|
||||
json_t *sender_account_details;
|
||||
json_t *transfer_details;
|
||||
struct GNUNET_TIME_Absolute execution_date;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
|
||||
&reserve_pub),
|
||||
TALER_PQ_result_spec_amount ("credit",
|
||||
&credit),
|
||||
GNUNET_PQ_result_spec_absolute_time("execution_date",
|
||||
&execution_date),
|
||||
TALER_PQ_result_spec_json ("sender_account_details",
|
||||
&sender_account_details),
|
||||
TALER_PQ_result_spec_json ("transfer_details",
|
||||
&transfer_details),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
&reserve_pub,
|
||||
&credit,
|
||||
sender_account_details,
|
||||
transfer_details,
|
||||
execution_date);
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -4415,8 +4731,79 @@ postgres_select_reserves_out_above_serial_id (void *cls,
|
||||
TALER_EXCHANGEDB_WithdrawCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_get_reserves_out_incr",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
int nrows;
|
||||
int i;
|
||||
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_reserves_out_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
struct GNUNET_HashCode h_blind_ev;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
struct TALER_DenominationSignature denom_sig;
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
struct TALER_ReserveSignatureP reserve_sig;
|
||||
struct GNUNET_TIME_Absolute execution_date;
|
||||
struct TALER_Amount amount_with_fee;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
|
||||
&h_blind_ev),
|
||||
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
|
||||
&denom_pub.rsa_public_key),
|
||||
GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
|
||||
&denom_sig.rsa_signature),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
|
||||
&reserve_pub),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
|
||||
&reserve_sig),
|
||||
GNUNET_PQ_result_spec_absolute_time ("execution_date",
|
||||
&execution_date),
|
||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||
&amount_with_fee),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
&h_blind_ev,
|
||||
&denom_pub,
|
||||
&denom_sig,
|
||||
&reserve_pub,
|
||||
&reserve_sig,
|
||||
execution_date,
|
||||
&amount_with_fee);
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -4440,8 +4827,69 @@ postgres_select_prepare_above_serial_id (void *cls,
|
||||
TALER_EXCHANGEDB_WirePreparationCallback cb,
|
||||
void *cb_cls)
|
||||
{
|
||||
GNUNET_break (0); // FIXME: not implemented
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
PGresult *result;
|
||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
||||
"audit_get_wire_incr",
|
||||
params);
|
||||
if (PGRES_TUPLES_OK !=
|
||||
PQresultStatus (result))
|
||||
{
|
||||
BREAK_DB_ERR (result);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
int nrows;
|
||||
int i;
|
||||
|
||||
nrows = PQntuples (result);
|
||||
if (0 == nrows)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"select_prepare_above_serial_id() returned 0 matching rows\n");
|
||||
PQclear (result);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
char *wire_method;
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
uint8_t finished;
|
||||
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_string ("type",
|
||||
&wire_method),
|
||||
GNUNET_PQ_result_spec_variable_size ("buf",
|
||||
&buf,
|
||||
&buf_size),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("finished",
|
||||
&finished),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result, rs, 0))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
PQclear (result);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
cb (cb_cls,
|
||||
serial_id,
|
||||
wire_method,
|
||||
buf,
|
||||
buf_size,
|
||||
finished);
|
||||
}
|
||||
|
||||
PQclear (result);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
* @brief test cases for DB interaction functions
|
||||
* @author Sree Harsha Totakura
|
||||
* @author Christian Grothoff
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
@ -77,6 +78,12 @@ dead_prepare_cb (void *cls,
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counter used in auditor-related db functions. Used to count
|
||||
* expected rows.
|
||||
*/
|
||||
unsigned int auditor_row_cnt;
|
||||
|
||||
|
||||
/**
|
||||
* Callback that is called with wire prepare data
|
||||
@ -103,6 +110,27 @@ mark_prepare_cb (void *cls,
|
||||
rowid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback with data about a prepared wire transfer.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid row identifier used to mark prepared transaction as done
|
||||
* @param wire_method which wire method is this preparation data for
|
||||
* @param buf transaction data that was persisted, NULL on error
|
||||
* @param buf_size number of bytes in @a buf, 0 on error
|
||||
* @param finished did we complete the transfer yet?
|
||||
*/
|
||||
void
|
||||
audit_wire_cb (void *cls,
|
||||
unsigned long long rowid,
|
||||
const char *wire_method,
|
||||
const char *buf,
|
||||
size_t buf_size,
|
||||
int finished)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test API relating to persisting the wire plugins preparation data.
|
||||
@ -134,6 +162,14 @@ test_wire_prepare (struct TALER_EXCHANGEDB_Session *session)
|
||||
session,
|
||||
&dead_prepare_cb,
|
||||
NULL));
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_prepare_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_wire_cb,
|
||||
NULL));
|
||||
FAILIF (1 != auditor_row_cnt);
|
||||
return GNUNET_OK;
|
||||
drop:
|
||||
return GNUNET_SYSERR;
|
||||
@ -465,6 +501,38 @@ check_transfer_data (void *cls,
|
||||
*ok = GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called with details about coins that were melted,
|
||||
* with the goal of auditing the refresh's execution.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the refresh session in our DB
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param coin_pub public key of the coin
|
||||
* @param coin_sig signature from the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param transaction_id unique transaction ID chosen by the merchant
|
||||
* @param h_contract hash of the contract between merchant and customer
|
||||
* @param refund_deadline by which the merchant adviced that he might want
|
||||
* to get a refund
|
||||
* @param wire_deadline by which the merchant adviced that he would like the
|
||||
* wire transfer to be executed
|
||||
* @param receiver_wire_account wire details for the merchant, NULL from iterate_matching_deposits()
|
||||
* @param done flag set if the deposit was already executed (or not)
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
int
|
||||
audit_refresh_session_cb (void *cls,
|
||||
unsigned long long rowid, /* FIXME: decide data type for serial_id! */
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
uint16_t num_newcoins,
|
||||
uint16_t noreveal_index)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to test melting of coins as part of a refresh session
|
||||
@ -538,6 +606,14 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
session,
|
||||
&session_hash,
|
||||
&ret_refresh_session));
|
||||
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_OK != plugin->select_refreshs_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_refresh_session_cb,
|
||||
NULL));
|
||||
FAILIF (1 != auditor_row_cnt);
|
||||
FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins);
|
||||
FAILIF (ret_refresh_session.noreveal_index != refresh_session.noreveal_index);
|
||||
|
||||
@ -874,6 +950,128 @@ deposit_cb (void *cls,
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for #select_deposits_above_serial_id ()
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the deposit in our DB
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param coin_pub public key of the coin
|
||||
* @param coin_sig signature from the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param transaction_id unique transaction ID chosen by the merchant
|
||||
* @param h_contract hash of the contract between merchant and customer
|
||||
* @param refund_deadline by which the merchant adviced that he might want
|
||||
* to get a refund
|
||||
* @param wire_deadline by which the merchant adviced that he would like the
|
||||
* wire transfer to be executed
|
||||
* @param receiver_wire_account wire details for the merchant, NULL from iterate_matching_deposits()
|
||||
* @param done flag set if the deposit was already executed (or not)
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
int
|
||||
audit_deposit_cb (void *cls,
|
||||
unsigned long long rowid,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
uint64_t transaction_id,
|
||||
const struct GNUNET_HashCode *h_contract,
|
||||
struct GNUNET_TIME_Absolute refund_deadline,
|
||||
struct GNUNET_TIME_Absolute wire_deadline,
|
||||
const json_t *receiver_wire_account,
|
||||
int done)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about coins that were refunding,
|
||||
* with the goal of auditing the refund's execution.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the refund in our DB
|
||||
* @param coin_pub public key of the coin
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param merchant_sig signature of the merchant
|
||||
* @param h_contract hash of the contract between merchant and customer
|
||||
* @param transaction_id original transaction ID chosen by the merchant
|
||||
* @param rtransaction_id refund transaction ID chosen by the merchant
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
int
|
||||
audit_refund_cb (void *cls,
|
||||
unsigned long long rowid, /* FIXME: decide data type for serial_id! */
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct TALER_MerchantSignatureP *merchant_sig,
|
||||
const struct GNUNET_HashCode *h_contract,
|
||||
uint64_t transaction_id,
|
||||
uint64_t rtransaction_id,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about incoming wire transfers.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the refresh session in our DB
|
||||
* @param reserve_pub public key of the reserve (also the WTID)
|
||||
* @param credit amount that was received
|
||||
* @param sender_account_details information about the sender's bank account
|
||||
* @param transfer_details information that uniquely identifies the wire transfer
|
||||
* @param execution_date when did we receive the funds
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
int
|
||||
audit_reserve_in_cb (void *cls,
|
||||
unsigned long long rowid, /* FIXME: decide data type for serial_id! */
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const struct TALER_Amount *credit,
|
||||
const json_t *sender_account_details,
|
||||
const json_t *transfer_details,
|
||||
struct GNUNET_TIME_Absolute execution_date)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called with details about withdraw operations.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the refresh session in our DB
|
||||
* @param h_blind_ev blinded hash of the coin's public key
|
||||
* @param denom_pub public denomination key of the deposited coin
|
||||
* @param denom_sig signature over the deposited coin
|
||||
* @param reserve_pub public key of the reserve
|
||||
* @param reserve_sig signature over the withdraw operation
|
||||
* @param execution_date when did the wallet withdraw the coin
|
||||
* @param amount_with_fee amount that was withdrawn
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
int
|
||||
audit_reserve_out_cb (void *cls,
|
||||
unsigned long long rowid, /* FIXME: decide data type for serial_id! */
|
||||
const struct GNUNET_HashCode *h_blind_ev,
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const struct TALER_ReserveSignatureP *reserve_sig,
|
||||
struct GNUNET_TIME_Absolute execution_date,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test garbage collection.
|
||||
@ -1121,6 +1319,21 @@ run (void *cls)
|
||||
}
|
||||
}
|
||||
FAILIF (3 != cnt);
|
||||
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_reserves_in_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_reserve_in_cb,
|
||||
NULL));
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_reserves_out_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_reserve_out_cb,
|
||||
NULL));
|
||||
FAILIF (3 != auditor_row_cnt);
|
||||
/* Tests for deposits */
|
||||
memset (&deposit, 0, sizeof (deposit));
|
||||
RND_BLK (&deposit.coin.coin_pub);
|
||||
@ -1145,6 +1358,14 @@ run (void *cls)
|
||||
plugin->have_deposit (plugin->cls,
|
||||
session,
|
||||
&deposit));
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_deposits_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_deposit_cb,
|
||||
NULL));
|
||||
FAILIF (1 != auditor_row_cnt);
|
||||
result = 9;
|
||||
FAILIF (1 !=
|
||||
plugin->iterate_matching_deposits (plugin->cls,
|
||||
@ -1232,7 +1453,15 @@ run (void *cls)
|
||||
plugin->insert_refund (plugin->cls,
|
||||
session,
|
||||
&refund));
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_OK !=
|
||||
plugin->select_refunds_above_serial_id (plugin->cls,
|
||||
session,
|
||||
0,
|
||||
&audit_refund_cb,
|
||||
NULL));
|
||||
|
||||
FAILIF (1 != auditor_row_cnt);
|
||||
tl = plugin->get_coin_transactions (plugin->cls,
|
||||
session,
|
||||
&refund.coin.coin_pub);
|
||||
|
@ -28,6 +28,90 @@
|
||||
#include "taler_signatures.h"
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the results of select_denomination_info()
|
||||
*
|
||||
* @param cls closure
|
||||
* @param issue issuing information with value, fees and other info about the denomination.
|
||||
*
|
||||
* @return sets the return value of select_denomination_info(),
|
||||
* #GNUNET_OK to continue,
|
||||
* #GNUNET_NO to stop processing further rows
|
||||
* #GNUNET_SYSERR or other values on error.
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_AUDITORDB_DenominationInfoDataCallback)(void *cls,
|
||||
const struct TALER_DenominationKeyValidityPS *issue);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the results of select_historic_denom_revenue()
|
||||
*
|
||||
* @param cls closure
|
||||
* @param denom_pub_hash hash of the denomination key
|
||||
* @param revenue_timestamp when did this profit get realized
|
||||
* @param revenue_balance what was the total profit made from
|
||||
* deposit fees, melting fees, refresh fees
|
||||
* and coins that were never returned?
|
||||
* @param deposit_fee_balance total profits from deposit fees
|
||||
* @param melt_fee_balance total profits from melting fees
|
||||
* @param refund_fee_balance total profits from refund fees
|
||||
*
|
||||
* @return sets the return value of select_denomination_info(),
|
||||
* #GNUNET_OK to continue,
|
||||
* #GNUNET_NO to stop processing further rows
|
||||
* #GNUNET_SYSERR or other values on error.
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_AUDITORDB_HistoricDenominationRevenueDataCallback)(void *cls,
|
||||
const struct GNUNET_HashCode *denom_pub_hash,
|
||||
struct GNUNET_TIME_Absolute revenue_timestamp,
|
||||
const struct TALER_Amount *revenue_balance,
|
||||
const struct TALER_Amount *deposit_fee_balance,
|
||||
const struct TALER_Amount *melt_fee_balance,
|
||||
const struct TALER_Amount *refund_fee_balance);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the results of select_historic_losses()
|
||||
*
|
||||
* @param cls closure
|
||||
* @param denom_pub_hash hash of the denomination key
|
||||
* @param loss_timestamp when did this profit get realized
|
||||
* @param loss_balance what was the total loss
|
||||
*
|
||||
* @return sets the return value of select_denomination_info(),
|
||||
* #GNUNET_OK to continue,
|
||||
* #GNUNET_NO to stop processing further rows
|
||||
* #GNUNET_SYSERR or other values on error.
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_AUDITORDB_HistoricLossesDataCallback)(void *cls,
|
||||
const struct GNUNET_HashCode *denom_pub_hash,
|
||||
struct GNUNET_TIME_Absolute loss_timestamp,
|
||||
const struct TALER_Amount *loss_balance);
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the results of select_historic_reserve_revenue()
|
||||
*
|
||||
* @param cls closure
|
||||
* @param start_time beginning of aggregated time interval
|
||||
* @param end_time end of aggregated time interval
|
||||
* @param reserve_profits total profits made
|
||||
*
|
||||
* @return sets the return value of select_denomination_info(),
|
||||
* #GNUNET_OK to continue,
|
||||
* #GNUNET_NO to stop processing further rows
|
||||
* #GNUNET_SYSERR or other values on error.
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_AUDITORDB_HistoricReserveRevenueDataCallback)(void *cls,
|
||||
struct GNUNET_TIME_Absolute start_time,
|
||||
struct GNUNET_TIME_Absolute end_time,
|
||||
const struct TALER_Amount *reserve_profits);
|
||||
|
||||
|
||||
/**
|
||||
* Handle for one session with the database.
|
||||
*/
|
||||
@ -164,10 +248,88 @@ struct TALER_AUDITORDB_Plugin
|
||||
(*select_denomination_info)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
void *cb, /* FIXME: type! */
|
||||
TALER_AUDITORDB_DenominationInfoDataCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Insert information about the auditor's progress with an exchange's
|
||||
* data.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to use
|
||||
* @param master_pub master key of the exchange
|
||||
* @param last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed
|
||||
* @param last_reserve_out_serial_id serial ID of the last withdraw the auditor processed
|
||||
* @param last_deposit_serial_id serial ID of the last deposit the auditor processed
|
||||
* @param last_melt_serial_id serial ID of the last refresh the auditor processed
|
||||
* @param last_prewire_serial_id serial ID of the last prewire transfer the auditor processed
|
||||
* @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
|
||||
*/
|
||||
int
|
||||
(*insert_auditor_progress)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
uint64_t last_reserve_in_serial_id,
|
||||
uint64_t last_reserve_out_serial_id,
|
||||
uint64_t last_deposit_serial_id,
|
||||
uint64_t last_melt_serial_id,
|
||||
uint64_t last_refund_serial_id,
|
||||
uint64_t last_prewire_serial_id);
|
||||
|
||||
|
||||
/**
|
||||
* Update information about the progress of the auditor. There
|
||||
* must be an existing record for the exchange.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to use
|
||||
* @param master_pub master key of the exchange
|
||||
* @param last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed
|
||||
* @param last_reserve_out_serial_id serial ID of the last withdraw the auditor processed
|
||||
* @param last_deposit_serial_id serial ID of the last deposit the auditor processed
|
||||
* @param last_melt_serial_id serial ID of the last refresh the auditor processed
|
||||
* @param last_prewire_serial_id serial ID of the last prewire transfer the auditor processed
|
||||
* @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
|
||||
*/
|
||||
int
|
||||
(*update_auditor_progress)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
uint64_t last_reserve_in_serial_id,
|
||||
uint64_t last_reserve_out_serial_id,
|
||||
uint64_t last_deposit_serial_id,
|
||||
uint64_t last_melt_serial_id,
|
||||
uint64_t last_refund_serial_id,
|
||||
uint64_t last_prewire_serial_id);
|
||||
|
||||
|
||||
/**
|
||||
* Get information about the progress of the auditor.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session connection to use
|
||||
* @param master_pub master key of the exchange
|
||||
* @param[out] last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed
|
||||
* @param[out] last_reserve_out_serial_id serial ID of the last withdraw the auditor processed
|
||||
* @param[out] last_deposit_serial_id serial ID of the last deposit the auditor processed
|
||||
* @param[out] last_melt_serial_id serial ID of the last refresh the auditor processed
|
||||
* @param[out] last_prewire_serial_id serial ID of the last prewire transfer the auditor processed
|
||||
* @return #GNUNET_OK on success; #GNUNET_SYSERR on failure;
|
||||
* #GNUNET_NO if we have no records for the @a master_pub
|
||||
*/
|
||||
int
|
||||
(*get_auditor_progress)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
uint64_t *last_reserve_in_serial_id,
|
||||
uint64_t *last_reserve_out_serial_id,
|
||||
uint64_t *last_deposit_serial_id,
|
||||
uint64_t *last_melt_serial_id,
|
||||
uint64_t *last_refund_serial_id,
|
||||
uint64_t *last_prewire_serial_id);
|
||||
|
||||
|
||||
/**
|
||||
* Insert information about a reserve. There must not be an
|
||||
* existing record for the reserve.
|
||||
@ -586,7 +748,7 @@ struct TALER_AUDITORDB_Plugin
|
||||
(*select_historic_denom_revenue)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
void *cb, /* FIXME: fix type */
|
||||
TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
@ -628,7 +790,7 @@ struct TALER_AUDITORDB_Plugin
|
||||
(*select_historic_losses)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
void *cb, /* FIXME: fix type */
|
||||
TALER_AUDITORDB_HistoricLossesDataCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
@ -666,7 +828,7 @@ struct TALER_AUDITORDB_Plugin
|
||||
(*select_historic_reserve_revenue)(void *cls,
|
||||
struct TALER_AUDITORDB_Session *session,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
void *cb, /* FIXME: type */
|
||||
TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
@ -721,6 +883,7 @@ struct TALER_AUDITORDB_Plugin
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
struct TALER_Amount *balance);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,7 @@
|
||||
|
||||
#include <jansson.h>
|
||||
#include "taler_util.h"
|
||||
#include "taler_error_codes.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
|
||||
|
||||
@ -355,6 +356,7 @@ struct TALER_EXCHANGE_WireHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param obj the received JSON reply, if successful this should be the wire
|
||||
* format details as provided by /wire, or NULL if the
|
||||
* reply was not in JSON format.
|
||||
@ -362,6 +364,7 @@ struct TALER_EXCHANGE_WireHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_WireResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *obj);
|
||||
|
||||
|
||||
@ -423,6 +426,7 @@ struct TALER_EXCHANGE_DepositHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_DepositResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *obj);
|
||||
|
||||
@ -504,6 +508,7 @@ struct TALER_EXCHANGE_RefundHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sign_key exchange key used to sign @a obj, or NULL
|
||||
* @param obj the received JSON reply, should be kept as proof (and, in particular,
|
||||
* be forwarded to the customer)
|
||||
@ -511,6 +516,7 @@ struct TALER_EXCHANGE_RefundHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_RefundResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *obj);
|
||||
|
||||
@ -650,6 +656,7 @@ struct TALER_EXCHANGE_ReserveHistory
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param[in] json original response in JSON format (useful only for diagnostics)
|
||||
* @param balance current balance in the reserve, NULL on error
|
||||
* @param history_length number of entries in the transaction history, 0 on error
|
||||
@ -658,6 +665,7 @@ struct TALER_EXCHANGE_ReserveHistory
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_ReserveStatusResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
@ -713,12 +721,14 @@ struct TALER_EXCHANGE_ReserveWithdrawHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sig signature over the coin, NULL on error
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_ReserveWithdrawResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_DenominationSignature *sig,
|
||||
const json_t *full_response);
|
||||
|
||||
@ -835,6 +845,7 @@ struct TALER_EXCHANGE_RefreshMeltHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, never #MHD_HTTP_OK (200) as for successful intermediate response this callback is skipped.
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT16_MAX on error
|
||||
* @param sign_key exchange key used to sign @a full_response, or NULL
|
||||
@ -843,7 +854,8 @@ struct TALER_EXCHANGE_RefreshMeltHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_RefreshMeltCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
uint16_t noreveal_index,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *full_response);
|
||||
|
||||
@ -900,6 +912,7 @@ TALER_EXCHANGE_refresh_melt_cancel (struct TALER_EXCHANGE_RefreshMeltHandle *rmh
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
@ -908,6 +921,7 @@ TALER_EXCHANGE_refresh_melt_cancel (struct TALER_EXCHANGE_RefreshMeltHandle *rmh
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_RefreshRevealCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
@ -979,6 +993,7 @@ struct TALER_EXCHANGE_RefreshLinkHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
@ -988,6 +1003,7 @@ struct TALER_EXCHANGE_RefreshLinkHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_RefreshLinkCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
@ -1043,11 +1059,13 @@ struct TALER_EXCHANGE_AdminAddIncomingHandle;
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_AdminAddIncomingResultCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *full_response);
|
||||
|
||||
|
||||
@ -1108,6 +1126,7 @@ struct TALER_EXCHANGE_TrackTransferHandle;
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP status code we got, 0 on exchange protocol violation
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sign_key exchange key used to sign @a json, or NULL
|
||||
* @param json original json reply (may include signatures, those have then been
|
||||
* validated already)
|
||||
@ -1121,6 +1140,7 @@ struct TALER_EXCHANGE_TrackTransferHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_TrackTransferCallback)(void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *json,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
@ -1171,6 +1191,7 @@ struct TALER_EXCHANGE_TrackTransactionHandle;
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP status code we got, 0 on exchange protocol violation
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sign_key exchange key used to sign @a json, or NULL
|
||||
* @param json original json reply (may include signatures, those have then been
|
||||
* validated already)
|
||||
@ -1182,6 +1203,7 @@ struct TALER_EXCHANGE_TrackTransactionHandle;
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_TrackTransactionCallback)(void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *json,
|
||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||
@ -1240,4 +1262,5 @@ TALER_EXCHANGE_verify_coin_history (const char *currency,
|
||||
json_t *history,
|
||||
struct TALER_Amount *total);
|
||||
|
||||
|
||||
#endif /* _TALER_EXCHANGE_SERVICE_H */
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <jansson.h>
|
||||
#include <gnunet/gnunet_json_lib.h>
|
||||
#include "taler_util.h"
|
||||
#include "taler_error_codes.h"
|
||||
|
||||
/**
|
||||
* Print JSON parsing related error information
|
||||
@ -92,6 +93,17 @@ int
|
||||
TALER_JSON_hash (const json_t *json,
|
||||
struct GNUNET_HashCode *hc);
|
||||
|
||||
/**
|
||||
* Extract the Taler error code from the given @a json object.
|
||||
* Note that #TALER_EC_NONE is returned if no "code" is present.
|
||||
*
|
||||
* @param json response to extract the error code from
|
||||
* @return the "code" value from @a json
|
||||
*/
|
||||
enum TALER_ErrorCode
|
||||
TALER_JSON_get_error_code (const json_t *json);
|
||||
|
||||
|
||||
#endif /* TALER_JSON_LIB_H_ */
|
||||
|
||||
/* End of taler_json_lib.h */
|
||||
|
@ -117,4 +117,6 @@ const struct GNUNET_OS_ProjectData *
|
||||
TALER_project_data_default (void);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -50,4 +50,33 @@ TALER_JSON_hash (const json_t *json,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Extract the Taler error code from the given @a json object.
|
||||
* Note that #TALER_EC_NONE is returned if no "code" is present.
|
||||
*
|
||||
* @param json response to extract the error code from
|
||||
* @return the "code" value from @a json
|
||||
*/
|
||||
enum TALER_ErrorCode
|
||||
TALER_JSON_get_error_code (const json_t *json)
|
||||
{
|
||||
const json_t *jc;
|
||||
|
||||
if (NULL == json)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_EC_INVALID_RESPONSE;
|
||||
}
|
||||
jc = json_object_get (json, "code");
|
||||
if (NULL == jc)
|
||||
return TALER_EC_NONE;
|
||||
if (json_is_integer (jc))
|
||||
return (enum TALER_ErrorCode) json_integer_value (jc);
|
||||
GNUNET_break_op (0);
|
||||
return TALER_EC_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* End of json/json.c */
|
||||
|
61
taler-exchange-dev.nix
Normal file
61
taler-exchange-dev.nix
Normal file
@ -0,0 +1,61 @@
|
||||
{ stdenv, makeWrapper, pkgconfig, autoconf, automake, libtool, ccache, ccache_dir ? ""
|
||||
, gnunet-dev, postgresql, jansson, libgcrypt, libgnurl, libmicrohttpd }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
src = ./.;
|
||||
name = "taler-exchange-dev";
|
||||
|
||||
buildInputs = [
|
||||
makeWrapper pkgconfig autoconf automake libtool ccache
|
||||
gnunet-dev postgresql jansson libgcrypt libgnurl libmicrohttpd
|
||||
];
|
||||
|
||||
patchPhase = ''
|
||||
if [ -e Makefile ]; then
|
||||
make distclean
|
||||
fi
|
||||
'';
|
||||
|
||||
NIX_CFLAGS_COMPILE = "-ggdb -O0";
|
||||
|
||||
configureFlags = [
|
||||
"--enable-gcc-hardening"
|
||||
"--enable-linker-hardening"
|
||||
|
||||
"--enable-logging=verbose"
|
||||
"--enable-poisoning"
|
||||
];
|
||||
|
||||
preConfigure = ''
|
||||
./bootstrap
|
||||
|
||||
if [ -n "${ccache_dir}" ]; then
|
||||
export CC='ccache gcc'
|
||||
export CCACHE_COMPRESS=1
|
||||
export CCACHE_DIR="${ccache_dir}"
|
||||
export CCACHE_UMASK=007
|
||||
fi
|
||||
'';
|
||||
|
||||
doCheck = false;
|
||||
|
||||
postInstall = ''
|
||||
# Tests can be run this way
|
||||
#export GNUNET_PREFIX="$out"
|
||||
#export PATH="$out/bin:$PATH"
|
||||
#make -k check
|
||||
'';
|
||||
|
||||
meta = with stdenv.lib; {
|
||||
description = "Exchange for GNU Taler";
|
||||
|
||||
longDescription = ''
|
||||
'';
|
||||
|
||||
homepage = https://taler.net/;
|
||||
|
||||
license = licenses.gpl3Plus;
|
||||
platforms = platforms.gnu;
|
||||
maintainers = with maintainers; [ ];
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user