Compare commits

...

27 Commits

Author SHA1 Message Date
e0f78bc3c9
-update doc/prebuilt 2023-07-11 09:59:07 +02:00
4ebdcc0247
-gana update 2023-07-11 09:37:32 +02:00
8a7bfefa38
-handle some of the codespell complaints 2023-07-11 09:21:34 +02:00
88ecba945e
-handle doxygen complaints 2023-07-11 09:06:28 +02:00
Christian Grothoff
43d5e5707c
towards using taler-unified-setup in auditor tests 2023-07-10 23:20:08 +02:00
Christian Grothoff
1e572ebcab
-typos 2023-07-10 19:48:24 +02:00
Christian Grothoff
c6676f1aa5
-fix indent 2023-07-10 17:58:03 +02:00
Christian Grothoff
6c44755458
use DK age group, not global age group 2023-07-10 16:55:26 +02:00
Christian Grothoff
6a483b51ec
fix alignment issue, ensure we hash over packed structure to avoid non-determinism 2023-07-10 16:34:01 +02:00
Christian Grothoff
66f9a5b5e5
-simplify 2023-07-10 15:26:53 +02:00
Christian Grothoff
f4abc1c369
tip -> reward 2023-07-10 10:34:33 +02:00
Christian Grothoff
c57c3463d1
Tip => Reward 2023-07-10 10:34:33 +02:00
8d6b0944da
gana update 2023-07-10 10:29:11 +02:00
6107e99559
Merge branch 'master' of ssh://git.taler.net/exchange 2023-07-10 10:25:29 +02:00
3024dc9fa5
fix memory leaks reported by valgrind 2023-07-10 10:23:52 +02:00
9d706a01a2
added expected HTTP-code to logger 2023-07-10 10:22:29 +02:00
Christian Grothoff
c05f832048
-current use is good 2023-07-06 12:40:18 +02:00
Christian Grothoff
1026a32c71
-no return is correct here 2023-07-06 12:39:38 +02:00
7e9f5324b7
-loglevel INFO 2023-07-06 11:30:45 +02:00
Christian Grothoff
c02d88c8e3
work on keys serialization/deserialization 2023-07-06 00:08:00 +02:00
Christian Grothoff
11ea6fcfce
fix mime-type matching (#7882) 2023-07-05 18:20:58 +02:00
Christian Grothoff
f2c3443860
fix mime-type matching (#7882) 2023-07-05 18:20:46 +02:00
Christian Grothoff
95c05a8827
fix mime-type matching (#7882) 2023-07-05 18:19:54 +02:00
Christian Grothoff
40dfb94e0f
fix mime-type matching (#7882) 2023-07-05 18:18:23 +02:00
Christian Grothoff
1db17d43bd
-misc minor fixes 2023-07-05 13:13:16 +02:00
Christian Grothoff
999db0fb80
-bugfixes 2023-07-04 23:21:47 +02:00
Christian Grothoff
ff8349e6e7
more exchange API refactoring 2023-07-04 15:37:46 +02:00
99 changed files with 2093 additions and 3614 deletions

@ -1 +1 @@
Subproject commit 31b74264e62c4a7f4a671033e214c43fa2f304c0 Subproject commit 86b36917a59cc46961a9c9042b1af75a88545558

View File

@ -85,7 +85,7 @@ CREATE_SUBDIRS = YES
# level increment doubles the number of directories, resulting in 4096 # level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The # directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed # sub-directories are organized in 2 levels, the first level always has a fixed
# numer of 16 directories. # number of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8. # Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES. # This tag requires that the tag CREATE_SUBDIRS is set to YES.

View File

@ -40,7 +40,7 @@ The main interactions of the system are:
\item[shutdown] the Taler payment system operator informs the customers that the system is being shut down for good \item[shutdown] the Taler payment system operator informs the customers that the system is being shut down for good
\end{description} \end{description}
In the analysis of the legal requirements, it is important to differenciate In the analysis of the legal requirements, it is important to differentiate
between transactions between wallets (customer-to-customer) and transactions between transactions between wallets (customer-to-customer) and transactions
where money flows from a wallet into a bank account (customer-to-merchant) as where money flows from a wallet into a bank account (customer-to-merchant) as
these have different limits: When digital coins are used to pay at a business in these have different limits: When digital coins are used to pay at a business in

View File

@ -43,8 +43,8 @@
\end{figure} \end{figure}
At the beginning of the KYB process, the user needs to specify whether they At the beginning of the KYB process, the user needs to specify whether they
are an {\bf individual} (not incorporated) or a {\bf business}.\footnote{ In are an {\bf individual} (not incorporated) or a {\bf business}.\footnote{In
pratice, we expect most owners of bank accounts crossing the KYB threshold to practice, we expect most owners of bank accounts crossing the KYB threshold to
be businesses, but in principle such a bank account could be owned by an be businesses, but in principle such a bank account could be owned by an
individual operating a business without a separate legal entity.} This then individual operating a business without a separate legal entity.} This then
determines which types of attributes are collected in the KYB process determines which types of attributes are collected in the KYB process

View File

@ -43,7 +43,7 @@
\end{figure} \end{figure}
At the beginning of the KYC process, the user needs to specify whether they At the beginning of the KYC process, the user needs to specify whether they
are an {\bf individual} or a {\bf business}.\footnote{ In pratice, we expect are an {\bf individual} or a {\bf business}.\footnote{ In practice, we expect
most wallet-users to be individuals, but in principle a wallet could be owned most wallet-users to be individuals, but in principle a wallet could be owned
by a business.} This then determines which types of attributes are collected by a business.} This then determines which types of attributes are collected
in the KYC process (Table~\ref{table:proc:kyc:individual} vs. in the KYC process (Table~\ref{table:proc:kyc:individual} vs.

@ -1 +1 @@
Subproject commit 66e99d09d4351bb6e6c5fd442f14ec7cf1363a81 Subproject commit fa4729db5637c82d5fc6f5bb7021f6c350c8c5a6

View File

@ -218,6 +218,7 @@ EXTRA_DIST = \
taler-auditor.in \ taler-auditor.in \
taler-helper-auditor-render.py \ taler-helper-auditor-render.py \
auditor.conf \ auditor.conf \
setup.sh \
test-sync-in.conf \ test-sync-in.conf \
test-sync-out.conf \ test-sync-out.conf \
generate-auditor-basedb.sh \ generate-auditor-basedb.sh \

View File

@ -1,14 +1,27 @@
[exchange-offline] [PATHS]
MASTER_PRIV_FILE = auditor-basedb.mpriv TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
TALER_HOME = ${PWD}/generate_auditordb_home/
[instance-default] [taler]
KEYFILE = ${TALER_DATA_HOME}/merchant/default.priv CURRENCY = TESTKUDOS
NAME = Merchant Inc. CURRENCY_ROUND_UNIT = TESTKUDOS:0.01
[exchange]
MASTER_PUBLIC_KEY = M4FGP18EQFXFGGFQ1AWXHACN2JX0SMVK9CNF6459Z1WG18JSN0BG
SIGNKEY_DURATION = 4 weeks
LOOKAHEAD_SIGN = 32 weeks 1 day
SIGNKEY_LEGAL_DURATION = 4 weeks
AML_THRESHOLD = TESTKUDOS:1000000
[exchangedb-postgres]
CONFIG = postgres:///auditor-basedb
[exchange-account-1] [exchange-account-1]
PAYTO_URI = payto://iban/SANDBOXX/DE989651?receiver-name=Exchange+Company PAYTO_URI = payto://iban/SANDBOXX/DE989651?receiver-name=Exchange+Company
enable_debit = yes ENABLE_DEBIT = YES
enable_credit = yes ENABLE_CREDIT = YES
[exchange-accountcredentials-1] [exchange-accountcredentials-1]
WIRE_GATEWAY_URL = http://localhost:8082/facades/test-facade/taler-wire-gateway/ WIRE_GATEWAY_URL = http://localhost:8082/facades/test-facade/taler-wire-gateway/
@ -16,24 +29,38 @@ WIRE_GATEWAY_AUTH_METHOD = basic
USERNAME = exchange USERNAME = exchange
PASSWORD = x PASSWORD = x
[merchant-account-merchant] [merchant]
PAYTO_URI = payto://x-taler-bank/localhost/42 WIREFORMAT = default
HONOR_default = YES DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1
ACTIVE_default = YES KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv
DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10
WIRE_TRANSFER_DELAY = 1 minute
FORCE_AUDIT = YES
[merchantdb-postgres]
CONFIG = postgres:///auditor-basedb
[merchant-exchange-default] [merchant-exchange-default]
MASTER_KEY = RKNMPRGXCX35H11WEYXDXYHPR7NX2QK9BG15MT0QEF75PC5KR470 MASTER_KEY = M4FGP18EQFXFGGFQ1AWXHACN2JX0SMVK9CNF6459Z1WG18JSN0BG
EXCHANGE_BASE_URL = http://localhost:8081/ EXCHANGE_BASE_URL = http://localhost:8081/
CURRENCY = TESTKUDOS CURRENCY = TESTKUDOS
[payments-generator] [bank]
currency = TESTKUDOS HTTP_PORT = 8082
instance = default
bank = http://localhost:8082/ [libeufin-nexus]
merchant = http://localhost:9966/ DB_CONNECTION="jdbc:postgresql://localhost/auditor-basedb?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432"
exchange_admin = http://localhost:18080/
exchange-admin = http://localhost:18080/ [libeufin-sandbox]
exchange = http://localhost:8081/ DB_CONNECTION="jdbc:postgresql://localhost/auditor-basedb?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432"
[auditor]
BASE_URL = http://localhost:8083/
TINY_AMOUNT = TESTKUDOS:0.01
PUBLIC_KEY = 0EHPW5WEKHXPPN4MPJNGA7Z6D29JP21GKVNV8ARFB1YW7WWJX20G
[auditordb-postgres]
CONFIG = postgres:///auditor-basedb
[coin_kudos_ct_1] [coin_kudos_ct_1]
value = TESTKUDOS:0.01 value = TESTKUDOS:0.01
@ -130,61 +157,3 @@ fee_refresh = TESTKUDOS:0.03
fee_refund = TESTKUDOS:0.01 fee_refund = TESTKUDOS:0.01
CIPHER = RSA CIPHER = RSA
rsa_keysize = 1024 rsa_keysize = 1024
[benchmark]
BANK_DETAILS = bank_details.json
MERCHANT_DETAILS = merchant_details.json
[arm]
CONFIG = /research/taler/exchange/src/auditor/auditor-basedb.conf
[taler]
CURRENCY_ROUND_UNIT = TESTKUDOS:0.01
CURRENCY = TESTKUDOS
AML_THRESHOLD = TESTKUDOS:1000000
[merchantdb-postgres]
CONFIG = postgres:///auditor-basedb
[merchant]
WIREFORMAT = default
DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1
KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv
DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10
WIRE_TRANSFER_DELAY = 1 minute
FORCE_AUDIT = YES
UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http
[exchangedb-postgres]
CONFIG = postgres:///auditor-basedb
[exchange]
MASTER_PUBLIC_KEY = RKNMPRGXCX35H11WEYXDXYHPR7NX2QK9BG15MT0QEF75PC5KR470
SIGNKEY_DURATION = 4 weeks
LOOKAHEAD_SIGN = 32 weeks 1 day
SIGNKEY_LEGAL_DURATION = 4 weeks
UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
[bank]
HTTP_PORT = 8082
SUGGESTED_EXCHANGE = http://localhost:8081/
SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2
ALLOW_REGISTRATIONS = YES
SERVE = http
MAX_DEBT_BANK = TESTKUDOS:100000.0
MAX_DEBT = TESTKUDOS:50.0
DATABASE = postgres:///auditor-basedb
[auditordb-postgres]
CONFIG = postgres:///auditor-basedb
[auditor]
BASE_URL = http://localhost:8083/
TINY_AMOUNT = TESTKUDOS:0.01
PUBLIC_KEY = 0EHPW5WEKHXPPN4MPJNGA7Z6D29JP21GKVNV8ARFB1YW7WWJX20G
[PATHS]
TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
TALER_HOME = ${PWD}/generate_auditordb_home/

View File

@ -1,412 +1,61 @@
#!/bin/bash #!/bin/bash
# Script to generate the basic database for auditor # This file is in the public domain.
# testing from a 'correct' interaction between exchange,
# wallet and merchant.
# #
# Creates $BASEDB.sql, $BASEDB.fees, # Script to generate the basic database for auditor testing from a 'correct'
# $BASEDB.{mpub,mpriv}. # interaction between exchange, wallet and merchant.
# Default $BASEDB is "auditor-basedb", override via $1.
# #
# Currently must be run online as it interacts with # Creates "$1.sql".
# bank.test.taler.net; also requires the wallet CLI #
# to be installed and in the path. Furthermore, the # Requires the wallet CLI to be installed and in the path. Furthermore, the
# user running this script must be Postgres superuser # user running this script must be Postgres superuser and be allowed to
# and be allowed to create/drop databases. # create/drop databases.
# #
set -eu set -eu
#set -x
# Cleanup to run whenever we exit
function exit_cleanup()
{
echo "Running generate-auditor-basedb exit cleanup logic..."
if test -f ${MY_TMP_DIR:-/}/libeufin-sandbox.pid
then
PID=`cat ${MY_TMP_DIR}/libeufin-sandbox.pid 2> /dev/null`
kill $PID 2> /dev/null || true
rm ${MY_TMP_DIR}/libeufin-sandbox.pid
echo "Killed libeufin sandbox $PID"
wait $PID || true
fi
if test -f ${MY_TMP_DIR:-/}/libeufin-nexus.pid
then
PID=`cat ${MY_TMP_DIR}/libeufin-nexus.pid 2> /dev/null`
kill $PID 2> /dev/null || true
rm ${MY_TMP_DIR}/libeufin-nexus.pid
echo "Killed libeufin nexus $PID"
wait $PID || true
fi
echo "killing libeufin DONE"
for n in `jobs -p`
do
kill $n 2> /dev/null || true
done
wait || true
}
# Install cleanup handler (except for kill -9)
trap exit_cleanup EXIT
# Exit, with status code "skip" (no 'real' failure)
function exit_skip() {
echo "SKIPPING: $1"
exit 77
}
# Where do we write the result? # Where do we write the result?
BASEDB=${1:-"auditor-basedb"} BASEDB="$1"
# Name of the Postgres database we will use for the script.
# Will be dropped, do NOT use anything that might be used
# elsewhere
export TARGET_DB=`basename ${BASEDB}`
export WALLET_DB=${BASEDB:-"wallet"}.wdb . setup.sh
# delete existing wallet database echo -n "Testing for curl ..."
rm -f $WALLET_DB
# Configuration file will be edited, so we create one
# from the template.
export CONF=$1.conf
cp generate-auditor-basedb.conf $CONF
echo "Created configuration at ${CONF}"
DATA_DIR=$1/exchange-data-dir/
mkdir -p $DATA_DIR
taler-config -c $CONF -s PATHS -o TALER_HOME -V $DATA_DIR
echo -n "Testing for libeufin"
libeufin-cli --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
echo -n "Testing for taler-wallet-cli"
taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
echo -n "Testing for curl"
curl --help >/dev/null </dev/null || exit_skip " MISSING" curl --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND" echo " FOUND"
CONF="generate-auditor-basedb.conf"
# reset database # reset database
dropdb $TARGET_DB >/dev/null 2>/dev/null || true echo -n "Reset 'auditor-basedb' database ..."
createdb $TARGET_DB || exit_skip "Could not create database $TARGET_DB" dropdb "auditor-basedb" >/dev/null 2>/dev/null || true
ORIGIN=`pwd` createdb "auditor-basedb" || exit_skip "Could not create database '$BASEDB'"
MY_TMP_DIR=`dirname $1` echo " DONE"
# Launch exchange, merchant and bank.
setup -c "$CONF" \
-aenmsw \
-d "iban"
# obtain key configuration data # obtain key configuration data
MASTER_PRIV_FILE=$1.mpriv EXCHANGE_URL=$(taler-config -c "$CONF" -s EXCHANGE -o BASE_URL)
MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` MERCHANT_PORT=$(taler-config -c "$CONF" -s MERCHANT -o PORT)
taler-config -f -c ${CONF} -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE} MERCHANT_URL="http://localhost:${MERCHANT_PORT}/"
rm -f "${MASTER_PRIV_FILE}" BANK_PORT=$(taler-config -c "$CONF" -s BANK -o HTTP_PORT)
mkdir -p $MASTER_PRIV_DIR
gnunet-ecc -l/dev/null -g1 $MASTER_PRIV_FILE > /dev/null
export MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE`
export EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL`
MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT`
export MERCHANT_URL=http://localhost:${MERCHANT_PORT}/
BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT`
BANK_URL="http://localhost:1${BANK_PORT}" BANK_URL="http://localhost:1${BANK_PORT}"
export AUDITOR_URL=http://localhost:8083/
AUDITOR_PRIV_FILE=$1.apriv
AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE`
taler-config -f -c ${CONF} -s auditor -o AUDITOR_PRIV_FILE -V ${AUDITOR_PRIV_FILE}
mkdir -p $AUDITOR_PRIV_DIR
gnunet-ecc -l/dev/null -g1 $AUDITOR_PRIV_FILE > /dev/null
AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE`
echo "MASTER PUB is ${MASTER_PUB} using file ${MASTER_PRIV_FILE}"
echo "AUDITOR PUB is ${AUDITOR_PUB} using file ${AUDITOR_PRIV_FILE}"
# patch configuration
taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB
taler-config -c $CONF -s auditor -o PUBLIC_KEY -V $AUDITOR_PUB
taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB
taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s bank -o database -V postgres:///$TARGET_DB
# setup exchange
echo "Setting up exchange"
taler-exchange-dbinit -c $CONF
echo "Setting up merchant"
taler-merchant-dbinit -c $CONF
# setup auditor
echo "Setting up auditor"
taler-auditor-dbinit -c $CONF || exit_skip "Failed to initialize auditor DB"
taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL || exit_skip "Failed to add exchange to auditor"
# Launch services
echo "Launching services (pre audit DB: $TARGET_DB)"
rm -rf ${TARGET_DB}-sandbox.sqlite3
export LIBEUFIN_SANDBOX_DB_CONNECTION="jdbc:sqlite:${TARGET_DB}-sandbox.sqlite3"
# Create the default demobank.
cd $MY_TMP_DIR
export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
libeufin-sandbox config --currency "TESTKUDOS" default
libeufin-sandbox serve --port "1${BANK_PORT}" \
> ${MY_TMP_DIR}/libeufin-sandbox-stdout.log \
2> ${MY_TMP_DIR}/libeufin-sandbox-stderr.log &
echo $! > ${MY_TMP_DIR}/libeufin-sandbox.pid
cd $ORIGIN
export LIBEUFIN_SANDBOX_URL="http://localhost:1${BANK_PORT}"
set +e
echo -n "Waiting for Sandbox..."
OK=0
for n in `seq 1 100`; do
echo -n "."
sleep 1
if wget --timeout=1 \
--user admin --password secret --auth-no-challenge \
--tries=3 --waitretry=0 \
-o /dev/null -O /dev/null \
${LIBEUFIN_SANDBOX_URL};
then
OK=1
break
fi
done
if test $OK != 1
then
exit_skip " Failed to launch sandbox"
fi
echo "OK"
register_sandbox_account() {
export LIBEUFIN_SANDBOX_USERNAME=$1
export LIBEUFIN_SANDBOX_PASSWORD=$2
cd $MY_TMP_DIR
libeufin-cli sandbox \
demobank \
register --name "$3"
cd $ORIGIN
unset LIBEUFIN_SANDBOX_USERNAME
unset LIBEUFIN_SANDBOX_PASSWORD
}
set -e
echo -n "Register the 'fortytwo' Sandbox user.."
register_sandbox_account fortytwo x "Forty Two"
echo OK
echo -n "Register the 'fortythree' Sandbox user.."
register_sandbox_account fortythree x "Forty Three"
echo OK
echo -n "Register 'exchange' Sandbox user.."
register_sandbox_account exchange x "Exchange Company"
echo OK
echo -n "Specify exchange's PAYTO_URI in the config ..."
export LIBEUFIN_SANDBOX_USERNAME=exchange
export LIBEUFIN_SANDBOX_PASSWORD=x
cd $MY_TMP_DIR
PAYTO=`libeufin-cli sandbox demobank info --bank-account exchange | jq --raw-output '.paytoUri'`
taler-config -c $CONF -s exchange-account-1 -o PAYTO_URI -V $PAYTO
echo " OK"
echo -n "Setting this exchange as the bank's default ..."
EXCHANGE_PAYTO=`libeufin-cli sandbox demobank info --bank-account exchange | jq --raw-output '.paytoUri'`
libeufin-sandbox default-exchange "$EXCHANGE_URL" "$EXCHANGE_PAYTO"
echo " OK"
# Prepare EBICS: create Ebics host and Exchange subscriber.
# Shortly becoming admin to setup Ebics.
export LIBEUFIN_SANDBOX_USERNAME=admin
export LIBEUFIN_SANDBOX_PASSWORD=secret
echo -n "Create EBICS host at Sandbox.."
libeufin-cli sandbox \
--sandbox-url "http://localhost:1${BANK_PORT}" \
ebicshost create --host-id "talerebics"
echo "OK"
echo -n "Create exchange EBICS subscriber at Sandbox.."
libeufin-cli sandbox \
demobank new-ebicssubscriber --host-id talerebics \
--user-id exchangeebics --partner-id talerpartner \
--bank-account exchange # that's a username _and_ a bank account name
echo "OK"
unset LIBEUFIN_SANDBOX_USERNAME
unset LIBEUFIN_SANDBOX_PASSWORD
# Prepare Nexus, which is the side actually talking
# to the exchange.
rm -rf ${TARGET_DB}-nexus.sqlite3
export LIBEUFIN_NEXUS_DB_CONNECTION="jdbc:sqlite:${TARGET_DB}-nexus.sqlite3"
# For convenience, username and password are
# identical to those used at the Sandbox.
echo -n "Create exchange Nexus user..."
libeufin-nexus superuser exchange --password x
echo " OK"
libeufin-nexus serve --port ${BANK_PORT} \
2> ${MY_TMP_DIR}/libeufin-nexus-stderr.log \
> ${MY_TMP_DIR}/libeufin-nexus-stdout.log &
echo $! > ${MY_TMP_DIR}/libeufin-nexus.pid
export LIBEUFIN_NEXUS_URL="http://localhost:${BANK_PORT}"
echo -n "Waiting for Nexus..."
set +e
OK=0
for n in `seq 1 50`; do
echo -n "."
sleep 1
if wget --timeout=1 \
--tries=3 --waitretry=0 \
-o /dev/null -O /dev/null \
$LIBEUFIN_NEXUS_URL;
then
OK=1
break
fi
done
if test $OK != 1
then
exit_skip " Failed to launch Nexus at $LIBEUFIN_NEXUS_URL"
fi
set -e
echo "OK"
export LIBEUFIN_NEXUS_USERNAME=exchange
export LIBEUFIN_NEXUS_PASSWORD=x
echo -n "Creating an EBICS connection at Nexus..."
libeufin-cli connections new-ebics-connection \
--ebics-url "http://localhost:1${BANK_PORT}/ebicsweb" \
--host-id "talerebics" \
--partner-id "talerpartner" \
--ebics-user-id "exchangeebics" \
talerconn
echo "OK"
echo -n "Setup EBICS keying..."
libeufin-cli connections connect "talerconn" > /dev/null
echo "OK"
echo -n "Download bank account name from Sandbox..."
libeufin-cli connections download-bank-accounts "talerconn"
echo "OK"
echo -n "Importing bank account info into Nexus..."
libeufin-cli connections import-bank-account \
--offered-account-id "exchange" \
--nexus-bank-account-id "exchange-nexus" \
"talerconn"
echo "OK"
echo -n "Setup payments submission task..."
# Tries every second.
libeufin-cli accounts task-schedule \
--task-type submit \
--task-name "exchange-payments" \
--task-cronspec "* * *" \
"exchange-nexus"
echo "OK"
# Tries every second. Ask C52
echo -n "Setup history fetch task..."
libeufin-cli accounts task-schedule \
--task-type fetch \
--task-name "exchange-history" \
--task-cronspec "* * *" \
--task-param-level report \
--task-param-range-type latest \
"exchange-nexus"
echo "OK"
# create Taler facade.
echo -n "Create the Taler facade at Nexus..."
libeufin-cli facades \
new-taler-wire-gateway-facade \
--currency "TESTKUDOS" --facade-name "test-facade" \
"talerconn" "exchange-nexus"
echo "OK"
cd $ORIGIN
# Facade schema: http://localhost:$BANK_PORT/facades/test-facade/taler-wire-gateway/
TFN=`which taler-exchange-httpd`
TBINPFX=`dirname $TFN`
TLIBEXEC=${TBINPFX}/../lib/taler/libexec/
taler-exchange-secmod-eddsa -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-eddsa.log &
taler-exchange-secmod-rsa -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-rsa.log &
taler-exchange-secmod-cs -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-cs.log &
taler-exchange-httpd -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-httpd.log &
taler-merchant-httpd -c $CONF -L INFO 2> ${MY_TMP_DIR}/taler-merchant-httpd.log &
taler-exchange-wirewatch -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-wirewatch.log &
taler-auditor-httpd -L INFO -c $CONF 2> ${MY_TMP_DIR}/taler-auditor-httpd.log &
export BANK_PORT
export EXCHANGE_URL
export MERCHANT_URL
export AUDITOR_URL
echo -n "Waiting for services to be available "
# Wait for all bank to be available (usually the slowest)
for n in `seq 1 50`
do
echo -n "."
sleep 0.2
OK=0
# bank
wget http://localhost:${BANK_PORT}/ -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
exit_skip "Failed to launch services (bank)"
fi
# Wait for all services to be available
for n in `seq 1 50`
do
echo -n "."
sleep 0.1
OK=0
# exchange
wget ${EXCHANGE_URL}seed -o /dev/null -O /dev/null >/dev/null || continue
# merchant
wget ${MERCHANT_URL} -o /dev/null -O /dev/null >/dev/null || continue
# Auditor
wget ${AUDITOR_URL} -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
bash
exit_skip "Failed to launch services (Taler)"
fi
echo -n "Setting up keys"
taler-exchange-offline -c $CONF \
download sign \
enable-account `taler-config -c $CONF -s exchange-account-1 -o PAYTO_URI` \
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
wire-fee now iban TESTKUDOS:0.07 TESTKUDOS:0.01 \
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1year 5 \
upload &> ${MY_TMP_DIR}/taler-exchange-offline.log
echo -n "."
for n in `seq 1 2`
do
echo -n "."
OK=0
wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
exit_skip "Failed to setup keys"
fi
echo " DONE"
echo -n "Adding auditor signatures ..."
taler-auditor-offline -c $CONF \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log
echo " DONE"
# Setup merchant
echo -n "Setting up merchant"
curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://iban/SANDBOXX/DE474361?receiver-name=Merchant43"}],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' http://localhost:9966/management/instances
echo -n "Setting up merchant ..."
curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://iban/SANDBOXX/DE474361?receiver-name=Merchant43"}],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' "${MERCHANT_URL}management/instances"
echo " DONE" echo " DONE"
# run wallet CLI # delete existing wallet database
echo "Running wallet" export WALLET_DB="wallet.wdb"
rm -f "$WALLET_DB"
taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api --expect-success 'runIntegrationTest' \ echo -n "Running wallet ..."
taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
api \
--expect-success \
'runIntegrationTest' \
"$(jq -n ' "$(jq -n '
{ {
amountToSpend: "TESTKUDOS:4", amountToSpend: "TESTKUDOS:4",
@ -418,28 +67,25 @@ taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api --expect-success 'runI
--arg MERCHANT_URL "$MERCHANT_URL" \ --arg MERCHANT_URL "$MERCHANT_URL" \
--arg EXCHANGE_URL "$EXCHANGE_URL" \ --arg EXCHANGE_URL "$EXCHANGE_URL" \
--arg BANK_URL "$BANK_URL/demobanks/default/access-api/" --arg BANK_URL "$BANK_URL/demobanks/default/access-api/"
)" &> ${MY_TMP_DIR}/taler-wallet-cli.log )" &> taler-wallet-cli.log
echo " DONE"
echo "Shutting down services"
exit_cleanup
# Dump database # Dump database
echo "Dumping database ${BASEDB}(-libeufin).sql" mkdir -p "$(dirname "$BASEDB")"
pg_dump -O $TARGET_DB | sed -e '/AS integer/d' > ${BASEDB}.sql
cd $MY_TMP_DIR
sqlite3 ${TARGET_DB}-nexus.sqlite3 ".dump" > ${BASEDB}-libeufin-nexus.sql
sqlite3 ${TARGET_DB}-sandbox.sqlite3 ".dump" > ${BASEDB}-libeufin-sandbox.sql
rm ${TARGET_DB}-sandbox.sqlite3 ${TARGET_DB}-nexus.sqlite3 # libeufin DB
cd $ORIGIN
echo $MASTER_PUB > ${BASEDB}.mpub echo "Dumping database ${BASEDB}.sql"
pg_dump -O "auditor-basedb" | sed -e '/AS integer/d' > "${BASEDB}.sql"
# clean up # clean up
echo "Final clean up" echo -n "Final clean up ..."
dropdb $TARGET_DB kill -TERM "$SETUP_PID"
wait
unset SETUP_PID
dropdb "auditor-basedb"
echo " DONE"
echo "=====================================" echo "====================================="
echo " Finished generation of $BASEDB" echo "Finished generation of ${BASEDB}.sql"
echo "=====================================" echo "====================================="
exit 0 exit 0

View File

@ -8,405 +8,50 @@
set -eu set -eu
# set -x # set -x
# Cleanup to run whenever we exit . setup.sh
function exit_cleanup()
{
echo "Running generate-revoke-basedb exit cleanup logic..."
if test -f ${MY_TMP_DIR:-/}/libeufin-sandbox.pid
then
PID=`cat ${MY_TMP_DIR}/libeufin-sandbox.pid 2> /dev/null`
kill $PID 2> /dev/null || true
rm ${MY_TMP_DIR}/libeufin-sandbox.pid
echo "Killed libeufin sandbox $PID"
wait $PID || true
fi
if test -f ${MY_TMP_DIR}/libeufin-nexus.pid
then
PID=`cat ${MY_TMP_DIR}/libeufin-nexus.pid 2> /dev/null`
kill $PID 2> /dev/null || true
rm ${MY_TMP_DIR}/libeufin-nexus.pid
echo "Killed libeufin nexus $PID"
wait $PID || true
fi
echo "killing libeufin DONE"
for n in `jobs -p`
do
kill $n 2> /dev/null || true
done
wait
}
function get_payto_uri() { echo -n "Testing for curl ..."
export LIBEUFIN_SANDBOX_USERNAME=$1
export LIBEUFIN_SANDBOX_PASSWORD=$2
export LIBEUFIN_SANDBOX_URL=$BANK_URL
cd $MY_TMP_DIR
libeufin-cli sandbox demobank info --bank-account $1 | jq --raw-output '.paytoUri'
cd $ORIGIN
}
# Install cleanup handler (except for kill -9)
trap exit_cleanup EXIT
# Exit, with status code "skip" (no 'real' failure)
function exit_skip() {
echo $1
exit 77
}
# Where do we write the result?
export BASEDB=${1:-"revoke-basedb"}
# Name of the Postgres database we will use for the script.
# Will be dropped, do NOT use anything that might be used
# elsewhere
export TARGET_DB=`basename ${BASEDB}`
TMP_DIR=`mktemp -d revocation-tmp-XXXXXX`
export WALLET_DB=wallet-revocation.json
rm -f $WALLET_DB
# Configuration file will be edited, so we create one
# from the template.
export CONF=${BASEDB}.conf
cp generate-auditor-basedb.conf $CONF
echo "Created configuration at ${CONF}"
DATA_DIR=$1/exchange-data-dir/
mkdir -p $DATA_DIR
taler-config -c $CONF -s PATHS -o TALER_HOME -V $DATA_DIR
echo -n "Testing for libeufin(-cli)"
libeufin-cli --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
echo -n "Testing for taler-wallet-cli"
taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
echo -n "Testing for curl"
curl --help >/dev/null </dev/null || exit_skip " MISSING" curl --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND" echo " FOUND"
# reset database CONF="generate-auditor-basedb.conf"
dropdb $TARGET_DB >/dev/null 2>/dev/null || true
createdb $TARGET_DB || exit_skip "Could not create database $TARGET_DB"
ORIGIN=`pwd`
MY_TMP_DIR=`dirname $1`
# reset database
echo -n "Reset 'auditor-basedb' database ..."
dropdb "auditor-basedb" >/dev/null 2>/dev/null || true
createdb "auditor-basedb" || exit_skip "Could not create database '$BASEDB'"
echo " DONE"
# Launch exchange, merchant and bank.
setup -c "$CONF" \
-aenmsw \
-d "iban"
# obtain key configuration data # obtain key configuration data
MASTER_PRIV_FILE=$1.mpriv EXCHANGE_URL=$(taler-config -c "$CONF" -s EXCHANGE -o BASE_URL)
MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` MERCHANT_PORT=$(taler-config -c "$CONF" -s MERCHANT -o PORT)
taler-config -f -c $CONF -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE} MERCHANT_URL="http://localhost:${MERCHANT_PORT}/"
mkdir -p $MASTER_PRIV_DIR BANK_PORT=$(taler-config -c "$CONF" -s BANK -o HTTP_PORT)
rm -f "${MASTER_PRIV_FILE}" BANK_URL="http://localhost:1${BANK_PORT}"
gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null
export MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE`
export EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL`
MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT`
export MERCHANT_URL=http://localhost:${MERCHANT_PORT}/
BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT`
export BANK_URL=http://localhost:1${BANK_PORT}
export AUDITOR_URL=http://localhost:8083/
AUDITOR_PRIV_FILE=$1.apriv
AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE`
taler-config -f -c ${CONF} -s auditor -o AUDITOR_PRIV_FILE -V ${AUDITOR_PRIV_FILE}
mkdir -p $AUDITOR_PRIV_DIR
gnunet-ecc -l /dev/null -g1 $AUDITOR_PRIV_FILE > /dev/null
AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE`
echo "MASTER PUB is ${MASTER_PUB} using file ${MASTER_PRIV_FILE}"
echo "AUDITOR PUB is ${AUDITOR_PUB} using file ${AUDITOR_PRIV_FILE}"
# patch configuration
taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB
taler-config -c $CONF -s auditor -o PUBLIC_KEY -V $AUDITOR_PUB
taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB
taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TARGET_DB
taler-config -c $CONF -s bank -o database -V postgres:///$TARGET_DB
taler-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/"
taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/"
# setup exchange
echo "Setting up exchange"
taler-exchange-dbinit -c $CONF
echo "Setting up merchant"
taler-merchant-dbinit -c $CONF
# setup auditor
echo "Setting up auditor"
taler-auditor-dbinit -c $CONF
taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL
# Launch services
echo "Launching services"
export LIBEUFIN_SANDBOX_DB_CONNECTION="jdbc:sqlite:${TARGET_DB}-sandbox.sqlite3"
# Create the default demobank.
cd $MY_TMP_DIR
export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=secret
libeufin-sandbox config --currency "TESTKUDOS" default
libeufin-sandbox serve --port "1${BANK_PORT}" \
> ${MY_TMP_DIR}/libeufin-sandbox-stdout.log \
2> ${MY_TMP_DIR}/libeufin-sandbox-stderr.log &
echo $! > ${MY_TMP_DIR}/libeufin-sandbox.pid
cd $ORIGIN
export LIBEUFIN_SANDBOX_URL="http://localhost:1${BANK_PORT}"
set +e
echo -n "Waiting for Sandbox..."
OK=0
for n in `seq 1 50`; do
echo -n "."
sleep 1
if wget --timeout=1 \
--user admin --password secret --auth-no-challenge \
--tries=3 --waitretry=0 \
-o /dev/null -O /dev/null \
${LIBEUFIN_SANDBOX_URL};
then
OK=1
break
fi
done
if test $OK != 1
then
exit_skip " Failed to launch sandbox"
fi
echo "OK"
register_sandbox_account() {
export LIBEUFIN_SANDBOX_USERNAME=$1
export LIBEUFIN_SANDBOX_PASSWORD=$2
cd $MY_TMP_DIR
libeufin-cli sandbox \
demobank \
register --name "$3"
cd $ORIGIN
unset LIBEUFIN_SANDBOX_USERNAME
unset LIBEUFIN_SANDBOX_PASSWORD
}
set -e
echo -n "Register the 'fortytwo' Sandbox user.."
register_sandbox_account fortytwo x "Forty Two"
echo OK
echo -n "Register the 'fortythree' Sandbox user.."
register_sandbox_account fortythree x "Forty Three"
echo OK
echo -n "Register 'exchange' Sandbox user.."
register_sandbox_account exchange x "Exchange Company"
echo OK
echo -n "Specify exchange's PAYTO_URI in the config ..."
export LIBEUFIN_SANDBOX_USERNAME=exchange
export LIBEUFIN_SANDBOX_PASSWORD=x
cd $MY_TMP_DIR
PAYTO=`libeufin-cli sandbox demobank info --bank-account exchange | jq --raw-output '.paytoUri'`
taler-config -c $CONF -s exchange-account-1 -o PAYTO_URI -V $PAYTO
echo " OK"
echo -n "Setting this exchange as the bank's default ..."
EXCHANGE_PAYTO=`libeufin-cli sandbox demobank info --bank-account exchange | jq --raw-output '.paytoUri'`
libeufin-sandbox default-exchange "$EXCHANGE_URL" "$EXCHANGE_PAYTO"
echo " OK"
# Prepare EBICS: create Ebics host and Exchange subscriber.
# Shortly becoming admin to setup Ebics.
export LIBEUFIN_SANDBOX_USERNAME=admin
export LIBEUFIN_SANDBOX_PASSWORD=secret
echo -n "Create EBICS host at Sandbox.."
libeufin-cli sandbox \
--sandbox-url "http://localhost:1${BANK_PORT}" \
ebicshost create --host-id "talerebics"
echo "OK"
echo -n "Create exchange EBICS subscriber at Sandbox.."
libeufin-cli sandbox \
demobank new-ebicssubscriber --host-id talerebics \
--user-id exchangeebics --partner-id talerpartner \
--bank-account exchange # that's a username _and_ a bank account name
echo "OK"
unset LIBEUFIN_SANDBOX_USERNAME
unset LIBEUFIN_SANDBOX_PASSWORD
# Prepare Nexus, which is the side actually talking
# to the exchange.
export LIBEUFIN_NEXUS_DB_CONNECTION="jdbc:sqlite:${TARGET_DB}-nexus.sqlite3"
# For convenience, username and password are
# identical to those used at the Sandbox.
echo -n "Create exchange Nexus user..."
libeufin-nexus superuser exchange --password x
echo " OK"
libeufin-nexus serve --port ${BANK_PORT} \
2> ${MY_TMP_DIR}/libeufin-nexus-stderr.log \
> ${MY_TMP_DIR}/libeufin-nexus-stdout.log &
echo $! > ${MY_TMP_DIR}/libeufin-nexus.pid
export LIBEUFIN_NEXUS_URL="http://localhost:${BANK_PORT}"
echo -n "Waiting for Nexus..."
set +e
OK=0
for n in `seq 1 50`; do
echo -n "."
sleep 1
if wget --timeout=1 \
--tries=3 --waitretry=0 \
-o /dev/null -O /dev/null \
$LIBEUFIN_NEXUS_URL;
then
OK=1
break
fi
done
if test $OK != 1
then
exit_skip " Failed to launch Nexus at $LIBEUFIN_NEXUS_URL"
fi
set -e
echo "OK"
export LIBEUFIN_NEXUS_USERNAME=exchange
export LIBEUFIN_NEXUS_PASSWORD=x
echo -n "Creating an EBICS connection at Nexus..."
libeufin-cli connections new-ebics-connection \
--ebics-url "http://localhost:1${BANK_PORT}/ebicsweb" \
--host-id "talerebics" \
--partner-id "talerpartner" \
--ebics-user-id "exchangeebics" \
talerconn
echo "OK"
echo -n "Setup EBICS keying..."
libeufin-cli connections connect "talerconn" > /dev/null
echo "OK"
echo -n "Download bank account name from Sandbox..."
libeufin-cli connections download-bank-accounts "talerconn"
echo "OK"
echo -n "Importing bank account info into Nexus..."
libeufin-cli connections import-bank-account \
--offered-account-id "exchange" \
--nexus-bank-account-id "exchange-nexus" \
"talerconn"
echo "OK"
echo -n "Setup payments submission task..."
# Tries every second.
libeufin-cli accounts task-schedule \
--task-type submit \
--task-name "exchange-payments" \
--task-cronspec "* * *" \
"exchange-nexus"
echo "OK"
# Tries every second. Ask C52
echo -n "Setup history fetch task..."
libeufin-cli accounts task-schedule \
--task-type fetch \
--task-name "exchange-history" \
--task-cronspec "* * *" \
--task-param-level report \
--task-param-range-type latest \
"exchange-nexus"
echo "OK"
# create Taler facade.
echo -n "Create the Taler facade at Nexus..."
libeufin-cli facades \
new-taler-wire-gateway-facade \
--currency "TESTKUDOS" --facade-name "test-facade" \
"talerconn" "exchange-nexus"
echo "OK"
cd $ORIGIN
# Facade schema: http://localhost:$BANK_PORT/facades/test-facade/taler-wire-gateway/
TFN=`which taler-exchange-httpd`
TBINPFX=`dirname $TFN`
TLIBEXEC=${TBINPFX}/../lib/taler/libexec/
taler-exchange-secmod-eddsa -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-eddsa.log &
SIGNKEY_HELPER_PID=$!
taler-exchange-secmod-rsa -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-rsa.log &
RSA_DENOM_HELPER_PID=$!
taler-exchange-secmod-cs -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-secmod-cs.log &
CS_DENOM_HELPER_PID=$!
taler-exchange-httpd -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-httpd.log &
EXCHANGE_PID=$!
taler-merchant-httpd -c $CONF -L INFO 2> ${MY_TMP_DIR}/taler-merchant-httpd.log &
MERCHANT_PID=$!
taler-exchange-wirewatch -c $CONF 2> ${MY_TMP_DIR}/taler-exchange-wirewatch.log &
taler-auditor-httpd -c $CONF 2> ${MY_TMP_DIR}/taler-auditor-httpd.log &
# Wait for all bank to be available (usually the slowest)
for n in `seq 1 50`
do
echo -n "."
sleep 0.2
OK=0
# bank
wget http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
exit_skip "Failed to launch Bank services"
fi
# Wait for all other services to be available
for n in `seq 1 50`
do
echo -n "."
sleep 0.1
OK=0
# exchange
wget http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue
# merchant
wget http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue
# Auditor
wget http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
exit_cleanup
exit_skip "Failed to launch Taler services"
fi
echo " DONE"
echo -n "Setting up keys"
taler-exchange-offline -c $CONF \
download sign \
enable-account `taler-config -c $CONF -s exchange-account-1 -o PAYTO_URI` \
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
wire-fee now iban TESTKUDOS:0.01 TESTKUDOS:0.01 \
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1year 5 \
upload &> ${MY_TMP_DIR}/taler-exchange-offline.log
echo -n "."
for n in `seq 1 2`
do
echo -n "."
OK=0
# bank
wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue
OK=1
break
done
if [ 1 != $OK ]
then
exit_skip "Failed to setup keys"
fi
taler-auditor-offline -c $CONF \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log
echo " DONE"
# Setup merchant # Setup merchant
echo -n "Setting up merchant" echo -n "Setting up merchant ..."
curl -H "Content-Type: application/json" -X POST -d '{"auth": {"method": "external"}, "accounts":[{"payto_uri":"payto://iban/SANDBOXX/DE474361?receiver-name=Merchant43"}],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' "${MERCHANT_URL}management/instances"
curl -H "Content-Type: application/json" -X POST -d '{"auth": {"method": "external"}, "accounts":[{"payto_uri":"payto://iban/SANDBOXX/DE474361?receiver-name=Merchant43"}],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' http://localhost:9966/management/instances echo " DONE"
# run wallet CLI # run wallet CLI
echo "Running wallet" echo "Running wallet"
taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api --expect-success 'withdrawTestBalance' \ export WALLET_DB="wallet.wdb"
rm -f "$WALLET_DB"
taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
api \
--expect-success 'withdrawTestBalance' \
"$(jq -n ' "$(jq -n '
{ {
amount: "TESTKUDOS:8", amount: "TESTKUDOS:8",
@ -414,57 +59,85 @@ taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api --expect-success 'with
exchangeBaseUrl: $EXCHANGE_URL, exchangeBaseUrl: $EXCHANGE_URL,
}' \ }' \
--arg BANK_URL "$BANK_URL/demobanks/default/access-api/" \ --arg BANK_URL "$BANK_URL/demobanks/default/access-api/" \
--arg EXCHANGE_URL $EXCHANGE_URL --arg EXCHANGE_URL "$EXCHANGE_URL"
)" )" &> taler-wallet-cli-withdraw.log
taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB run-until-done taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
run-until-done \
&> taler-wallet-cli-withdraw-finish.log
export coins=$(taler-wallet-cli --wallet-db=$WALLET_DB advanced dump-coins) export COINS=$(taler-wallet-cli --wallet-db="$WALLET_DB" advanced dump-coins)
echo -n "COINS are:" echo -n "COINS are:"
echo $coins echo "$COINS"
# Find coin we want to revoke # Find coin we want to revoke
export rc=$(echo "$coins" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .coin_pub') export rc=$(echo "$COINS" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .coin_pub')
# Find the denom # Find the denom
export rd=$(echo "$coins" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .denom_pub_hash') export rd=$(echo "$COINS" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .denom_pub_hash')
echo "Revoking denomination ${rd} (to affect coin ${rc})" echo -n "Revoking denomination ${rd} (to affect coin ${rc}) ..."
# Find all other coins, which will be suspended # Find all other coins, which will be suspended
export susp=$(echo "$coins" | jq --arg rc "$rc" '[.coins[] | select(.coin_pub != $rc) | .coin_pub]') export susp=$(echo "$COINS" | jq --arg rc "$rc" '[.coins[] | select(.coin_pub != $rc) | .coin_pub]')
# Do the revocation # Do the revocation
taler-exchange-offline -c $CONF \ taler-exchange-offline \
revoke-denomination "${rd}" upload &> ${MY_TMP_DIR}/taler-exchange-offline-revoke.log -c $CONF \
revoke-denomination "${rd}" \
upload \
&> taler-exchange-offline-revoke.log
echo "DONE"
echo -n "Signing replacement keys ..."
sleep 1 # Give exchange time to create replacmenent key sleep 1 # Give exchange time to create replacmenent key
# Re-sign replacement keys # Re-sign replacement keys
taler-auditor-offline -c $CONF \ taler-auditor-offline \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log -c $CONF \
download \
sign \
upload \
&> taler-auditor-offline-reinit.log
echo " DONE"
# Now we suspend the other coins, so later we will pay with the recouped coin # Now we suspend the other coins, so later we will pay with the recouped coin
taler-wallet-cli --wallet-db=$WALLET_DB advanced suspend-coins "$susp" taler-wallet-cli \
--wallet-db="$WALLET_DB" \
advanced \
suspend-coins "$susp"
# Update exchange /keys so recoup gets scheduled # Update exchange /keys so recoup gets scheduled
taler-wallet-cli --wallet-db=$WALLET_DB exchanges update \ taler-wallet-cli \
-f $EXCHANGE_URL --wallet-db="$WALLET_DB" \
exchanges \
update \
-f "$EXCHANGE_URL"
# Block until scheduled operations are done # Block until scheduled operations are done
taler-wallet-cli --wallet-db=$WALLET_DB run-until-done taler-wallet-cli \
--wallet-db="$WALLET_DB"\
run-until-done
# Now we buy something, only the coins resulting from recouped will be # Now we buy something, only the coins resulting from recoup will be
# used, as other ones are suspended # used, as other ones are suspended
taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'testPay' \ taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
api \
'testPay' \
"$(jq -n ' "$(jq -n '
{ {
amount: "TESTKUDOS:1", amount: "TESTKUDOS:1",
merchantBaseUrl: $MERCHANT_URL, merchantBaseUrl: $MERCHANT_URL,
summary: "foo", summary: "foo",
}' \ }' \
--arg MERCHANT_URL $MERCHANT_URL --arg MERCHANT_URL "$MERCHANT_URL"
)" )"
taler-wallet-cli --wallet-db=$WALLET_DB run-until-done taler-wallet-cli \
--wallet-db="$WALLET_DB" \
run-until-done
echo "Purchase with recoup'ed coin (via reserve) done" echo "Purchase with recoup'ed coin (via reserve) done"
@ -477,9 +150,6 @@ echo "Will refresh coin ${rrc} of denomination ${zombie_denom}"
# Find all other coins, which will be suspended # Find all other coins, which will be suspended
export susp=$(echo "$coins" | jq --arg rrc "$rrc" '[.coins[] | select(.coin_pub != $rrc) | .coin_pub]') export susp=$(echo "$coins" | jq --arg rrc "$rrc" '[.coins[] | select(.coin_pub != $rrc) | .coin_pub]')
export rrc
export zombie_denom
# Travel into the future! (must match DURATION_WITHDRAW option) # Travel into the future! (must match DURATION_WITHDRAW option)
export TIMETRAVEL="--timetravel=604800000000" export TIMETRAVEL="--timetravel=604800000000"
@ -510,8 +180,15 @@ do
done done
echo "Refreshing coin $rrc" echo "Refreshing coin $rrc"
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced force-refresh "$rrc" taler-wallet-cli \
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB run-until-done "$TIMETRAVEL" \
--wallet-db="$WALLET_DB" \
advanced force-refresh \
"$rrc"
taler-wallet-cli \
"$TIMETRAVEL" \
--wallet-db="$WALLET_DB" \
run-until-done
# Update our list of the coins # Update our list of the coins
export coins=$(taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced dump-coins) export coins=$(taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced dump-coins)
@ -534,29 +211,49 @@ export susp=$(echo "$coins" | jq --arg freshc "$freshc" '[.coins[] | select(.coi
# Do the revocation of freshc # Do the revocation of freshc
echo "Revoking ${fresh_denom} (to affect coin ${freshc})" echo "Revoking ${fresh_denom} (to affect coin ${freshc})"
taler-exchange-offline -c $CONF \ taler-exchange-offline \
revoke-denomination "${fresh_denom}" upload &> ${MY_TMP_DIR}/taler-exchange-offline-revoke-2.log -c "$CONF" \
revoke-denomination \
"${fresh_denom}" \
upload &> taler-exchange-offline-revoke-2.log
sleep 1 # Give exchange time to create replacmenent key sleep 1 # Give exchange time to create replacmenent key
# Re-sign replacement keys # Re-sign replacement keys
taler-auditor-offline -c $CONF \ taler-auditor-offline \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log -c "$CONF" \
download \
sign \
upload &> taler-auditor-offline.log
# Now we suspend the other coins, so later we will pay with the recouped coin # Now we suspend the other coins, so later we will pay with the recouped coin
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced suspend-coins "$susp" taler-wallet-cli \
"$TIMETRAVEL" \
--wallet-db="$WALLET_DB" \
advanced \
suspend-coins "$susp"
# Update exchange /keys so recoup gets scheduled # Update exchange /keys so recoup gets scheduled
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB exchanges update \ taler-wallet-cli \
-f $EXCHANGE_URL "$TIMETRAVEL"\
--wallet-db="$WALLET_DB" \
exchanges update \
-f "$EXCHANGE_URL"
# Block until scheduled operations are done # Block until scheduled operations are done
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB run-until-done taler-wallet-cli \
"$TIMETRAVEL" \
--wallet-db="$WALLET_DB" \
run-until-done
echo "Restarting merchant (so new keys are known)" echo "Restarting merchant (so new keys are known)"
kill -TERM $MERCHANT_PID kill -TERM $MERCHANT_PID
taler-merchant-httpd -c $CONF -L INFO 2> ${MY_TMP_DIR}/taler-merchant-httpd.log & taler-merchant-httpd \
-c "$CONF" \
-L INFO \
2> ${MY_TMP_DIR}/taler-merchant-httpd.log &
MERCHANT_PID=$! MERCHANT_PID=$!
# Wait for merchant to be again available # Wait for merchant to be again available
for n in `seq 1 50` for n in `seq 1 50`
do do
@ -580,7 +277,10 @@ taler-wallet-cli $TIMETRAVEL --no-throttle --wallet-db=$WALLET_DB api 'testPay'
}' \ }' \
--arg MERCHANT_URL $MERCHANT_URL --arg MERCHANT_URL $MERCHANT_URL
)" )"
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB run-until-done taler-wallet-cli \
"$TIMETRAVEL" \
--wallet-db="$WALLET_DB" \
run-until-done
echo "Bought something with refresh-recouped coin" echo "Bought something with refresh-recouped coin"
@ -588,26 +288,24 @@ echo "Shutting down services"
exit_cleanup exit_cleanup
# Where do we write the result?
export BASEDB=${1:-"revoke-basedb"}
# Dump database # Dump database
echo "Dumping database" echo "Dumping database ${BASEDB}.sql"
echo "Dumping PostgreSQL database: ${BASEDB}.sql" pg_dump -O "auditor-basedb" | sed -e '/AS integer/d' > "${BASEDB}.sql"
pg_dump -O $TARGET_DB | sed -e '/AS integer/d' > ${BASEDB}.sql
echo "Dumping libeufin database: ${TARGET_DB}-libeufin-*.sql"
cd $MY_TMP_DIR
sqlite3 ${TARGET_DB}-nexus.sqlite3 ".dump" > ${BASEDB}-libeufin-nexus.sql
sqlite3 ${TARGET_DB}-sandbox.sqlite3 ".dump" > ${BASEDB}-libeufin-sandbox.sql
rm ${TARGET_DB}-sandbox.sqlite3 ${TARGET_DB}-nexus.sqlite3 # libeufin DB # clean up
echo -n "Final clean up ..."
cd $ORIGIN kill -TERM "$SETUP_PID"
wait
echo $MASTER_PUB > ${BASEDB}.mpub unset SETUP_PID
dropdb "auditor-basedb"
echo "Final clean up" echo " DONE"
dropdb $TARGET_DB
echo "=====================================" echo "====================================="
echo " Finished generation of $BASEDB " echo "Finished generation of ${BASEDB}.sql"
echo "=====================================" echo "====================================="
exit 0 exit 0

View File

@ -0,0 +1 @@
%I7qYÿ®ÜX˜2@–šò%'1†”ÂOàÔæJ³Ô¦‘

72
src/auditor/setup.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
# This file is in the public domain
# Script to be inlined into the main test scripts. Defines function 'setup()'
# which wraps around 'taler-unified-setup.sh' to launch GNU Taler services.
# Call setup() with the arguments to pass to 'taler-unified-setup'. setup()
# will then launch GNU Taler, wait for the process to be complete before
# returning. The script will also install an exit handler to ensure the GNU
# Taler processes are stopped when the shell exits.
set -eu
# Cleanup to run whenever we exit
function exit_cleanup()
{
if [ ! -z ${SETUP_PID+x} ]
then
echo "Killing taler-unified-setup ($SETUP_PID)" >&2
kill -TERM "$SETUP_PID"
wait
fi
}
# Install cleanup handler (except for kill -9)
trap exit_cleanup EXIT
function setup()
{
echo "Starting test system ..." >&2
# Create a named pipe in a temp directory we own.
FIFO_DIR=$(mktemp -d fifo-XXXXXX)
FIFO_OUT=$(echo "$FIFO_DIR/out")
mkfifo "$FIFO_OUT"
# Open pipe as FD 3 (RW) and FD 4 (RO)
exec 3<> "$FIFO_OUT" 4< "$FIFO_OUT"
rm -rf "$FIFO_DIR"
# We require '-W' for our termination logic to work.
taler-unified-setup.sh -W "$@" >&3 &
SETUP_PID=$!
# Close FD3
exec 3>&-
sed -u '/<<READY>>/ q' <&4
# Close FD4
exec 4>&-
echo "Test system ready" >&2
}
# Exit, with status code "skip" (no 'real' failure)
function exit_fail() {
echo "$@" >&2
exit 1
}
# Exit, with status code "skip" (no 'real' failure)
function exit_skip() {
echo "SKIPPING: $1"
exit 77
}
function get_payto_uri() {
export LIBEUFIN_SANDBOX_USERNAME="$1"
export LIBEUFIN_SANDBOX_PASSWORD="$2"
export LIBEUFIN_SANDBOX_URL="http://localhost:18082"
libeufin-cli sandbox demobank info --bank-account "$1" | jq --raw-output '.paytoUri'
}
function get_bankaccount_transactions() {
export LIBEUFIN_SANDBOX_USERNAME=$1
export LIBEUFIN_SANDBOX_PASSWORD=$2
export LIBEUFIN_SANDBOX_URL="http://localhost:18082"
libeufin-cli sandbox demobank list-transactions --bank-account $1
}

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# #
# This file is part of TALER # This file is part of TALER
# Copyright (C) 2014-2022 Taler Systems SA # Copyright (C) 2014-2023 Taler Systems SA
# #
# TALER is free software; you can redistribute it and/or modify it under the # 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 # terms of the GNU General Public License as published by the Free Software
@ -49,17 +49,7 @@ VALGRIND=""
# history request. # history request.
LIBEUFIN_SETTLE_TIME=1 LIBEUFIN_SETTLE_TIME=1
# Exit, with status code "skip" (no 'real' failure) . setup.sh
function exit_skip() {
echo "SKIPPING test: $1"
exit 77
}
# Exit, with error message (hard failure)
function exit_fail() {
echo "FAILING test: $1"
exit 1
}
# Stop libeufin sandbox and nexus (if running) # Stop libeufin sandbox and nexus (if running)
function stop_libeufin() function stop_libeufin()
@ -2002,12 +1992,12 @@ function check_with_database()
{ {
BASEDB=$1 BASEDB=$1
CONF=$1.conf CONF=$1.conf
ORIGIN=`pwd` ORIGIN=$(pwd)
MY_TMP_DIR=`dirname $1` MY_TMP_DIR=$(dirname $1)
echo "Running test suite with database $BASEDB using configuration $CONF" echo "Running test suite with database $BASEDB using configuration $CONF"
MASTER_PRIV_FILE=${BASEDB}.mpriv MASTER_PRIV_FILE=${BASEDB}.mpriv
taler-config -f -c ${CONF} -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE} taler-config -f -c ${CONF} -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE}
MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE` MASTER_PUB=$(gnunet-ecc -p $MASTER_PRIV_FILE)
echo "MASTER PUB is ${MASTER_PUB} using file ${MASTER_PRIV_FILE}" echo "MASTER PUB is ${MASTER_PUB} using file ${MASTER_PRIV_FILE}"
@ -2037,7 +2027,7 @@ function check_with_database()
# ####### Setup globals ###### # ####### Setup globals ######
# Postgres database to use # Postgres database to use
export DB=auditor-basedb export DB="auditor-basedb"
# test required commands exist # test required commands exist
echo "Testing for jq" echo "Testing for jq"
@ -2059,12 +2049,12 @@ INITDB_BIN=$(command -v initdb) || true
if [[ ! -z "$INITDB_BIN" ]]; then if [[ ! -z "$INITDB_BIN" ]]; then
echo " FOUND (in path) at" $INITDB_BIN echo " FOUND (in path) at" $INITDB_BIN
else else
HAVE_INITDB=`find /usr -name "initdb" | head -1 2> /dev/null | grep postgres` || exit_skip " MISSING" HAVE_INITDB=$(find /usr -name "initdb" | head -1 2> /dev/null | grep postgres) || exit_skip " MISSING"
echo " FOUND at" `dirname $HAVE_INITDB` echo " FOUND at" $(dirname $HAVE_INITDB)
INITDB_BIN=`echo $HAVE_INITDB | grep bin/initdb | grep postgres | sort -n | tail -n1` INITDB_BIN=$(echo $HAVE_INITDB | grep bin/initdb | grep postgres | sort -n | tail -n1)
fi fi
POSTGRES_PATH=`dirname $INITDB_BIN` POSTGRES_PATH=$(dirname $INITDB_BIN)
MYDIR=`mktemp -d /tmp/taler-auditor-basedbXXXXXX` MYDIR=$(mktemp -d /tmp/taler-auditor-basedbXXXXXX)
echo "Using $MYDIR for logging and temporary data" echo "Using $MYDIR for logging and temporary data"
TMPDIR="$MYDIR/postgres/" TMPDIR="$MYDIR/postgres/"
mkdir -p $TMPDIR mkdir -p $TMPDIR
@ -2089,9 +2079,9 @@ PGHOST="$TMPDIR/sockets"
export PGHOST export PGHOST
echo "Generating fresh database at $MYDIR" echo "Generating fresh database at $MYDIR"
if faketime -f '-1 d' ./generate-auditor-basedb.sh $MYDIR/$DB if faketime -f '-1 d' ./generate-auditor-basedb.sh "$MYDIR/$DB"
then then
check_with_database $MYDIR/$DB check_with_database "$MYDIR/$DB"
if test x$fail != x0 if test x$fail != x0
then then
exit $fail exit $fail

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2020-2021 Taler Systems SA Copyright (C) 2020-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU General Public License as published by the Free Software
@ -174,7 +174,7 @@ static struct DenominationAddRequest *dar_tail;
/** /**
* Handle to the exchange, used to request /keys. * Handle to the exchange, used to request /keys.
*/ */
static struct TALER_EXCHANGE_Handle *exchange; static struct TALER_EXCHANGE_GetKeysHandle *exchange;
/** /**
@ -219,7 +219,7 @@ do_shutdown (void *cls)
} }
if (NULL != exchange) if (NULL != exchange)
{ {
TALER_EXCHANGE_disconnect (exchange); TALER_EXCHANGE_get_keys_cancel (exchange);
exchange = NULL; exchange = NULL;
} }
if (NULL != nxt) if (NULL != nxt)
@ -646,22 +646,23 @@ do_upload (char *const *args)
* *
* @param cls closure with the `char **` remaining args * @param cls closure with the `char **` remaining args
* @param kr response data * @param kr response data
* @param keys key data from the exchange
*/ */
static void static void
keys_cb ( keys_cb (
void *cls, void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr) const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys)
{ {
char *const *args = cls; char *const *args = cls;
exchange = NULL;
switch (kr->hr.http_status) switch (kr->hr.http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (! json_is_object (kr->hr.reply)) if (NULL == kr->hr.reply)
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
test_shutdown (); test_shutdown ();
global_ret = EXIT_FAILURE; global_ret = EXIT_FAILURE;
return; return;
@ -673,8 +674,6 @@ keys_cb (
kr->hr.hint, kr->hr.hint,
kr->hr.http_status, kr->hr.http_status,
(unsigned int) kr->hr.ec); (unsigned int) kr->hr.ec);
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
test_shutdown (); test_shutdown ();
global_ret = EXIT_FAILURE; global_ret = EXIT_FAILURE;
return; return;
@ -692,9 +691,8 @@ keys_cb (
json_decref (in); json_decref (in);
in = NULL; in = NULL;
} }
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
next (args); next (args);
TALER_EXCHANGE_keys_decref (keys);
} }
@ -721,11 +719,11 @@ do_download (char *const *args)
global_ret = EXIT_NOTCONFIGURED; global_ret = EXIT_NOTCONFIGURED;
return; return;
} }
exchange = TALER_EXCHANGE_connect (ctx, exchange = TALER_EXCHANGE_get_keys (ctx,
exchange_url, exchange_url,
&keys_cb, NULL,
(void *) args, &keys_cb,
TALER_EXCHANGE_OPTION_END); (void *) args);
GNUNET_free (exchange_url); GNUNET_free (exchange_url);
} }

View File

@ -20,8 +20,8 @@ KYC_AML_TRIGGER = true
# in the database. Should be a high-entropy nonce. # in the database. Should be a high-entropy nonce.
ATTRIBUTE_ENCRYPTION_KEY = SET_ME_PLEASE ATTRIBUTE_ENCRYPTION_KEY = SET_ME_PLEASE
# Set to NO to disable tipping. # Set to NO to disable rewards.
ENABLE_TIPPING = YES ENABLE_REWARDS = YES
# How long do we allow /keys to be cached at most? The actual # How long do we allow /keys to be cached at most? The actual
# limit is the minimum of this value and the first expected # limit is the minimum of this value and the first expected

View File

@ -161,9 +161,9 @@ char *TEH_currency;
char *TEH_kyc_aml_trigger; char *TEH_kyc_aml_trigger;
/** /**
* Option set to #GNUNET_YES if tipping is enabled. * Option set to #GNUNET_YES if rewards are enabled.
*/ */
int TEH_enable_tipping; int TEH_enable_rewards;
/** /**
* What is the largest amount we allow a peer to * What is the largest amount we allow a peer to
@ -1943,15 +1943,15 @@ exchange_serve_process_config (void)
"Amount in section `exchange' under `AML_THRESHOLD' uses the wrong currency!\n"); "Amount in section `exchange' under `AML_THRESHOLD' uses the wrong currency!\n");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
TEH_enable_tipping TEH_enable_rewards
= GNUNET_CONFIGURATION_get_value_yesno ( = GNUNET_CONFIGURATION_get_value_yesno (
TEH_cfg, TEH_cfg,
"exchange", "exchange",
"ENABLE_TIPPING"); "ENABLE_REWARDS");
if (GNUNET_SYSERR == TEH_enable_tipping) if (GNUNET_SYSERR == TEH_enable_rewards)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Need YES or NO in section `exchange' under `ENABLE_TIPPING'\n"); "Need YES or NO in section `exchange' under `ENABLE_REWARDS'\n");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (GNUNET_OK !=

View File

@ -65,9 +65,9 @@ extern int TEH_check_invariants_flag;
extern int TEH_allow_keys_timetravel; extern int TEH_allow_keys_timetravel;
/** /**
* Option set to #GNUNET_YES if tipping is enabled. * Option set to #GNUNET_YES if rewards are allowed.
*/ */
extern int TEH_enable_tipping; extern int TEH_enable_rewards;
/** /**
* Main directory with revocation data. * Main directory with revocation data.

View File

@ -106,7 +106,7 @@ free_age_withdraw_context_resources (struct AgeWithdrawContext *awc)
* @param connection The MHD connection to handle * @param connection The MHD connection to handle
* @param j_denoms_h Array of n hashes of the denominations for the withdrawal, in JSON format * @param j_denoms_h Array of n hashes of the denominations for the withdrawal, in JSON format
* @param j_blinded_coin_evs Array of n arrays of kappa blinded envelopes of in JSON format for the coins. * @param j_blinded_coin_evs Array of n arrays of kappa blinded envelopes of in JSON format for the coins.
* @param[out] aws The context of the operation, only partially built at call time * @param[out] awc The context of the operation, only partially built at call time
* @param[out] mhd_ret The result if a reply is queued for MHD * @param[out] mhd_ret The result if a reply is queued for MHD
* @return true on success, false on failure, with a reply already queued for MHD * @return true on success, false on failure, with a reply already queued for MHD
*/ */
@ -315,7 +315,7 @@ EXIT:
* @param connection HTTP-connection to the client * @param connection HTTP-connection to the client
* @param ksh The handle to the current state of (denomination) keys in the exchange * @param ksh The handle to the current state of (denomination) keys in the exchange
* @param denom_h Hash of the denomination key to check * @param denom_h Hash of the denomination key to check
* @param[out] dk On success, will contain the denomination key details * @param[out] pdk On success, will contain the denomination key details
* @param[out] result On failure, an MHD-response will be qeued and result will be set to accordingly * @param[out] result On failure, an MHD-response will be qeued and result will be set to accordingly
* @return true on success (denomination valid), false otherwise * @return true on success (denomination valid), false otherwise
*/ */
@ -402,10 +402,10 @@ denomination_is_valid (
* *
* @param connection The HTTP connection to the client * @param connection The HTTP connection to the client
* @param len The lengths of the array @a denoms_h * @param len The lengths of the array @a denoms_h
* @param denoms_h array of hashes of denomination public keys * @param denom_hs array of hashes of denomination public keys
* @param coin_evs array of blinded coin planchets * @param coin_evs array of blinded coin planchets
* @param[out] denom_serials On success, will be filled with the serial-id's of the denomination keys. Caller must deallocate. * @param[out] denom_serials On success, will be filled with the serial-id's of the denomination keys. Caller must deallocate.
* @param[out] amount_with_fee On succes, will contain the committed amount including fees * @param[out] amount_with_fee On success, will contain the committed amount including fees
* @param[out] result In the error cases, a response will be queued with MHD and this will be the result. * @param[out] result In the error cases, a response will be queued with MHD and this will be the result.
* @return GNUNET_OK if the denominations are valid and support age-restriction * @return GNUNET_OK if the denominations are valid and support age-restriction
* GNUNET_SYSERR otherwise * GNUNET_SYSERR otherwise
@ -511,8 +511,7 @@ static enum GNUNET_GenericReturnValue
verify_reserve_signature ( verify_reserve_signature (
struct MHD_Connection *connection, struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_AgeWithdraw *commitment, const struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
enum MHD_Result *mhd_ret enum MHD_Result *mhd_ret)
)
{ {
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
@ -824,10 +823,7 @@ age_withdraw_transaction (void *cls,
* 2.) age withdraw was successful. * 2.) age withdraw was successful.
* *
* @param connection HTTP-connection to the client * @param connection HTTP-connection to the client
* @param h_commitment Original commitment * @param awc The context for the current age withdraw request
* @param num_coins Number of coins
* @param coin_evs The Hashes of the undisclosed, blinded coins, @a num_coins many
* @param denom_keys The array of denomination keys, @a num_coins. Needed to detect Clause-Schnorr-based denominations
* @param[out] result On error, a HTTP-response will be queued and result set accordingly * @param[out] result On error, a HTTP-response will be queued and result set accordingly
* @return GNUNET_OK on success, GNUNET_SYSERR otherwise * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
*/ */

View File

@ -81,8 +81,6 @@ struct AgeRevealContext
* memory for those. * memory for those.
* *
* @param connection The MHD connection to handle * @param connection The MHD connection to handle
* @param j_denoms_h Array of hashes of the denominations for the withdrawal, in JSON format
* @param j_coin_evs The blinded envelopes in JSON format for the coins that are not revealed and will be signed on success
* @param j_disclosed_coin_secrets The n*(kappa-1) disclosed coins' private keys in JSON format, from which all other attributes (age restriction, blinding, nonce) will be derived from * @param j_disclosed_coin_secrets The n*(kappa-1) disclosed coins' private keys in JSON format, from which all other attributes (age restriction, blinding, nonce) will be derived from
* @param[out] actx The context of the operation, only partially built at call time * @param[out] actx The context of the operation, only partially built at call time
* @param[out] mhd_ret The result if a reply is queued for MHD * @param[out] mhd_ret The result if a reply is queued for MHD
@ -223,7 +221,7 @@ find_original_commitment (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} }
/* after unsuccessfull retries*/ /* after unsuccessful retries*/
*result = TALER_MHD_reply_with_ec (connection, *result = TALER_MHD_reply_with_ec (connection,
TALER_EC_GENERIC_DB_FETCH_FAILED, TALER_EC_GENERIC_DB_FETCH_FAILED,
"get_age_withdraw_info"); "get_age_withdraw_info");
@ -235,11 +233,11 @@ find_original_commitment (
* @brief Derives a age-restricted planchet from a given secret and calculates the hash * @brief Derives a age-restricted planchet from a given secret and calculates the hash
* *
* @param connection Connection to the client * @param connection Connection to the client
* @param ksh The denomination keys in memory * @param keys The denomination keys in memory
* @param secret The secret to a planchet * @param secret The secret to a planchet
* @param denom_pub_h The hash of the denomination for the planchet * @param denom_pub_h The hash of the denomination for the planchet
* @param max_age The maximum age allowed * @param max_age The maximum age allowed
* @param[out] hc Hashcode to write * @param[out] bch Hashcode to write
* @param[out] result On error, a HTTP-response will be queued and result set accordingly * @param[out] result On error, a HTTP-response will be queued and result set accordingly
* @return GNUNET_OK on success, GNUNET_SYSERR otherwise, with an error message * @return GNUNET_OK on success, GNUNET_SYSERR otherwise, with an error message
* written to the client and @e result set. * written to the client and @e result set.

View File

@ -182,8 +182,7 @@ kyc_aml_finished (void *cls,
kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; kat->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED, kat->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
"do_insert_kyc_attributes"); "do_insert_kyc_attributes");
/* Continued below to return the response */
/* FIXME-Christian: shouldn't we return in the error case? */
} }
/* Finally, return result to main handler */ /* Finally, return result to main handler */
kat->cb (kat->cb_cls, kat->cb (kat->cb_cls,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2020-2022 Taler Systems SA Copyright (C) 2020-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU Affero General Public License as published by the Free Software
@ -801,7 +801,7 @@ destroy_key_helpers (struct HelperState *hs)
* denomination. * denomination.
*/ */
static struct TALER_AgeMask static struct TALER_AgeMask
load_age_mask (const char*section_name) load_age_mask (const char *section_name)
{ {
static const struct TALER_AgeMask null_mask = {0}; static const struct TALER_AgeMask null_mask = {0};
enum GNUNET_GenericReturnValue ret; enum GNUNET_GenericReturnValue ret;
@ -1701,8 +1701,10 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
TALER_MHD_get_date_string (m.abs_time, TALER_MHD_get_date_string (m.abs_time,
dat); dat);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setting /keys 'Expires' header to '%s'\n", "Setting /keys 'Expires' header to '%s' (rekey frequency is %s)\n",
dat); dat,
GNUNET_TIME_relative2s (ksh->rekey_frequency,
false));
GNUNET_break (MHD_YES == GNUNET_break (MHD_YES ==
MHD_add_response_header (response, MHD_add_response_header (response,
MHD_HTTP_HEADER_EXPIRES, MHD_HTTP_HEADER_EXPIRES,
@ -1857,8 +1859,11 @@ create_krd (struct TEH_KeyStateHandle *ksh,
TEH_currency), TEH_currency),
GNUNET_JSON_pack_string ("asset_type", GNUNET_JSON_pack_string ("asset_type",
asset_type), asset_type),
// FIXME: legacy, remove soon!
GNUNET_JSON_pack_bool ("tipping_allowed", GNUNET_JSON_pack_bool ("tipping_allowed",
GNUNET_YES == TEH_enable_tipping), GNUNET_YES == TEH_enable_rewards),
GNUNET_JSON_pack_bool ("rewards_allowed",
GNUNET_YES == TEH_enable_rewards),
GNUNET_JSON_pack_data_auto ("master_public_key", GNUNET_JSON_pack_data_auto ("master_public_key",
&TEH_master_public_key), &TEH_master_public_key),
GNUNET_JSON_pack_time_rel ("reserve_closing_delay", GNUNET_JSON_pack_time_rel ("reserve_closing_delay",
@ -2105,8 +2110,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{ {
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group; struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
/* groupData is the value we store for each group meta-data */ /* GroupData is the value we store for each group meta-data */
struct groupData struct GroupData
{ {
/** /**
* The json blob with the group meta-data and list of denominations * The json blob with the group meta-data and list of denominations
@ -2210,7 +2215,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
*/ */
{ {
static const char *denoms_key = "denoms"; static const char *denoms_key = "denoms";
struct groupData *group; struct GroupData *group;
json_t *list; json_t *list;
json_t *entry; json_t *entry;
struct GNUNET_HashCode key; struct GNUNET_HashCode key;
@ -2221,25 +2226,19 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
.age_mask = dk->meta.age_mask, .age_mask = dk->meta.age_mask,
}; };
memset (&meta.hash, 0, sizeof(meta.hash));
/* Search the group/JSON-blob for the key */ /* Search the group/JSON-blob for the key */
GNUNET_CRYPTO_hash (&meta, sizeof(meta), &key); TALER_denomination_group_get_key (&meta,
&key);
group = group = GNUNET_CONTAINER_multihashmap_get (
(struct groupData *) GNUNET_CONTAINER_multihashmap_get ( denominations_by_group,
denominations_by_group, &key);
&key);
if (NULL == group) if (NULL == group)
{ {
/* There is no group for this meta-data yet, so we create a new group */ /* There is no group for this meta-data yet, so we create a new group */
bool age_restricted = meta.age_mask.bits != 0; bool age_restricted = meta.age_mask.bits != 0;
char *cipher; const char *cipher;
group = GNUNET_new (struct groupData);
memset (group, 0, sizeof(*group));
group = GNUNET_new (struct GroupData);
switch (meta.cipher) switch (meta.cipher)
{ {
case TALER_DENOMINATION_RSA: case TALER_DENOMINATION_RSA:
@ -2253,9 +2252,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
} }
group->json = GNUNET_JSON_PACK ( group->json = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("cipher", cipher), GNUNET_JSON_pack_string ("cipher",
TALER_JSON_PACK_DENOM_FEES ("fee", &meta.fees), cipher),
TALER_JSON_pack_amount ("value", &meta.value)); TALER_JSON_PACK_DENOM_FEES ("fee",
&meta.fees),
TALER_JSON_pack_amount ("value",
&meta.value));
GNUNET_assert (NULL != group->json); GNUNET_assert (NULL != group->json);
if (age_restricted) if (age_restricted)
@ -2294,17 +2296,16 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{ {
case TALER_DENOMINATION_RSA: case TALER_DENOMINATION_RSA:
key_spec = key_spec =
GNUNET_JSON_pack_rsa_public_key ("rsa_pub", GNUNET_JSON_pack_rsa_public_key (
dk->denom_pub.details. "rsa_pub",
rsa_public_key); dk->denom_pub.details.rsa_public_key);
break; break;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
key_spec = key_spec =
GNUNET_JSON_pack_data_varsize ("cs_pub", GNUNET_JSON_pack_data_varsize (
&dk->denom_pub.details. "cs_pub",
cs_public_key, &dk->denom_pub.details.cs_public_key,
sizeof (dk->denom_pub.details. sizeof (dk->denom_pub.details.cs_public_key));
cs_public_key));
break; break;
default: default:
GNUNET_assert (false); GNUNET_assert (false);
@ -2347,7 +2348,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
GNUNET_CONTAINER_multihashmap_size (denominations_by_group)) GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
{ {
struct GNUNET_CONTAINER_MultiHashMapIterator *iter; struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
struct groupData *group = NULL; struct GroupData *group = NULL;
iter = iter =
GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group); GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
@ -2372,15 +2373,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
json_array_append_new ( json_array_append_new (
grouped_denominations, grouped_denominations,
group->json)); group->json));
/* Build the running XOR over all hash(_xor) */ /* Build the running XOR over all hash(_xor) */
GNUNET_CRYPTO_hash_xor (&group->hash_xor, GNUNET_CRYPTO_hash_xor (&group->hash_xor,
&grouped_hash_xor, &grouped_hash_xor,
&grouped_hash_xor); &grouped_hash_xor);
GNUNET_free (group); GNUNET_free (group);
} }
GNUNET_CONTAINER_multihashmap_iterator_destroy (iter); GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
} }
@ -2544,9 +2542,9 @@ build_key_state (struct HelperState *hs,
ksh->helpers = hs; ksh->helpers = hs;
} }
ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024, ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
GNUNET_YES); true);
ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32, ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
GNUNET_NO /* MUST be NO! */); false /* MUST be false! */);
ksh->auditors = json_array (); ksh->auditors = json_array ();
GNUNET_assert (NULL != ksh->auditors); GNUNET_assert (NULL != ksh->auditors);
/* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */ /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */

View File

@ -94,7 +94,7 @@ age_restriction_load_config (
ext->config = &AR_config; ext->config = &AR_config;
ext->enabled = true; ext->enabled = true;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"loaded new age restriction config with age groups: %s\n", "loaded new age restriction config with age groups: %s\n",
TALER_age_mask_to_string (&mask)); TALER_age_mask_to_string (&mask));
@ -112,7 +112,6 @@ static json_t *
age_restriction_manifest ( age_restriction_manifest (
const struct TALER_Extension *ext) const struct TALER_Extension *ext)
{ {
char *mask_str;
json_t *conf; json_t *conf;
GNUNET_assert (NULL != ext); GNUNET_assert (NULL != ext);
@ -124,12 +123,11 @@ age_restriction_manifest (
return json_null (); return json_null ();
} }
mask_str = TALER_age_mask_to_string (&AR_config.mask);
conf = GNUNET_JSON_PACK ( conf = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("age_groups", mask_str) GNUNET_JSON_pack_string ("age_groups",
TALER_age_mask_to_string (&AR_config.mask))
); );
free (mask_str);
return GNUNET_JSON_PACK ( return GNUNET_JSON_PACK (
GNUNET_JSON_pack_bool ("critical", ext->critical), GNUNET_JSON_pack_bool ("critical", ext->critical),

View File

@ -184,7 +184,7 @@ configure_extension (
{ {
struct LoadConfClosure *col = cls; struct LoadConfClosure *col = cls;
const char *name; const char *name;
char *lib_name; char lib_name[1024] = {0};
struct TALER_Extension *extension; struct TALER_Extension *extension;
if (GNUNET_OK != col->error) if (GNUNET_OK != col->error)
@ -199,17 +199,16 @@ configure_extension (
/* Load the extension library */ /* Load the extension library */
GNUNET_asprintf (&lib_name, GNUNET_snprintf (lib_name,
sizeof(lib_name),
"libtaler_extension_%s", "libtaler_extension_%s",
name); name);
/* Lower-case extension name, config is case-insensitive */ /* Lower-case extension name, config is case-insensitive */
for (unsigned int i = 0; i < strlen (lib_name); i++) for (unsigned int i = 0; i < strlen (lib_name); i++)
{
lib_name[i] = tolower (lib_name[i]); lib_name[i] = tolower (lib_name[i]);
}
extension = GNUNET_PLUGIN_load ( extension = GNUNET_PLUGIN_load (lib_name,
lib_name, (void *) col->cfg);
(void *) col->cfg);
if (NULL == extension) if (NULL == extension)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,

View File

@ -829,9 +829,9 @@ struct TALER_CoinPubHashP
/** /**
* @brief Value that uniquely identifies a tip. * @brief Value that uniquely identifies a reward.
*/ */
struct TALER_TipIdentifierP struct TALER_RewardIdentifierP
{ {
/** /**
* The tip identifier is a SHA-512 hash code. * The tip identifier is a SHA-512 hash code.
@ -5947,33 +5947,54 @@ TALER_age_commitment_verify (
/** /**
* @brief helper function to free memory of a struct TALER_AgeCommitment * @brief helper function to free memory of a struct TALER_AgeCommitment
* *
* @param p the commitment from which all memory should be freed. * @param ac the commitment from which all memory should be freed.
*/ */
void void
TALER_age_commitment_free ( TALER_age_commitment_free (
struct TALER_AgeCommitment *p); struct TALER_AgeCommitment *ac);
/** /**
* @brief helper function to free memory of a struct TALER_AgeProof * @brief helper function to free memory of a struct TALER_AgeProof
* *
* @param p the proof of commitment from which all memory should be freed. * @param ap the proof of commitment from which all memory should be freed.
*/ */
void void
TALER_age_proof_free ( TALER_age_proof_free (
struct TALER_AgeProof *p); struct TALER_AgeProof *ap);
/** /**
* @brief helper function to free memory of a struct TALER_AgeCommitmentProof * @brief helper function to free memory of a struct TALER_AgeCommitmentProof
* *
* @param p the commitment and its proof from which all memory should be freed. * @param acp the commitment and its proof from which all memory should be freed.
*/ */
void void
TALER_age_commitment_proof_free ( TALER_age_commitment_proof_free (
struct TALER_AgeCommitmentProof *p); struct TALER_AgeCommitmentProof *acp);
/**
* @brief helper function to allocate and copy a struct TALER_AgeCommitmentProof
*
* @param[in] acp The original age commitment proof
* @return The deep copy of @e acp, allocated
*/
struct TALER_AgeCommitmentProof *
TALER_age_commitment_proof_duplicate (
const struct TALER_AgeCommitmentProof *acp);
/**
* @brief helper function to copy a struct TALER_AgeCommitmentProof
*
* @param[in] acp The original age commitment proof
* @param[out] nacp The struct to copy the data into, with freshly allocated and copied keys.
*/
void
TALER_age_commitment_proof_deep_copy (
const struct TALER_AgeCommitmentProof *acp,
struct TALER_AgeCommitmentProof *nacp);
/** /**
* @brief For age-withdraw, clients have to prove that the public keys for all * @brief For age-withdraw, clients have to prove that the public keys for all
* age groups larger than the allowed maximum age group are derived by scalar * age groups larger than the allowed maximum age group are derived by scalar
@ -6011,4 +6032,56 @@ TALER_age_restriction_from_secret (
struct TALER_AgeCommitmentProof *comm_proof); struct TALER_AgeCommitmentProof *comm_proof);
/**
* Group of Denominations. These are the common fields of an array of
* denominations.
*
* The corresponding JSON-blob will also contain an array of particular
* denominations with only the timestamps, cipher-specific public key and the
* master signature.
*/
struct TALER_DenominationGroup
{
/**
* XOR of all SHA-512 hashes of the public keys in this
* group.
*/
struct GNUNET_HashCode hash;
/**
* Value of coins in this denomination group.
*/
struct TALER_Amount value;
/**
* Fee structure for all coins in the group.
*/
struct TALER_DenomFeeSet fees;
/**
* Cipher used for the denomination.
*/
enum TALER_DenominationCipher cipher;
/**
* Age mask for the denomiation.
*/
struct TALER_AgeMask age_mask;
};
/**
* Compute a unique key for the meta data of a denomination group.
*
* @param dg denomination group to evaluate
* @param[out] key key to set
*/
void
TALER_denomination_group_get_key (
const struct TALER_DenominationGroup *dg,
struct GNUNET_HashCode *key);
#endif #endif

View File

@ -32,27 +32,6 @@
/* ********************* /keys *********************** */ /* ********************* /keys *********************** */
/**
* List of possible options to be passed to
* #TALER_EXCHANGE_connect().
*/
enum TALER_EXCHANGE_Option
{
/**
* Terminator (end of option list).
*/
TALER_EXCHANGE_OPTION_END = 0,
/**
* Followed by a "const json_t *" that was previously returned for
* this exchange URL by #TALER_EXCHANGE_serialize_data(). Used to
* resume a connection to an exchange without having to re-download
* /keys data (or at least only download the deltas).
*/
TALER_EXCHANGE_OPTION_DATA
};
/** /**
* @brief Exchange's signature key * @brief Exchange's signature key
@ -146,6 +125,7 @@ struct TALER_EXCHANGE_DenomPublicKey
* revoked by the exchange. * revoked by the exchange.
*/ */
bool revoked; bool revoked;
}; };
@ -260,6 +240,11 @@ struct TALER_EXCHANGE_Keys
*/ */
struct TALER_MasterPublicKeyP master_pub; struct TALER_MasterPublicKeyP master_pub;
/**
* Signature over extension configuration data, if any.
*/
struct TALER_MasterSignatureP extensions_sig;
/** /**
* Array of the exchange's online signing keys. * Array of the exchange's online signing keys.
*/ */
@ -280,6 +265,11 @@ struct TALER_EXCHANGE_Keys
*/ */
struct TALER_EXCHANGE_GlobalFee *global_fees; struct TALER_EXCHANGE_GlobalFee *global_fees;
/**
* Configuration data for extensions.
*/
json_t *extensions;
/** /**
* Supported Taler protocol version by the exchange. * Supported Taler protocol version by the exchange.
* String in the format current:revision:age using the * String in the format current:revision:age using the
@ -294,11 +284,18 @@ struct TALER_EXCHANGE_Keys
char *currency; char *currency;
/** /**
* How long after a reserve went idle will the exchange close it? * What is the base URL of the exchange that returned
* This is an approximate number, not cryptographically signed by * these keys?
* the exchange (advisory-only, may change anytime).
*/ */
struct GNUNET_TIME_Relative reserve_closing_delay; char *exchange_url;
/**
* Asset type used by the exchange. Typical values
* are "fiat" or "crypto" or "regional" or "stock".
* Wallets should adjust their UI/UX based on this
* value.
*/
char *asset_type;
/** /**
* Array of amounts a wallet is allowed to hold from * Array of amounts a wallet is allowed to hold from
@ -307,16 +304,22 @@ struct TALER_EXCHANGE_Keys
struct TALER_Amount *wallet_balance_limit_without_kyc; struct TALER_Amount *wallet_balance_limit_without_kyc;
/** /**
* Length of the @e wallet_balance_limit_without_kyc * How long after a reserve went idle will the exchange close it?
* array. * This is an approximate number, not cryptographically signed by
* the exchange (advisory-only, may change anytime).
*/ */
unsigned int wblwk_length; struct GNUNET_TIME_Relative reserve_closing_delay;
/** /**
* Timestamp indicating the /keys generation. * Timestamp indicating the /keys generation.
*/ */
struct GNUNET_TIME_Timestamp list_issue_date; struct GNUNET_TIME_Timestamp list_issue_date;
/**
* When does this keys data expire?
*/
struct GNUNET_TIME_Timestamp key_data_expiration;
/** /**
* Timestamp indicating the creation time of the last * Timestamp indicating the creation time of the last
* denomination key in /keys. * denomination key in /keys.
@ -329,6 +332,12 @@ struct TALER_EXCHANGE_Keys
*/ */
struct TALER_AgeMask age_mask; struct TALER_AgeMask age_mask;
/**
* Length of the @e wallet_balance_limit_without_kyc
* array.
*/
unsigned int wblwk_length;
/** /**
* Length of the @e global_fees array. * Length of the @e global_fees array.
*/ */
@ -360,17 +369,15 @@ struct TALER_EXCHANGE_Keys
unsigned int denom_keys_size; unsigned int denom_keys_size;
/** /**
* Asset type used by the exchange. Typical values * Reference counter for this structure.
* are "fiat" or "crypto" or "regional" or "stock". * Freed when it reaches 0.
* Wallets should adjust their UI/UX based on this
* value.
*/ */
char *asset_type; unsigned int rc;
/** /**
* Set to true if tipping is allowed at this exchange. * Set to true if rewards are allowed at this exchange.
*/ */
bool tipping_allowed; bool rewards_allowed;
}; };
@ -505,77 +512,82 @@ struct TALER_EXCHANGE_KeysResponse
/** /**
* Function called with information about who is auditing * Function called with information about who is auditing
* a particular exchange and what keys the exchange is using. * a particular exchange and what keys the exchange is using.
* The ownership over the @a keys object is passed to
* the callee, thus it is given explicitly and not
* (only) via @a kr.
* *
* @param cls closure * @param cls closure
* @param kr response from /keys * @param kr response from /keys
* @param[in] keys keys object passed to callback with
* reference counter of 1. Must be freed by callee
* using #TALER_EXCHANGE_keys_decref(). NULL on failure.
*/ */
typedef void typedef void
(*TALER_EXCHANGE_CertificationCallback) ( (*TALER_EXCHANGE_GetKeysCallback) (
void *cls, void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr); const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys);
/** /**
* @brief Handle to the exchange. This is where we interact with * @brief Handle for a GET /keys request.
* a particular exchange and keep the per-exchange information.
*/ */
struct TALER_EXCHANGE_Handle; struct TALER_EXCHANGE_GetKeysHandle;
/** /**
* Initialise a connection to the exchange. Will connect to the * Fetch the main /keys resources from an exchange. Does an incremental
* exchange and obtain information about the exchange's master public * fetch if @a last_keys is given. The obtained information will be passed to
* key and the exchange's auditor. The respective information will * the @a cert_cb (possibly after first merging it with @a last_keys to
* be passed to the @a cert_cb once available, and all future * produce a full picture; expired keys (for deposit) will be removed from @a
* interactions with the exchange will be checked to be signed * last_keys if there are any).
* (where appropriate) by the respective master key.
* *
* @param ctx the context * @param ctx the context
* @param url HTTP base URL for the exchange * @param url HTTP base URL for the exchange
* @param[in,out] last_keys previous keys object, NULL for none
* @param cert_cb function to call with the exchange's certification information, * @param cert_cb function to call with the exchange's certification information,
* possibly called repeatedly if the information changes * possibly called repeatedly if the information changes
* @param cert_cb_cls closure for @a cert_cb * @param cert_cb_cls closure for @a cert_cb
* @param ... list of additional arguments, terminated by #TALER_EXCHANGE_OPTION_END.
* @return the exchange handle; NULL upon error * @return the exchange handle; NULL upon error
*/ */
struct TALER_EXCHANGE_Handle * struct TALER_EXCHANGE_GetKeysHandle *
TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, TALER_EXCHANGE_get_keys (
const char *url, struct GNUNET_CURL_Context *ctx,
TALER_EXCHANGE_CertificationCallback cert_cb, const char *url,
void *cert_cb_cls, struct TALER_EXCHANGE_Keys *last_keys,
...); TALER_EXCHANGE_GetKeysCallback cert_cb,
void *cert_cb_cls);
/** /**
* Serialize the latest key data from @a exchange to be persisted * Serialize the latest data from @a keys to be persisted
* on disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more * (for example, to be used as @a last_keys later).
* efficiently recover the state).
* *
* @param exchange which exchange's key and wire data should be serialized * @param kd the key data to serialize
* @return NULL on error (i.e. no current data available); otherwise * @return NULL on error; otherwise JSON object owned by the caller
* json object owned by the caller
*/ */
json_t * json_t *
TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange); TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd);
/** /**
* Disconnect from the exchange. * Deserialize keys data stored in @a j.
* *
* @param exchange the exchange handle * @param j JSON keys data previously returned from #TALER_EXCHANGE_keys_to_json()
*/ * @return NULL on error (i.e. invalid JSON); otherwise
void * keys object with reference counter 1 owned by the caller
TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange);
/**
* Obtain the keys from the exchange.
*
* @param exchange the exchange handle
* @return the exchange's key set
*/ */
struct TALER_EXCHANGE_Keys * struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange); TALER_EXCHANGE_keys_from_json (const json_t *j);
/**
* Cancel GET /keys operation.
*
* @param[in] gkh the GET /keys handle
*/
void
TALER_EXCHANGE_get_keys_cancel (struct TALER_EXCHANGE_GetKeysHandle *gkh);
/** /**
@ -598,90 +610,6 @@ void
TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys); TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys);
/**
* Let the user set the last valid denomination time manually.
*
* @param exchange the exchange handle.
* @param last_denom_new new last denomination time.
*/
void
TALER_EXCHANGE_set_last_denom (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_TIME_Timestamp last_denom_new);
/**
* Flags for #TALER_EXCHANGE_check_keys_current().
*/
enum TALER_EXCHANGE_CheckKeysFlags
{
/**
* No special options.
*/
TALER_EXCHANGE_CKF_NONE,
/**
* Force downloading /keys now, even if /keys is still valid
* (that is, the period advertised by the exchange for re-downloads
* has not yet expired).
*/
TALER_EXCHANGE_CKF_FORCE_DOWNLOAD = 1,
/**
* Pull all keys again, resetting the client state to the original state.
* Using this flag disables the incremental download, and also prevents using
* the context until the re-download has completed.
*/
TALER_EXCHANGE_CKF_PULL_ALL_KEYS = 2,
/**
* Force downloading all keys now.
*/
TALER_EXCHANGE_CKF_FORCE_ALL_NOW = TALER_EXCHANGE_CKF_FORCE_DOWNLOAD
| TALER_EXCHANGE_CKF_PULL_ALL_KEYS
};
/**
* Check if our current response for /keys is valid, and if
* not, trigger /keys download. If @a cb is given, changes
* the @a exchange callback for the /keys response.
*
* @param exchange exchange to check keys for
* @param flags options controlling when to download what
* @param cb function to call with the /keys response, can be NULL
* @param cb_cls closure for @a cb
* @return until when the existing response is current, 0 if we are re-downloading now
*/
struct GNUNET_TIME_Timestamp
TALER_EXCHANGE_check_keys_current (
struct TALER_EXCHANGE_Handle *exchange,
enum TALER_EXCHANGE_CheckKeysFlags flags,
TALER_EXCHANGE_CertificationCallback cb,
void *cb_cls);
/**
* Obtain the keys from the exchange in the raw JSON format.
*
* @param exchange the exchange handle
* @return the exchange's keys in raw JSON
*/
json_t *
TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange);
/**
* Obtain the keys from the exchange in the raw JSON format.
*
* @param keys the keys structure
* @return the keys in raw JSON
*/
json_t *
TALER_EXCHANGE_keys_to_json (struct TALER_EXCHANGE_Keys *keys);
/** /**
* Test if the given @a pub is a the current signing key from the exchange * Test if the given @a pub is a the current signing key from the exchange
* according to @a keys. * according to @a keys.
@ -691,18 +619,9 @@ TALER_EXCHANGE_keys_to_json (struct TALER_EXCHANGE_Keys *keys);
* @return #GNUNET_OK if @a pub is (according to /keys) a current signing key * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys, TALER_EXCHANGE_test_signing_key (
const struct TALER_ExchangePublicKeyP *pub); const struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ExchangePublicKeyP *pub);
/**
* Get exchange's base URL.
*
* @param exchange exchange handle.
* @return the base URL from the handle.
*/
const char *
TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange);
/** /**
@ -736,7 +655,8 @@ TALER_EXCHANGE_get_global_fee (
* Create a copy of a denomination public key. * Create a copy of a denomination public key.
* *
* @param key key to copy * @param key key to copy
* @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key * @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key()
* @deprecated
*/ */
struct TALER_EXCHANGE_DenomPublicKey * struct TALER_EXCHANGE_DenomPublicKey *
TALER_EXCHANGE_copy_denomination_key ( TALER_EXCHANGE_copy_denomination_key (
@ -745,9 +665,10 @@ TALER_EXCHANGE_copy_denomination_key (
/** /**
* Destroy a denomination public key. * Destroy a denomination public key.
* Should only be called with keys created by #TALER_EXCHANGE_copy_denomination_key. * Should only be called with keys created by #TALER_EXCHANGE_copy_denomination_key().
* *
* @param key key to destroy. * @param key key to destroy.
* @deprecated
*/ */
void void
TALER_EXCHANGE_destroy_denomination_key ( TALER_EXCHANGE_destroy_denomination_key (
@ -2828,13 +2749,16 @@ TALER_EXCHANGE_batch_withdraw2_cancel (
*/ */
struct TALER_EXCHANGE_AgeWithdrawCoinInput struct TALER_EXCHANGE_AgeWithdrawCoinInput
{ {
/* The master secret from which we derive all other relevant values for /**
* The master secret from which we derive all other relevant values for
* the coin: private key, nonces (if applicable) and age restriction * the coin: private key, nonces (if applicable) and age restriction
*/ */
const struct TALER_PlanchetMasterSecretP secret[TALER_CNC_KAPPA]; const struct TALER_PlanchetMasterSecretP secret[TALER_CNC_KAPPA];
/* The denomination of the coin. Must support age restriction, i.e /**
* its .keys.age_mask MUST not be 0 */ * The denomination of the coin. Must support age restriction, i.e
* its .keys.age_mask MUST not be 0
*/
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
}; };
@ -2901,7 +2825,7 @@ typedef void
* *
* @param curl_ctx The curl context * @param curl_ctx The curl context
* @param exchange_url The base url of the exchange * @param exchange_url The base url of the exchange
* @parm keys The denomination keys from the exchange * @param keys The denomination keys from the exchange
* @param reserve_priv The pivate key to the reserve * @param reserve_priv The pivate key to the reserve
* @param num_coins The number of elements in @e coin_inputs * @param num_coins The number of elements in @e coin_inputs
* @param coin_inputs The input for the coins to withdraw * @param coin_inputs The input for the coins to withdraw
@ -2918,8 +2842,8 @@ TALER_EXCHANGE_age_withdraw (
struct TALER_EXCHANGE_Keys *keys, struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_ReservePrivateKeyP *reserve_priv,
size_t num_coins, size_t num_coins,
const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[ const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[const static
const static num_coins], num_coins],
uint8_t max_age, uint8_t max_age,
TALER_EXCHANGE_AgeWithdrawCallback res_cb, TALER_EXCHANGE_AgeWithdrawCallback res_cb,
void *res_cb_cls); void *res_cb_cls);
@ -3133,7 +3057,7 @@ struct TALER_EXCHANGE_RevealedCoinInfo
* Age commitment and its hash of the coin, might be NULL. * Age commitment and its hash of the coin, might be NULL.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof; struct TALER_AgeCommitmentProof *age_commitment_proof;
struct TALER_AgeCommitmentHash *h_age_commitment; struct TALER_AgeCommitmentHash h_age_commitment;
/** /**
* Blinding keys used to blind the fresh coin. * Blinding keys used to blind the fresh coin.
@ -3220,7 +3144,6 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
* *
* @param ctx curl context * @param ctx curl context
* @param url exchange base URL * @param url exchange base URL
* @param keys exchange keys
* @param rms the fresh secret that defines the refresh operation * @param rms the fresh secret that defines the refresh operation
* @param rd the refresh data that characterizes the refresh operation * @param rd the refresh data that characterizes the refresh operation
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd * @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd
@ -3277,10 +3200,11 @@ struct TALER_EXCHANGE_LinkedCoinInfo
struct TALER_CoinSpendPrivateKeyP coin_priv; struct TALER_CoinSpendPrivateKeyP coin_priv;
/** /**
* Age commitment and its hash, if applicable. Might be NULL. * Age commitment and its hash, if applicable.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof; bool has_age_commitment;
struct TALER_AgeCommitmentHash *h_age_commitment; struct TALER_AgeCommitmentProof age_commitment_proof;
struct TALER_AgeCommitmentHash h_age_commitment;
/** /**
* Master secret of this coin. * Master secret of this coin.

View File

@ -380,26 +380,6 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \ TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \
TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse) TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse)
/**
* Group of Denominations. These are the common fields of an array of
* denominations.
*
* The corresponding JSON-blob will also contain an array of particular
* denominations with only the timestamps, cipher-specific public key and the
* master signature.
*
**/
struct TALER_DenominationGroup
{
enum TALER_DenominationCipher cipher;
struct TALER_Amount value;
struct TALER_DenomFeeSet fees;
struct TALER_AgeMask age_mask;
// hash is/should be the XOR of all SHA-512 hashes of the public keys in this
// group
struct GNUNET_HashCode hash;
};
/** /**
* Generate a parser for a group of denominations. * Generate a parser for a group of denominations.

View File

@ -57,18 +57,44 @@
* *
* @param is interpreter to fail * @param is interpreter to fail
* @param status unexpected HTTP status code received * @param status unexpected HTTP status code received
* @param expected expected HTTP status code
*/ */
#define TALER_TESTING_unexpected_status(is,status) \ #define TALER_TESTING_unexpected_status(is,status,expected) \
do { \ do { \
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \
"Unexpected response code %u to command %s in %s:%u\n", \ "Unexpected response code %u (expected: %u) to command %s in %s:%u\n", \
status, \ status, \
expected, \
TALER_TESTING_interpreter_get_current_label (is), \ TALER_TESTING_interpreter_get_current_label (is), \
__FILE__, \ __FILE__, \
__LINE__); \ __LINE__); \
TALER_TESTING_interpreter_fail (is); \ TALER_TESTING_interpreter_fail (is); \
} while (0) } while (0)
/**
* Log an error message about us receiving an unexpected HTTP
* status code at the current command and fail the test and print the response
* body (expected as json).
*
* @param is interpreter to fail
* @param status unexpected HTTP status code received
* @param expected expected HTTP status code
* @param body received JSON-reply
*/
#define TALER_TESTING_unexpected_status_with_body(is,status,expected,body) \
do { \
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \
"Unexpected response code %u (expected: %u) to " \
"command %s in %s:%u\nwith body:\n>>%s<<\n", \
status, \
expected, \
TALER_TESTING_interpreter_get_current_label (is), \
__FILE__, \
__LINE__, \
json_dumps (body, JSON_INDENT (2))); \
TALER_TESTING_interpreter_fail (is); \
} while (0)
/** /**
* Log an error message about a command not having * Log an error message about a command not having
@ -85,7 +111,7 @@
__FILE__, \ __FILE__, \
__LINE__, \ __LINE__, \
TALER_TESTING_interpreter_get_current_label (is)); \ TALER_TESTING_interpreter_get_current_label (is)); \
}while (0) } while (0)
/** /**
@ -623,6 +649,7 @@ TALER_TESTING_cmd_system_start (
* *
* @param label command label * @param label command label
* @param cfg configuration to use * @param cfg configuration to use
* @param last_keys_ref reference to command with prior /keys response, NULL for none
* @param wait_for_keys block until we got /keys * @param wait_for_keys block until we got /keys
* @param load_private_key obtain private key from file indicated in @a cfg * @param load_private_key obtain private key from file indicated in @a cfg
* @return the command. * @return the command.
@ -631,6 +658,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange ( TALER_TESTING_cmd_get_exchange (
const char *label, const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys, bool wait_for_keys,
bool load_private_key); bool load_private_key);
@ -1786,45 +1814,6 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_wait_service (const char *label, TALER_TESTING_cmd_wait_service (const char *label,
const char *url); const char *url);
/**
* Make a "check keys" command.
*
* @param label command label
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys (const char *label);
/**
* Make a "check keys" command that forcedly does NOT cherry pick;
* just redownload the whole /keys.
*
* @param label command label
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_pull_all_keys (const char *label);
/**
* Make a "check keys" command. It lets the user set a last denom issue date to be
* used in the request for /keys.
*
* @param label command label
* @param last_denom_date_ref previous /keys command to use to
* obtain the "last_denom_date" value from; "zero" can be used
* as a special value to force an absolute time of zero to be
* given to as an argument
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_with_last_denom (
const char *label,
const char *last_denom_date_ref);
/** /**
* Create a "batch" command. Such command takes a * Create a "batch" command. Such command takes a
* end_CMD-terminated array of CMDs and executed them. * end_CMD-terminated array of CMDs and executed them.
@ -1883,31 +1872,6 @@ TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
unsigned int new_ip); unsigned int new_ip);
/**
* Make a serialize-keys CMD.
*
* @param label CMD label
* @return the CMD.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_serialize_keys (const char *label);
/**
* Make a connect-with-state CMD. This command
* will use a serialized key state to reconnect
* to the exchange.
*
* @param label command label
* @param state_reference label of a CMD offering
* a serialized key state.
* @return the CMD.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_connect_with_state (const char *label,
const char *state_reference);
/** /**
* Make the "insert-deposit" CMD. * Make the "insert-deposit" CMD.
* *
@ -2246,6 +2210,7 @@ TALER_TESTING_cmd_proof_kyc_oauth2 (
* KYC processes which also provides a @a birthdate in a response * KYC processes which also provides a @a birthdate in a response
* *
* @param label command label * @param label command label
* @param birthdate fixed birthdate, such as "2022-03-04", "2022-03-00", "2022-00-00"
* @param port the TCP port to listen on * @param port the TCP port to listen on
*/ */
struct TALER_TESTING_Command struct TALER_TESTING_Command
@ -2499,6 +2464,30 @@ TALER_TESTING_cmd_check_aml_decisions (
unsigned int expected_http_status); unsigned int expected_http_status);
/* ****************** convenience functions ************** */
/**
* Get exchange URL from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange URL, or NULL on error
*/
const char *
TALER_TESTING_get_exchange_url (
struct TALER_TESTING_Interpreter *is);
/**
* Get exchange keys from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange keys, or NULL on error
*/
struct TALER_EXCHANGE_Keys *
TALER_TESTING_get_keys (
struct TALER_TESTING_Interpreter *is);
/* *** Generic trait logic for implementing traits ********* */ /* *** Generic trait logic for implementing traits ********* */
@ -2657,13 +2646,13 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_row, const uint64_t) \ op (bank_row, const uint64_t) \
op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \ op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \
op (officer_priv, const struct TALER_AmlOfficerPrivateKeyP) \ op (officer_priv, const struct TALER_AmlOfficerPrivateKeyP) \
op (officer_name, const char) \ op (officer_name, const char) \
op (aml_decision, enum TALER_AmlDecisionState) \ op (aml_decision, enum TALER_AmlDecisionState) \
op (aml_justification, const char) \ op (aml_justification, const char) \
op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \ op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \
op (auditor_pub, const struct TALER_AuditorPublicKeyP) \ op (auditor_pub, const struct TALER_AuditorPublicKeyP) \
op (master_priv, const struct TALER_MasterPrivateKeyP) \ op (master_priv, const struct TALER_MasterPrivateKeyP) \
op (master_pub, const struct TALER_MasterPublicKeyP) \ op (master_pub, const struct TALER_MasterPublicKeyP) \
op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \ op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \
op (purse_pub, const struct TALER_PurseContractPublicKeyP) \ op (purse_pub, const struct TALER_PurseContractPublicKeyP) \
op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \ op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \
@ -2682,7 +2671,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \
op (contract_terms, const json_t) \ op (contract_terms, const json_t) \
op (wire_details, const json_t) \ op (wire_details, const json_t) \
op (exchange_keys, const json_t) \
op (exchange_url, const char) \ op (exchange_url, const char) \
op (auditor_url, const char) \ op (auditor_url, const char) \
op (exchange_bank_account_url, const char) \ op (exchange_bank_account_url, const char) \
@ -2703,7 +2691,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \ op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \
op (claim_token, const struct TALER_ClaimTokenP) \ op (claim_token, const struct TALER_ClaimTokenP) \
op (relative_time, const struct GNUNET_TIME_Relative) \ op (relative_time, const struct GNUNET_TIME_Relative) \
op (exchange, struct TALER_EXCHANGE_Handle) \
op (fakebank, struct TALER_FAKEBANK_Handle) \ op (fakebank, struct TALER_FAKEBANK_Handle) \
op (keys, struct TALER_EXCHANGE_Keys) \ op (keys, struct TALER_EXCHANGE_Keys) \
op (process, struct GNUNET_OS_Process *) op (process, struct GNUNET_OS_Process *)
@ -2740,38 +2727,4 @@ TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT)
TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT) TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT)
/* ****************** convenience functions ************** */
/**
* Get exchange handle from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange handle, or NULL on error
*/
struct TALER_EXCHANGE_Handle *
TALER_TESTING_get_exchange (struct TALER_TESTING_Interpreter *is);
/**
* Get exchange URL from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange URL, or NULL on error
*/
const char *
TALER_TESTING_get_exchange_url (
struct TALER_TESTING_Interpreter *is);
/**
* Get exchange keys from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange keys, or NULL on error
*/
struct TALER_EXCHANGE_Keys *
TALER_TESTING_get_keys (
struct TALER_TESTING_Interpreter *is);
#endif #endif

View File

@ -578,11 +578,14 @@ TALER_parse_age_group_string (
/** /**
* @brief Encodes the age mask into a string, like "8:10:12:14:16:18:21" * @brief Encodes the age mask into a string, like "8:10:12:14:16:18:21"
* *
* NOTE: This function uses a static buffer. It is not safe to call this
* function concurrently.
*
* @param mask Age mask * @param mask Age mask
* @return String representation of the age mask, allocated by GNUNET_malloc. * @return String representation of the age mask.
* Can be used as value in the TALER config. * Can be used as value in the TALER config.
*/ */
char * const char *
TALER_age_mask_to_string ( TALER_age_mask_to_string (
const struct TALER_AgeMask *mask); const struct TALER_AgeMask *mask);

View File

@ -279,6 +279,11 @@ parse_denomination_group (void *cls,
&emsg, &emsg,
&eline)) &eline))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to parse %s at %u: %s\n",
spec[eline].field,
eline,
emsg);
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }

View File

@ -95,7 +95,7 @@ struct TALER_AUDITOR_GetConfigHandle
* in the @a key_data. * in the @a key_data.
* *
* @param[in] resp_obj JSON object to parse * @param[in] resp_obj JSON object to parse
* @param[in,out] auditor where to store the results we decoded * @param[in,out] vi where to store the results we decoded
* @param[out] vc where to store config compatibility data * @param[out] vc where to store config compatibility data
* @return #TALER_EC_NONE on success * @return #TALER_EC_NONE on success
*/ */

View File

@ -382,7 +382,8 @@ reserve_age_withdraw_payment_required (
* HTTP /reserves/$RESERVE_PUB/age-withdraw request. * HTTP /reserves/$RESERVE_PUB/age-withdraw request.
* *
* @param cls the `struct TALER_EXCHANGE_AgeWithdrawHandle` * @param cls the `struct TALER_EXCHANGE_AgeWithdrawHandle`
* @param aw2r response data * @param response_code The HTTP response code
* @param response response data
*/ */
static void static void
handle_reserve_age_withdraw_finished ( handle_reserve_age_withdraw_finished (
@ -651,6 +652,7 @@ ERROR:
* Prepares the request URL for the age-withdraw request * Prepares the request URL for the age-withdraw request
* *
* @param awh The handler * @param awh The handler
* @param exchange_url The base-URL to the exchange
*/ */
static static
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
@ -770,7 +772,7 @@ csr_withdraw_done (
* *
* @param awh The handler to the age-withdraw * @param awh The handler to the age-withdraw
* @param num_coins The number of coins in @e coin_inputs * @param num_coins The number of coins in @e coin_inputs
* @param coin_inputs The input for the individial coin(-candidates) * @param coin_inputs The input for the individual coin(-candidates)
* @return GNUNET_OK on success, GNUNET_SYSERR on failure * @return GNUNET_OK on success, GNUNET_SYSERR on failure
*/ */
static static

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015 Taler Systems SA Copyright (C) 2014, 2015, 2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU General Public License as published by the Free Software
@ -28,124 +28,6 @@
#include "taler_util.h" #include "taler_util.h"
#include "taler_curl_lib.h" #include "taler_curl_lib.h"
/**
* Entry in DLL of auditors used by an exchange.
*/
struct TEAH_AuditorListEntry;
/**
* Stages of initialization for the `struct TALER_EXCHANGE_Handle`
*/
enum ExchangeHandleState
{
/**
* Just allocated.
*/
MHS_INIT = 0,
/**
* Obtained the exchange's certification data and keys.
*/
MHS_CERT = 1,
/**
* Failed to initialize (fatal).
*/
MHS_FAILED = 2
};
/**
* Handle to the exchange
*/
struct TALER_EXCHANGE_Handle
{
/**
* The context of this handle
*/
struct GNUNET_CURL_Context *ctx;
/**
* The URL of the exchange (i.e. "http://exchange.taler.net/")
*/
char *url;
/**
* Function to call with the exchange's certification data,
* NULL if this has already been done.
*/
TALER_EXCHANGE_CertificationCallback cert_cb;
/**
* Closure to pass to @e cert_cb.
*/
void *cert_cb_cls;
/**
* Data for the request to get the /keys of a exchange,
* NULL once we are past stage #MHS_INIT.
*/
struct KeysRequest *kr;
/**
* Task for retrying /keys request.
*/
struct GNUNET_SCHEDULER_Task *retry_task;
/**
* Raw key data of the exchange, only valid if
* @e handshake_complete is past stage #MHS_CERT.
*/
json_t *key_data_raw;
/**
* Head of DLL of auditors of this exchange.
*/
struct TEAH_AuditorListEntry *auditors_head;
/**
* Tail of DLL of auditors of this exchange.
*/
struct TEAH_AuditorListEntry *auditors_tail;
/**
* Key data of the exchange, only valid if
* @e handshake_complete is past stage #MHS_CERT.
*/
struct TALER_EXCHANGE_Keys key_data;
/**
* Retry /keys frequency.
*/
struct GNUNET_TIME_Relative retry_delay;
/**
* When does @e key_data expire?
*/
struct GNUNET_TIME_Timestamp key_data_expiration;
/**
* Number of subsequent failed requests to /keys.
*
* Used to compute the CURL timeout for the request.
*/
unsigned int keys_error_count;
/**
* Number of subsequent failed requests to /wire.
*
* Used to compute the CURL timeout for the request.
*/
unsigned int wire_error_count;
/**
* Stage of the exchange's initialization routines.
*/
enum ExchangeHandleState state;
};
/** /**
* Function called for each auditor to give us a chance to possibly * Function called for each auditor to give us a chance to possibly
@ -156,9 +38,10 @@ struct TALER_EXCHANGE_Handle
* @param auditor_pub public key of the auditor * @param auditor_pub public key of the auditor
*/ */
typedef void typedef void
(*TEAH_AuditorCallback)(void *cls, (*TEAH_AuditorCallback)(
const char *auditor_url, void *cls,
const struct TALER_AuditorPublicKeyP *auditor_pub); const char *auditor_url,
const struct TALER_AuditorPublicKeyP *auditor_pub);
/** /**
@ -171,50 +54,11 @@ typedef void
* @param ac_cls closure for @a ac * @param ac_cls closure for @a ac
*/ */
void void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys, TEAH_get_auditors_for_dc (
TEAH_AuditorCallback ac, struct TALER_EXCHANGE_Keys *keys,
void *ac_cls); TEAH_AuditorCallback ac,
void *ac_cls);
/**
* Get the context of a exchange.
*
* @param h the exchange handle to query
* @return ctx context to execute jobs in
*/
struct GNUNET_CURL_Context *
TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h);
/**
* Check if the handle is ready to process requests.
*
* @param h the exchange handle to query
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
*/
enum GNUNET_GenericReturnValue
TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h);
/**
* Check if the handle is ready to process requests.
*
* @param h the exchange handle to query
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
*/
enum GNUNET_GenericReturnValue
TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h);
/**
* Obtain the URL to use for an API request.
*
* @param h the exchange handle to query
* @param path Taler API path (i.e. "/reserve/withdraw")
* @return the full URL to use with cURL
*/
char *
TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
const char *path);
/* end of exchange_api_handle.h */ /* end of exchange_api_handle.h */
#endif #endif

View File

@ -114,6 +114,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_TransferSecretP secret; struct TALER_TransferSecretP secret;
struct TALER_PlanchetDetail pd; struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHashP c_hash; struct TALER_CoinPubHashP c_hash;
struct TALER_AgeCommitmentHash *pah = NULL;
/* parse reply */ /* parse reply */
if (GNUNET_OK != if (GNUNET_OK !=
@ -137,34 +138,35 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
&alg_values, &alg_values,
&bks); &bks);
lci->age_commitment_proof = NULL; lci->has_age_commitment = false;
lci->h_age_commitment = NULL;
/* Derive the age commitment and calculate the hash */ /* Derive the age commitment and calculate the hash */
if (NULL != lh->age_commitment_proof) if (NULL != lh->age_commitment_proof)
{ {
lci->age_commitment_proof = GNUNET_new (struct TALER_AgeCommitmentProof);
lci->h_age_commitment = GNUNET_new (struct TALER_AgeCommitmentHash);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_age_commitment_derive ( TALER_age_commitment_derive (
lh->age_commitment_proof, lh->age_commitment_proof,
&secret.key, &secret.key,
lci->age_commitment_proof)); &lci->age_commitment_proof));
TALER_age_commitment_hash ( TALER_age_commitment_hash (
&(lci->age_commitment_proof->commitment), &lci->age_commitment_proof.commitment,
lci->h_age_commitment); &lci->h_age_commitment);
lci->has_age_commitment = true;
pah = &lci->h_age_commitment;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_planchet_prepare (&rpub, TALER_planchet_prepare (
&alg_values, &rpub,
&bks, &alg_values,
&lci->coin_priv, &bks,
lci->h_age_commitment, &lci->coin_priv,
&c_hash, pah,
&pd)) &c_hash,
&pd))
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -364,6 +366,8 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
{ {
TALER_denom_sig_free (&lcis[i].sig); TALER_denom_sig_free (&lcis[i].sig);
TALER_denom_pub_free (&lcis[i].pub); TALER_denom_pub_free (&lcis[i].pub);
if (lcis[i].has_age_commitment)
TALER_age_commitment_proof_free (&lcis[i].age_commitment_proof);
} }
} }
return ret; return ret;
@ -513,6 +517,7 @@ TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh)
GNUNET_CURL_job_cancel (lh->job); GNUNET_CURL_job_cancel (lh->job);
lh->job = NULL; lh->job = NULL;
} }
GNUNET_free (lh->url); GNUNET_free (lh->url);
GNUNET_free (lh); GNUNET_free (lh);
} }

View File

@ -336,13 +336,14 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
} }
TALER_denom_pub_hash (&mh->md.melted_coin.pub_key, TALER_denom_pub_hash (&mh->md.melted_coin.pub_key,
&h_denom_pub); &h_denom_pub);
TALER_wallet_melt_sign (&mh->md.melted_coin.melt_amount_with_fee, TALER_wallet_melt_sign (
&mh->md.melted_coin.fee_melt, &mh->md.melted_coin.melt_amount_with_fee,
&mh->md.rc, &mh->md.melted_coin.fee_melt,
&h_denom_pub, &mh->md.rc,
mh->md.melted_coin.h_age_commitment, &h_denom_pub,
&mh->md.melted_coin.coin_priv, mh->md.melted_coin.h_age_commitment,
&mh->coin_sig); &mh->md.melted_coin.coin_priv,
&mh->coin_sig);
GNUNET_CRYPTO_eddsa_key_get_public (&mh->md.melted_coin.coin_priv.eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&mh->md.melted_coin.coin_priv.eddsa_priv,
&mh->coin_pub.eddsa_pub); &mh->coin_pub.eddsa_pub);
melt_obj = GNUNET_JSON_PACK ( melt_obj = GNUNET_JSON_PACK (
@ -357,7 +358,7 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
GNUNET_JSON_pack_data_auto ("rc", GNUNET_JSON_pack_data_auto ("rc",
&mh->md.rc), &mh->md.rc),
GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_allow_null (
mh->md.melted_coin.h_age_commitment (NULL != mh->md.melted_coin.h_age_commitment)
? GNUNET_JSON_pack_data_auto ("age_commitment_hash", ? GNUNET_JSON_pack_data_auto ("age_commitment_hash",
mh->md.melted_coin.h_age_commitment) mh->md.melted_coin.h_age_commitment)
: GNUNET_JSON_pack_string ("age_commitment_hash", : GNUNET_JSON_pack_string ("age_commitment_hash",
@ -504,7 +505,6 @@ csr_cb (void *cls,
} }
/* FIXME: refactor this to use struct TALER_EXCHANGE_Handle */
struct TALER_EXCHANGE_MeltHandle * struct TALER_EXCHANGE_MeltHandle *
TALER_EXCHANGE_melt ( TALER_EXCHANGE_melt (
struct GNUNET_CURL_Context *ctx, struct GNUNET_CURL_Context *ctx,

View File

@ -45,6 +45,11 @@ TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
struct FreshCoinData *fcd = &md->fcds[j]; struct FreshCoinData *fcd = &md->fcds[j];
TALER_denom_pub_free (&fcd->fresh_pk); TALER_denom_pub_free (&fcd->fresh_pk);
for (size_t i = 0; i < TALER_CNC_KAPPA; i++)
{
TALER_age_commitment_proof_free (fcd->age_commitment_proofs[i]);
GNUNET_free (fcd->age_commitment_proofs[i]);
}
} }
GNUNET_free (md->fcds); GNUNET_free (md->fcds);
} }
@ -168,7 +173,8 @@ TALER_EXCHANGE_get_melt_data_ (
union TALER_DenominationBlindingKeyP *bks = &fcd->bks[i]; union TALER_DenominationBlindingKeyP *bks = &fcd->bks[i];
struct TALER_PlanchetDetail pd; struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHashP c_hash; struct TALER_CoinPubHashP c_hash;
struct TALER_AgeCommitmentHash *ach = NULL; struct TALER_AgeCommitmentHash ach;
struct TALER_AgeCommitmentHash *pah = NULL;
TALER_transfer_secret_to_planchet_secret (&trans_sec, TALER_transfer_secret_to_planchet_secret (&trans_sec,
j, j,
@ -182,22 +188,21 @@ TALER_EXCHANGE_get_melt_data_ (
&alg_values[j], &alg_values[j],
bks); bks);
/* Handle age commitment, if present */ if (NULL != rd->melt_age_commitment_proof)
if (NULL != md->melted_coin.age_commitment_proof)
{ {
fcd->age_commitment_proof[i] = GNUNET_new (struct fcd->age_commitment_proofs[i] = GNUNET_new (struct
TALER_AgeCommitmentProof); TALER_AgeCommitmentProof);
ach = GNUNET_new (struct TALER_AgeCommitmentHash);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_age_commitment_derive ( TALER_age_commitment_derive (
md->melted_coin.age_commitment_proof, md->melted_coin.age_commitment_proof,
&trans_sec.key, &trans_sec.key,
fcd->age_commitment_proof[i])); fcd->age_commitment_proofs[i]));
TALER_age_commitment_hash ( TALER_age_commitment_hash (
&fcd->age_commitment_proof[i]->commitment, &fcd->age_commitment_proofs[i]->commitment,
ach); &ach);
pah = &ach;
} }
if (TALER_DENOMINATION_CS == alg_values[j].cipher) if (TALER_DENOMINATION_CS == alg_values[j].cipher)
@ -208,7 +213,7 @@ TALER_EXCHANGE_get_melt_data_ (
&alg_values[j], &alg_values[j],
bks, bks,
coin_priv, coin_priv,
ach, pah,
&c_hash, &c_hash,
&pd)) &pd))
{ {

View File

@ -101,10 +101,9 @@ struct FreshCoinData
/** /**
* Arrays of age commitments and proofs to be created, one for each * Arrays of age commitments and proofs to be created, one for each
* cut-and-choose dimension. The entries in each list might be NULL and * cut-and-choose dimension. NULL if age restriction is not applicable.
* indicate no age commitment/restriction on the particular coin.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof[TALER_CNC_KAPPA]; struct TALER_AgeCommitmentProof *age_commitment_proofs[TALER_CNC_KAPPA];
/** /**
* Blinding key secrets for the coins, depending on the * Blinding key secrets for the coins, depending on the

View File

@ -125,8 +125,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
} }
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++) for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
{ {
struct TALER_EXCHANGE_RevealedCoinInfo *rci = struct TALER_EXCHANGE_RevealedCoinInfo *rci = &rcis[i];
&rcis[i];
const struct FreshCoinData *fcd = &rrh->md.fcds[i]; const struct FreshCoinData *fcd = &rrh->md.fcds[i];
const struct TALER_DenominationPublicKey *pk; const struct TALER_DenominationPublicKey *pk;
json_t *jsonai; json_t *jsonai;
@ -140,25 +139,25 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
}; };
struct TALER_FreshCoin coin; struct TALER_FreshCoin coin;
union TALER_DenominationBlindingKeyP bks; union TALER_DenominationBlindingKeyP bks;
const struct TALER_AgeCommitmentHash *pah = NULL;
rci->ps = fcd->ps[rrh->noreveal_index]; rci->ps = fcd->ps[rrh->noreveal_index];
rci->bks = fcd->bks[rrh->noreveal_index]; rci->bks = fcd->bks[rrh->noreveal_index];
rci->age_commitment_proof = fcd->age_commitment_proof[rrh->noreveal_index]; rci->age_commitment_proof = NULL;
rci->h_age_commitment = NULL;
pk = &fcd->fresh_pk; pk = &fcd->fresh_pk;
jsonai = json_array_get (jsona, i); jsonai = json_array_get (jsona, i);
GNUNET_assert (NULL != jsonai); GNUNET_assert (NULL != jsonai);
GNUNET_assert (
(NULL != rrh->md.melted_coin.age_commitment_proof) ==
(NULL != rci->age_commitment_proof));
if (NULL != rci->age_commitment_proof) if (NULL != rrh->md.melted_coin.age_commitment_proof)
{ {
rci->h_age_commitment = GNUNET_new (struct TALER_AgeCommitmentHash); rci->age_commitment_proof =
TALER_age_commitment_hash ( fcd->age_commitment_proofs[rrh->noreveal_index];
&rci->age_commitment_proof->commitment,
rci->h_age_commitment); TALER_age_commitment_hash (&rci->age_commitment_proof->commitment,
&rci->h_age_commitment);
pah = &rci->h_age_commitment;
} }
if (GNUNET_OK != if (GNUNET_OK !=
@ -180,18 +179,20 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
hence recomputing it here... */ hence recomputing it here... */
GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv,
&coin_pub.eddsa_pub); &coin_pub.eddsa_pub);
TALER_coin_pub_hash (&coin_pub, TALER_coin_pub_hash (
rci->h_age_commitment, &coin_pub,
&coin_hash); pah,
&coin_hash);
if (GNUNET_OK != if (GNUNET_OK !=
TALER_planchet_to_coin (pk, TALER_planchet_to_coin (
&blind_sig, pk,
&bks, &blind_sig,
&rci->coin_priv, &bks,
rci->h_age_commitment, &rci->coin_priv,
&coin_hash, pah,
&rrh->alg_values[i], &coin_hash,
&coin)) &rrh->alg_values[i],
&coin))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -257,7 +258,10 @@ handle_refresh_reveal_finished (void *cls,
rrh->reveal_cb = NULL; rrh->reveal_cb = NULL;
} }
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++) for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
{
TALER_denom_sig_free (&rcis[i].sig); TALER_denom_sig_free (&rcis[i].sig);
TALER_age_commitment_proof_free (rcis[i].age_commitment_proof);
}
TALER_EXCHANGE_refreshes_reveal_cancel (rrh); TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
return; return;
} }
@ -303,7 +307,6 @@ handle_refresh_reveal_finished (void *cls,
} }
/* FIXME: refactor this to use struct TALER_EXCHANGE_Handle */
struct TALER_EXCHANGE_RefreshesRevealHandle * struct TALER_EXCHANGE_RefreshesRevealHandle *
TALER_EXCHANGE_refreshes_reveal ( TALER_EXCHANGE_refreshes_reveal (
struct GNUNET_CURL_Context *ctx, struct GNUNET_CURL_Context *ctx,
@ -408,20 +411,19 @@ TALER_EXCHANGE_refreshes_reveal (
} }
/* build array of old age commitment, if applicable */ /* build array of old age commitment, if applicable */
GNUNET_assert ((NULL == rd->melt_age_commitment_proof) ==
(NULL == rd->melt_h_age_commitment));
if (NULL != rd->melt_age_commitment_proof) if (NULL != rd->melt_age_commitment_proof)
{ {
GNUNET_assert (NULL != rd->melt_h_age_commitment);
GNUNET_assert (NULL != (old_age_commitment = json_array ())); GNUNET_assert (NULL != (old_age_commitment = json_array ()));
for (size_t i = 0; i < rd->melt_age_commitment_proof->commitment.num; i++) for (size_t i = 0; i < rd->melt_age_commitment_proof->commitment.num; i++)
{ {
GNUNET_assert (0 == enum GNUNET_GenericReturnValue ret;
json_array_append_new ( ret = json_array_append_new (
old_age_commitment, old_age_commitment,
GNUNET_JSON_from_data_auto ( GNUNET_JSON_from_data_auto (
&rd->melt_age_commitment_proof-> &rd->melt_age_commitment_proof->commitment.keys[i]));
commitment.keys[i]))); GNUNET_assert (0 == ret);
} }
} }

View File

@ -126,10 +126,17 @@ mime_matches (const char *accept_pattern,
{ {
const char *da = strchr (accept_pattern, '/'); const char *da = strchr (accept_pattern, '/');
const char *dm = strchr (mime, '/'); const char *dm = strchr (mime, '/');
const char *end;
if ( (NULL == da) || if ( (NULL == da) ||
(NULL == dm) ) (NULL == dm) )
return (0 == strcmp ("*", accept_pattern)); return (0 == strcmp ("*", accept_pattern));
/* FIXME: eventually, we might want to parse the "q=$FLOAT"
part after the ';' and figure out which one is the
best/preferred match instead of returning a boolean... */
end = strchr (da, ';');
if (NULL == end)
end = &da[strlen (da)];
return return
( ( (1 == da - accept_pattern) && ( ( (1 == da - accept_pattern) &&
('*' == *accept_pattern) ) || ('*' == *accept_pattern) ) ||
@ -138,8 +145,9 @@ mime_matches (const char *accept_pattern,
mime, mime,
da - accept_pattern)) ) ) && da - accept_pattern)) ) ) &&
( (0 == strcmp (da, "/*")) || ( (0 == strcmp (da, "/*")) ||
(0 == strcasecmp (da, (0 == strncasecmp (da,
dm)) ); dm,
end - da)) );
} }
@ -150,9 +158,9 @@ TALER_MHD_xmime_matches (const char *accept_pattern,
char *ap = GNUNET_strdup (accept_pattern); char *ap = GNUNET_strdup (accept_pattern);
char *sptr; char *sptr;
for (const char *tok = strtok_r (ap, ";", &sptr); for (const char *tok = strtok_r (ap, ",", &sptr);
NULL != tok; NULL != tok;
tok = strtok_r (NULL, ";", &sptr)) tok = strtok_r (NULL, ",", &sptr))
{ {
if (mime_matches (tok, if (mime_matches (tok,
mime)) mime))

View File

@ -59,9 +59,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_batch_withdraw.c \ testing_api_cmd_batch_withdraw.c \
testing_api_cmd_check_aml_decision.c \ testing_api_cmd_check_aml_decision.c \
testing_api_cmd_check_aml_decisions.c \ testing_api_cmd_check_aml_decisions.c \
testing_api_cmd_check_keys.c \
testing_api_cmd_common.c \ testing_api_cmd_common.c \
testing_api_cmd_connect_with_state.c \
testing_api_cmd_contract_get.c \ testing_api_cmd_contract_get.c \
testing_api_cmd_deposit.c \ testing_api_cmd_deposit.c \
testing_api_cmd_deposits_get.c \ testing_api_cmd_deposits_get.c \
@ -106,7 +104,6 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_revoke_denom_key.c \ testing_api_cmd_revoke_denom_key.c \
testing_api_cmd_revoke_sign_key.c \ testing_api_cmd_revoke_sign_key.c \
testing_api_cmd_run_fakebank.c \ testing_api_cmd_run_fakebank.c \
testing_api_cmd_serialize_keys.c \
testing_api_cmd_set_officer.c \ testing_api_cmd_set_officer.c \
testing_api_cmd_set_wire_fee.c \ testing_api_cmd_set_wire_fee.c \
testing_api_cmd_signal.c \ testing_api_cmd_signal.c \

View File

@ -251,7 +251,7 @@ then
echo -n "Configuring sandbox " echo -n "Configuring sandbox "
libeufin-sandbox config --currency "$CURRENCY" default &> libeufin-sandbox-config.log libeufin-sandbox config --currency "$CURRENCY" default &> libeufin-sandbox-config.log
echo "DONE" echo "DONE"
echo -n "Launching sandbox " echo -n "Launching sandbox ... "
export LIBEUFIN_SANDBOX_ADMIN_PASSWORD="secret" export LIBEUFIN_SANDBOX_ADMIN_PASSWORD="secret"
libeufin-sandbox serve \ libeufin-sandbox serve \
--port "$SANDBOX_PORT" \ --port "$SANDBOX_PORT" \
@ -660,6 +660,8 @@ then
enable-account "$EXCHANGE_PAYTO_URI" \ enable-account "$EXCHANGE_PAYTO_URI" \
upload &> "taler-exchange-offline-account.log" upload &> "taler-exchange-offline-account.log"
echo " OK" echo " OK"
else
echo "WARNING: Account ${USE_ACCOUNT} not enabled (set to: '$ENABLED')"
fi fi
if [ "1" = "$START_AUDITOR" ] if [ "1" = "$START_AUDITOR" ]
then then

View File

@ -653,12 +653,12 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_get_auditor ("get-auditor", TALER_TESTING_cmd_get_auditor ("get-auditor",
cred.cfg, cred.cfg,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_exec_auditor_offline ("auditor-offline", TALER_TESTING_cmd_exec_auditor_offline ("auditor-offline",
config_file), config_file),
CMD_RUN_AUDITOR ("virgin-auditor"), CMD_RUN_AUDITOR ("virgin-auditor"),

View File

@ -78,6 +78,9 @@ run (void *cls,
case TALER_TESTING_BS_IBAN: case TALER_TESTING_BS_IBAN:
ssoptions = "-ns"; ssoptions = "-ns";
break; break;
default:
ssoptions = NULL;
break;
} }
memset (&wtid, memset (&wtid,
42, 42,

View File

@ -660,7 +660,6 @@ run (void *cls,
"refresh-reveal-age-1", "refresh-reveal-age-1",
MHD_HTTP_CONFLICT, MHD_HTTP_CONFLICT,
NULL), NULL),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };
@ -1236,9 +1235,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("wire", TALER_TESTING_cmd_batch ("wire",
wire), wire),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",

View File

@ -21,7 +21,7 @@ CONFIG = "postgres:///talercheck"
HTTP_PORT = 8082 HTTP_PORT = 8082
[exchange] [exchange]
TERMS_ETAG = 0 TERMS_ETAG = tos
PRIVACY_ETAG = 0 PRIVACY_ETAG = 0
AML_THRESHOLD = EUR:1000000 AML_THRESHOLD = EUR:1000000
PORT = 8081 PORT = 8081
@ -34,6 +34,9 @@ EXPIRE_IDLE_SLEEP_INTERVAL = 1 s
[exchangedb-postgres] [exchangedb-postgres]
CONFIG = "postgres:///talercheck" CONFIG = "postgres:///talercheck"
[taler-exchange-secmod-cs]
LOOKAHEAD_SIGN = 24 days
[taler-exchange-secmod-rsa] [taler-exchange-secmod-rsa]
LOOKAHEAD_SIGN = 24 days LOOKAHEAD_SIGN = 24 days

View File

@ -65,22 +65,21 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("initial-/keys"),
TALER_TESTING_cmd_sleep ("sleep", TALER_TESTING_cmd_sleep ("sleep",
6 /* seconds */), 6 /* seconds */),
TALER_TESTING_cmd_check_keys ("check-keys-1"), TALER_TESTING_cmd_get_exchange ("get-exchange-1",
TALER_TESTING_cmd_check_keys_with_last_denom ("check-keys-2", cred.cfg,
"check-keys-1"), "get-exchange",
TALER_TESTING_cmd_serialize_keys ("serialize-keys"), true,
TALER_TESTING_cmd_connect_with_state ("reconnect-with-state", true),
"serialize-keys"), TALER_TESTING_cmd_get_exchange ("get-exchange-2",
/** cred.cfg,
* Make sure we have the same keys situation as "get-exchange-1",
* it was before the serialization. true,
*/ true),
TALER_TESTING_cmd_check_keys ("check-keys-after-deserialization"),
/** /**
* Use one of the deserialized keys. * Use one of the deserialized keys.
*/ */

View File

@ -69,13 +69,19 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-1",
cred.cfg,
"get-exchange",
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-2",
cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_check_keys ("first-download"),
/* Causes GET /keys?last_denom_issue=0 */
TALER_TESTING_cmd_check_keys_with_last_denom ("second-download",
"zero"),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -67,20 +67,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
#if 0
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_wire_add ("add-wire-account",
"payto://x-taler-bank/localhost/2?receiver-name=2",
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
config_file),
#endif
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
/** /**
* Fill reserve with EUR:10.02, as withdraw fee is 1 ct per * Fill reserve with EUR:10.02, as withdraw fee is 1 ct per
* config. * config.

View File

@ -255,6 +255,7 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_batch ( TALER_TESTING_cmd_batch (

View File

@ -59,6 +59,7 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_get_auditor ("get-auditor", TALER_TESTING_cmd_get_auditor ("get-auditor",
@ -145,7 +146,16 @@ run (void *cls,
false), false),
TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys", TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys",
config_file), config_file),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"), TALER_TESTING_cmd_get_exchange ("get-exchange-1",
cred.cfg,
"get-exchange",
true,
true),
TALER_TESTING_cmd_get_exchange ("get-exchange-2",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -504,9 +504,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",
withdraw), withdraw),
TALER_TESTING_cmd_batch ("push", TALER_TESTING_cmd_batch ("push",

View File

@ -523,9 +523,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_batch ("withdraw", TALER_TESTING_cmd_batch ("withdraw",
withdraw), withdraw),
TALER_TESTING_cmd_batch ("spend", TALER_TESTING_cmd_batch ("spend",

View File

@ -87,9 +87,9 @@ run (void *cls,
NULL), NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange", TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg, cred.cfg,
NULL,
true, true,
true), true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"), TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"), CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"),
TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty", TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty",

View File

@ -76,7 +76,8 @@ auditor_add_cb (
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -81,7 +81,8 @@ denom_sig_add_cb (
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -77,7 +77,8 @@ auditor_del_cb (
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -170,7 +170,8 @@ deposit_confirmation_cb (
} }
} }
TALER_TESTING_unexpected_status (dcs->is, TALER_TESTING_unexpected_status (dcs->is,
hr->http_status); hr->http_status,
dcs->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (dcs->is); TALER_TESTING_interpreter_next (dcs->is);
@ -211,12 +212,8 @@ deposit_confirmation_run (void *cls,
const struct TALER_EXCHANGE_Keys *keys; const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_SigningPublicKey *spk; const struct TALER_EXCHANGE_SigningPublicKey *spk;
const char *auditor_url; const char *auditor_url;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd; (void) cmd;
if (NULL == exchange)
return;
dcs->is = is; dcs->is = is;
GNUNET_assert (NULL != dcs->deposit_reference); GNUNET_assert (NULL != dcs->deposit_reference);
{ {
@ -267,7 +264,7 @@ deposit_confirmation_run (void *cls,
dcs->coin_index, dcs->coin_index,
&wire_deadline)); &wire_deadline));
GNUNET_assert (NULL != exchange_timestamp); GNUNET_assert (NULL != exchange_timestamp);
keys = TALER_EXCHANGE_get_keys (exchange); keys = TALER_TESTING_get_keys (is);
GNUNET_assert (NULL != keys); GNUNET_assert (NULL != keys);
spk = TALER_EXCHANGE_get_signing_key_info (keys, spk = TALER_EXCHANGE_get_signing_key_info (keys,
exchange_pub); exchange_pub);

View File

@ -120,10 +120,8 @@ do_retry (void *cls)
/** /**
* Callback to analyze the /exchanges response. * Callback to analyze the /exchanges response.
* *
* @param cls closure. * @param cls closure of type struct ExchangesState*
* @param hr HTTP response details * @param ler Response to the GET /exchanges request
* @param num_exchanges length of the @a ei array
* @param ei array with information about the exchanges
*/ */
static void static void
exchanges_cb (void *cls, exchanges_cb (void *cls,
@ -160,7 +158,8 @@ exchanges_cb (void *cls,
} }
} }
TALER_TESTING_unexpected_status (es->is, TALER_TESTING_unexpected_status (es->is,
hr->http_status); hr->http_status,
es->expected_response_code);
return; return;
} }
if (MHD_HTTP_OK != hr->http_status) if (MHD_HTTP_OK != hr->http_status)

View File

@ -199,7 +199,8 @@ confirmation_cb (void *cls,
} }
} }
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
tr->http_status); tr->http_status,
MHD_HTTP_OK);
return; return;
} }

View File

@ -199,7 +199,8 @@ batch_deposit_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
if (MHD_HTTP_OK == dr->hr.http_status) if (MHD_HTTP_OK == dr->hr.http_status)

View File

@ -79,10 +79,10 @@ struct CoinState
/** /**
* If age > 0, put here the corresponding age commitment with its proof and * If age > 0, put here the corresponding age commitment with its proof and
* its hash, respectivelly, NULL otherwise. * its hash, respectivelly.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof; struct TALER_AgeCommitmentProof age_commitment_proof;
struct TALER_AgeCommitmentHash *h_age_commitment; struct TALER_AgeCommitmentHash h_age_commitment;
/** /**
* Reserve history entry that corresponds to this coin. * Reserve history entry that corresponds to this coin.
@ -190,7 +190,8 @@ reserve_batch_withdraw_cb (void *cls,
if (ws->expected_response_code != wr->hr.http_status) if (ws->expected_response_code != wr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
wr->hr.http_status); wr->hr.http_status,
ws->expected_response_code);
return; return;
} }
switch (wr->hr.http_status) switch (wr->hr.http_status)
@ -253,12 +254,8 @@ batch_withdraw_run (void *cls,
const struct TALER_TESTING_Command *create_reserve; const struct TALER_TESTING_Command *create_reserve;
const struct TALER_EXCHANGE_DenomPublicKey *dpk; const struct TALER_EXCHANGE_DenomPublicKey *dpk;
struct TALER_EXCHANGE_WithdrawCoinInput wcis[ws->num_coins]; struct TALER_EXCHANGE_WithdrawCoinInput wcis[ws->num_coins];
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd; (void) cmd;
if (NULL == exchange)
return;
ws->is = is; ws->is = is;
create_reserve create_reserve
= TALER_TESTING_interpreter_lookup_command ( = TALER_TESTING_interpreter_lookup_command (
@ -281,7 +278,7 @@ batch_withdraw_run (void *cls,
} }
if (NULL == ws->exchange_url) if (NULL == ws->exchange_url)
ws->exchange_url ws->exchange_url
= GNUNET_strdup (TALER_EXCHANGE_get_base_url (exchange)); = GNUNET_strdup (TALER_TESTING_get_exchange_url (is));
ws->reserve_priv = *rp; ws->reserve_priv = *rp;
GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv,
&ws->reserve_pub.eddsa_pub); &ws->reserve_pub.eddsa_pub);
@ -295,7 +292,7 @@ batch_withdraw_run (void *cls,
struct TALER_EXCHANGE_WithdrawCoinInput *wci = &wcis[i]; struct TALER_EXCHANGE_WithdrawCoinInput *wci = &wcis[i];
TALER_planchet_master_setup_random (&cs->ps); TALER_planchet_master_setup_random (&cs->ps);
dpk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (exchange), dpk = TALER_TESTING_find_pk (TALER_TESTING_get_keys (is),
&cs->amount, &cs->amount,
ws->age > 0); ws->age > 0);
if (NULL == dpk) if (NULL == dpk)
@ -319,7 +316,7 @@ batch_withdraw_run (void *cls,
wci->pk = cs->pk; wci->pk = cs->pk;
wci->ps = &cs->ps; wci->ps = &cs->ps;
wci->ach = cs->h_age_commitment; wci->ach = &cs->h_age_commitment;
} }
ws->wsh = TALER_EXCHANGE_batch_withdraw ( ws->wsh = TALER_EXCHANGE_batch_withdraw (
TALER_TESTING_interpreter_get_context (is), TALER_TESTING_interpreter_get_context (is),
@ -369,13 +366,8 @@ batch_withdraw_cleanup (void *cls,
TALER_EXCHANGE_destroy_denomination_key (cs->pk); TALER_EXCHANGE_destroy_denomination_key (cs->pk);
cs->pk = NULL; cs->pk = NULL;
} }
if (NULL != cs->age_commitment_proof) if (0 < ws->age)
{ TALER_age_commitment_proof_free (&cs->age_commitment_proof);
TALER_age_commitment_proof_free (cs->age_commitment_proof);
cs->age_commitment_proof = NULL;
}
if (NULL != cs->h_age_commitment)
GNUNET_free (cs->h_age_commitment);
} }
GNUNET_free (ws->coins); GNUNET_free (ws->coins);
GNUNET_free (ws->exchange_url); GNUNET_free (ws->exchange_url);
@ -427,9 +419,13 @@ batch_withdraw_traits (void *cls,
TALER_TESTING_make_trait_payto_uri (ws->reserve_payto_uri), TALER_TESTING_make_trait_payto_uri (ws->reserve_payto_uri),
TALER_TESTING_make_trait_exchange_url (ws->exchange_url), TALER_TESTING_make_trait_exchange_url (ws->exchange_url),
TALER_TESTING_make_trait_age_commitment_proof (index, TALER_TESTING_make_trait_age_commitment_proof (index,
cs->age_commitment_proof), ws->age > 0 ?
&cs->age_commitment_proof:
NULL),
TALER_TESTING_make_trait_h_age_commitment (index, TALER_TESTING_make_trait_h_age_commitment (index,
cs->h_age_commitment), ws->age > 0 ?
&cs->h_age_commitment :
NULL),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -476,13 +472,9 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
if (0 < age) if (0 < age)
{ {
struct TALER_AgeCommitmentProof *acp;
struct TALER_AgeCommitmentHash *hac;
struct GNUNET_HashCode seed; struct GNUNET_HashCode seed;
struct TALER_AgeMask mask; struct TALER_AgeMask mask;
acp = GNUNET_new (struct TALER_AgeCommitmentProof);
hac = GNUNET_new (struct TALER_AgeCommitmentHash);
mask = TALER_extensions_get_age_restriction_mask (); mask = TALER_extensions_get_age_restriction_mask ();
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&seed, &seed,
@ -493,7 +485,7 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
&mask, &mask,
age, age,
&seed, &seed,
acp)) &cs->age_commitment_proof))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to generate age commitment for age %d at %s\n", "Failed to generate age commitment for age %d at %s\n",
@ -502,10 +494,8 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
GNUNET_assert (0); GNUNET_assert (0);
} }
TALER_age_commitment_hash (&acp->commitment, TALER_age_commitment_hash (&cs->age_commitment_proof.commitment,
hac); &cs->h_age_commitment);
cs->age_commitment_proof = acp;
cs->h_age_commitment = hac;
} }
if (GNUNET_OK != if (GNUNET_OK !=

View File

@ -80,7 +80,8 @@ check_aml_decision_cb (void *cls,
if (ds->expected_http_status != adr->hr.http_status) if (ds->expected_http_status != adr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
adr->hr.http_status); adr->hr.http_status,
ds->expected_http_status);
return; return;
} }
if (MHD_HTTP_OK == adr->hr.http_status) if (MHD_HTTP_OK == adr->hr.http_status)

View File

@ -80,7 +80,8 @@ check_aml_decisions_cb (void *cls,
if (ds->expected_http_status != adr->hr.http_status) if (ds->expected_http_status != adr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
adr->hr.http_status); adr->hr.http_status,
ds->expected_http_status);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -1,251 +0,0 @@
/*
This file is part of TALER
(C) 2018, 2020, 2021 Taler Systems SA
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 testing/testing_api_cmd_check_keys.c
* @brief Implementation of "check keys" test command.
* @author Marcello Stanisci
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_testing_lib.h"
/**
* State for a "check keys" CMD.
*/
struct CheckKeysState
{
/**
* If this value is true, then the "cherry picking" facility is turned off;
* whole /keys is downloaded.
*/
bool pull_all_keys;
/**
* Label of a command to use to derive the "last_denom_issue" date to use.
*/
const char *last_denom_date_ref;
/**
* Our interpreter state.
*/
struct TALER_TESTING_Interpreter *is;
/**
* Last denomination date we received when doing this request.
*/
struct GNUNET_TIME_Timestamp my_denom_date;
};
/**
* Function called with information about who is auditing
* a particular exchange and what keys the exchange is using.
*
* @param cls closure
* @param kr response from /keys
*/
static void
keys_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr)
{
struct CheckKeysState *cks = cls;
if (MHD_HTTP_OK != kr->hr.http_status)
{
TALER_TESTING_unexpected_status (cks->is,
kr->hr.http_status);
return;
}
cks->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
TALER_TESTING_interpreter_next (cks->is);
}
/**
* Run the "check keys" command.
*
* @param cls closure.
* @param cmd the command currently being executed.
* @param is the interpreter state.
*/
static void
check_keys_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct CheckKeysState *cks = cls;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
struct GNUNET_TIME_Timestamp rdate;
(void) cmd;
cks->is = is;
if (NULL == exchange)
return;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Triggering GET /keys, cmd `%s'\n",
cmd->label);
if (NULL != cks->last_denom_date_ref)
{
if (0 == strcmp ("zero",
cks->last_denom_date_ref))
{
TALER_LOG_DEBUG ("Forcing last_denom_date URL argument set to zero\n");
TALER_EXCHANGE_set_last_denom (exchange,
GNUNET_TIME_UNIT_ZERO_TS);
}
else
{
const struct GNUNET_TIME_Timestamp *last_denom_date;
const struct TALER_TESTING_Command *ref;
ref = TALER_TESTING_interpreter_lookup_command (is,
cks->last_denom_date_ref);
if (NULL == ref)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_timestamp (ref,
0,
&last_denom_date))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
TALER_LOG_DEBUG ("Forcing last_denom_date URL argument\n");
TALER_EXCHANGE_set_last_denom (exchange,
*last_denom_date);
}
}
rdate = TALER_EXCHANGE_check_keys_current (
exchange,
cks->pull_all_keys
? TALER_EXCHANGE_CKF_FORCE_ALL_NOW
: TALER_EXCHANGE_CKF_FORCE_DOWNLOAD,
&keys_cb,
cks);
/* Redownload /keys. */
GNUNET_break (GNUNET_TIME_absolute_is_zero (rdate.abs_time));
}
/**
* Cleanup the state.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
check_keys_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct CheckKeysState *cks = cls;
(void) cmd;
GNUNET_free (cks);
}
/**
* Offer internal data to a "check_keys" CMD state to other
* commands.
*
* @param cls closure
* @param[out] ret result (could be anything)
* @param trait name of the trait
* @param index index number of the object to offer.
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
check_keys_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct CheckKeysState *cks = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_timestamp (0,
&cks->my_denom_date),
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys (const char *label)
{
struct CheckKeysState *cks;
cks = GNUNET_new (struct CheckKeysState);
{
struct TALER_TESTING_Command cmd = {
.cls = cks,
.label = label,
.run = &check_keys_run,
.cleanup = &check_keys_cleanup,
.traits = &check_keys_traits
};
return cmd;
}
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_pull_all_keys (const char *label)
{
struct TALER_TESTING_Command cmd
= TALER_TESTING_cmd_check_keys (label);
struct CheckKeysState *cks = cmd.cls;
cks->pull_all_keys = true;
return cmd;
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_keys_with_last_denom (
const char *label,
const char *last_denom_date_ref)
{
struct TALER_TESTING_Command cmd
= TALER_TESTING_cmd_check_keys (label);
struct CheckKeysState *cks = cmd.cls;
cks->last_denom_date_ref = last_denom_date_ref;
return cmd;
}
/* end of testing_api_cmd_check_keys.c */

View File

@ -1,191 +0,0 @@
/*
This file is part of TALER
(C) 2018-2023 Taler Systems SA
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 testing/testing_api_cmd_connect_with_state.c
* @brief Lets tests use the keys deserialization API.
* @author Marcello Stanisci
*/
#include "platform.h"
#include <jansson.h>
#include "taler_testing_lib.h"
/**
* Internal state for a connect-with-state CMD.
*/
struct ConnectWithStateState
{
/**
* Reference to a CMD that offers a serialized key-state
* that will be used in the reconnection.
*/
const char *state_reference;
/**
* Interpreter state.
*/
struct TALER_TESTING_Interpreter *is;
/**
* New exchange handle.
*/
struct TALER_EXCHANGE_Handle *exchange;
};
static void
cert_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr)
{
struct ConnectWithStateState *cwss = cls;
struct TALER_TESTING_Interpreter *is = cwss->is;
const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
switch (hr->http_status)
{
case MHD_HTTP_OK:
/* dealt with below */
break;
default:
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Got failure response %u/%d for /keys!\n",
hr->http_status,
(int) hr->ec);
TALER_TESTING_interpreter_fail (is);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got %d DK from /keys\n",
kr->details.ok.keys->num_denom_keys);
TALER_TESTING_interpreter_next (is);
}
/**
* Run the command.
*
* @param cls closure.
* @param cmd the command to execute.
* @param is the interpreter state.
*/
static void
connect_with_state_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct ConnectWithStateState *cwss = cls;
const struct TALER_TESTING_Command *state_cmd;
const json_t *serialized_keys;
const char *exchange_url;
cwss->is = is;
state_cmd = TALER_TESTING_interpreter_lookup_command (is,
cwss->state_reference);
if (NULL == state_cmd)
{
/* Command providing serialized keys not found. */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_exchange_keys (state_cmd,
&serialized_keys));
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_exchange_url (state_cmd,
&exchange_url));
cwss->exchange
= TALER_EXCHANGE_connect (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
&cert_cb,
cwss,
TALER_EXCHANGE_OPTION_DATA,
serialized_keys,
TALER_EXCHANGE_OPTION_END);
}
/**
* Offer exchange connection as trait.
*
* @param cls closure.
* @param[out] ret result.
* @param trait name of the trait.
* @param index index number of the object to offer.
* @return #GNUNET_OK on success.
*/
static enum GNUNET_GenericReturnValue
connect_with_state_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct ConnectWithStateState *cwss = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_exchange (cwss->exchange),
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
/**
* Cleanup the state of a "connect with state" CMD. Just
* a placeholder to avoid jumping on an invalid address.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
connect_with_state_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct ConnectWithStateState *cwss = cls;
GNUNET_free (cwss);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_connect_with_state (const char *label,
const char *state_reference)
{
struct ConnectWithStateState *cwss;
cwss = GNUNET_new (struct ConnectWithStateState);
cwss->state_reference = state_reference;
{
struct TALER_TESTING_Command cmd = {
.cls = cwss,
.label = label,
.run = connect_with_state_run,
.cleanup = connect_with_state_cleanup,
.traits = connect_with_state_traits
};
return cmd;
}
}

View File

@ -102,7 +102,8 @@ get_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
ref = TALER_TESTING_interpreter_lookup_command (ds->is, ref = TALER_TESTING_interpreter_lookup_command (ds->is,

View File

@ -248,8 +248,12 @@ deposit_cb (void *cls,
return; return;
} }
} }
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status_with_body (
dr->hr.http_status); ds->is,
dr->hr.http_status,
ds->expected_response_code,
dr->hr.reply);
return; return;
} }
if (MHD_HTTP_OK == dr->hr.http_status) if (MHD_HTTP_OK == dr->hr.http_status)
@ -280,8 +284,7 @@ deposit_run (void *cls,
const struct TALER_TESTING_Command *coin_cmd; const struct TALER_TESTING_Command *coin_cmd;
const struct TALER_CoinSpendPrivateKeyP *coin_priv; const struct TALER_CoinSpendPrivateKeyP *coin_priv;
struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPublicKeyP coin_pub;
const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL; const struct TALER_AgeCommitmentHash *phac;
struct TALER_AgeCommitmentHash h_age_commitment = {0};
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
const struct TALER_DenominationSignature *denom_pub_sig; const struct TALER_DenominationSignature *denom_pub_sig;
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
@ -385,9 +388,9 @@ deposit_run (void *cls,
ds->coin_index, ds->coin_index,
&coin_priv)) || &coin_priv)) ||
(GNUNET_OK != (GNUNET_OK !=
TALER_TESTING_get_trait_age_commitment_proof (coin_cmd, TALER_TESTING_get_trait_h_age_commitment (coin_cmd,
ds->coin_index, ds->coin_index,
&age_commitment_proof)) || &phac)) ||
(GNUNET_OK != (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (coin_cmd, TALER_TESTING_get_trait_denom_pub (coin_cmd,
ds->coin_index, ds->coin_index,
@ -405,11 +408,6 @@ deposit_run (void *cls,
return; return;
} }
if (NULL != age_commitment_proof)
{
TALER_age_commitment_hash (&age_commitment_proof->commitment,
&h_age_commitment);
}
ds->deposit_fee = denom_pub->fees.deposit; ds->deposit_fee = denom_pub->fees.deposit;
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
&coin_pub.eddsa_pub); &coin_pub.eddsa_pub);
@ -443,7 +441,7 @@ deposit_run (void *cls,
&denom_pub->fees.deposit, &denom_pub->fees.deposit,
&h_wire, &h_wire,
&h_contract_terms, &h_contract_terms,
&h_age_commitment, phac,
NULL, /* FIXME #7270: add hash of extensions */ NULL, /* FIXME #7270: add hash of extensions */
&denom_pub->h_key, &denom_pub->h_key,
ds->wallet_timestamp, ds->wallet_timestamp,
@ -456,11 +454,11 @@ deposit_run (void *cls,
{ {
struct TALER_EXCHANGE_CoinDepositDetail cdd = { struct TALER_EXCHANGE_CoinDepositDetail cdd = {
.amount = ds->amount, .amount = ds->amount,
.h_age_commitment = h_age_commitment,
.coin_pub = coin_pub, .coin_pub = coin_pub,
.coin_sig = coin_sig, .coin_sig = coin_sig,
.denom_sig = *denom_pub_sig, .denom_sig = *denom_pub_sig,
.h_denom_pub = denom_pub->h_key .h_denom_pub = denom_pub->h_key,
.h_age_commitment = {{{0}}},
}; };
struct TALER_EXCHANGE_DepositContractDetail dcd = { struct TALER_EXCHANGE_DepositContractDetail dcd = {
.wire_deadline = ds->wire_deadline, .wire_deadline = ds->wire_deadline,
@ -473,6 +471,9 @@ deposit_run (void *cls,
.refund_deadline = ds->refund_deadline .refund_deadline = ds->refund_deadline
}; };
if (NULL != phac)
cdd.h_age_commitment = *phac;
ds->dh = TALER_EXCHANGE_batch_deposit ( ds->dh = TALER_EXCHANGE_batch_deposit (
TALER_TESTING_interpreter_get_context (is), TALER_TESTING_interpreter_get_context (is),
exchange_url, exchange_url,
@ -547,6 +548,7 @@ deposit_traits (void *cls,
/* Will point to coin cmd internals. */ /* Will point to coin cmd internals. */
const struct TALER_CoinSpendPrivateKeyP *coin_spent_priv; const struct TALER_CoinSpendPrivateKeyP *coin_spent_priv;
const struct TALER_AgeCommitmentProof *age_commitment_proof; const struct TALER_AgeCommitmentProof *age_commitment_proof;
const struct TALER_AgeCommitmentHash *h_age_commitment;
if (GNUNET_YES != ds->command_initialized) if (GNUNET_YES != ds->command_initialized)
{ {
@ -571,12 +573,17 @@ deposit_traits (void *cls,
(GNUNET_OK != (GNUNET_OK !=
TALER_TESTING_get_trait_age_commitment_proof (coin_cmd, TALER_TESTING_get_trait_age_commitment_proof (coin_cmd,
ds->coin_index, ds->coin_index,
&age_commitment_proof)) ) &age_commitment_proof)) ||
(GNUNET_OK !=
TALER_TESTING_get_trait_h_age_commitment (coin_cmd,
ds->coin_index,
&h_age_commitment)) )
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (ds->is); TALER_TESTING_interpreter_fail (ds->is);
return GNUNET_NO; return GNUNET_NO;
} }
{ {
struct TALER_TESTING_Trait traits[] = { struct TALER_TESTING_Trait traits[] = {
/* First two traits are only available if /* First two traits are only available if
@ -590,6 +597,8 @@ deposit_traits (void *cls,
coin_spent_priv), coin_spent_priv),
TALER_TESTING_make_trait_age_commitment_proof (0, TALER_TESTING_make_trait_age_commitment_proof (0,
age_commitment_proof), age_commitment_proof),
TALER_TESTING_make_trait_h_age_commitment (0,
h_age_commitment),
TALER_TESTING_make_trait_wire_details (ds->wire_details), TALER_TESTING_make_trait_wire_details (ds->wire_details),
TALER_TESTING_make_trait_contract_terms (ds->contract_terms), TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
TALER_TESTING_make_trait_merchant_priv (&ds->merchant_priv), TALER_TESTING_make_trait_merchant_priv (&ds->merchant_priv),

View File

@ -117,7 +117,8 @@ deposit_wtid_cb (void *cls,
if (tts->expected_response_code != dr->hr.http_status) if (tts->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
dr->hr.http_status); dr->hr.http_status,
tts->expected_response_code);
return; return;
} }
switch (dr->hr.http_status) switch (dr->hr.http_status)

View File

@ -83,7 +83,8 @@ version_cb (
if (MHD_HTTP_OK != vr->hr.http_status) if (MHD_HTTP_OK != vr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (gas->is, TALER_TESTING_unexpected_status (gas->is,
vr->hr.http_status); vr->hr.http_status,
MHD_HTTP_OK);
return; return;
} }
if ( (NULL != gas->priv_file) && if ( (NULL != gas->priv_file) &&

View File

@ -46,7 +46,12 @@ struct GetExchangeState
/** /**
* Exchange handle we produced. * Exchange handle we produced.
*/ */
struct TALER_EXCHANGE_Handle *exchange; struct TALER_EXCHANGE_GetKeysHandle *exchange;
/**
* Keys of the exchange.
*/
struct TALER_EXCHANGE_Keys *keys;
/** /**
* URL of the exchange. * URL of the exchange.
@ -58,6 +63,17 @@ struct GetExchangeState
*/ */
char *master_priv_file; char *master_priv_file;
/**
* Label of a command to use to obtain existing
* keys.
*/
const char *last_keys_ref;
/**
* Last denomination date we received when doing this request.
*/
struct GNUNET_TIME_Timestamp my_denom_date;
/** /**
* Are we waiting for /keys before continuing? * Are we waiting for /keys before continuing?
*/ */
@ -65,14 +81,25 @@ struct GetExchangeState
}; };
/**
* Function called with information about who is auditing
* a particular exchange and what keys the exchange is using.
*
* @param cls closure
* @param kr response from /keys
* @param[in] keys the keys of the exchange
*/
static void static void
cert_cb (void *cls, cert_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr) const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys)
{ {
struct GetExchangeState *ges = cls; struct GetExchangeState *ges = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr; const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
struct TALER_TESTING_Interpreter *is = ges->is; struct TALER_TESTING_Interpreter *is = ges->is;
ges->exchange = NULL;
ges->keys = keys;
switch (hr->http_status) switch (hr->http_status)
{ {
case MHD_HTTP_OK: case MHD_HTTP_OK:
@ -82,11 +109,13 @@ cert_cb (void *cls,
TALER_TESTING_interpreter_next (is); TALER_TESTING_interpreter_next (is);
return; return;
} }
ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
return; return;
default: default:
GNUNET_break (0); GNUNET_break (0);
TALER_EXCHANGE_disconnect (ges->exchange); GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
ges->exchange = NULL; "/keys responded with HTTP status %u\n",
hr->http_status);
if (ges->wait_for_keys) if (ges->wait_for_keys)
{ {
ges->wait_for_keys = false; ges->wait_for_keys = false;
@ -111,6 +140,7 @@ get_exchange_run (void *cls,
struct TALER_TESTING_Interpreter *is) struct TALER_TESTING_Interpreter *is)
{ {
struct GetExchangeState *ges = cls; struct GetExchangeState *ges = cls;
struct TALER_EXCHANGE_Keys *xkeys = NULL;
(void) cmd; (void) cmd;
if (NULL == ges->exchange_url) if (NULL == ges->exchange_url)
@ -119,6 +149,72 @@ get_exchange_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (NULL != ges->last_keys_ref)
{
const struct TALER_TESTING_Command *state_cmd;
struct TALER_EXCHANGE_Keys *old_keys;
const char *exchange_url;
json_t *s_keys;
state_cmd
= TALER_TESTING_interpreter_lookup_command (is,
ges->last_keys_ref);
if (NULL == state_cmd)
{
/* Command providing serialized keys not found. */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_keys (state_cmd,
&old_keys))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (NULL == old_keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_exchange_url (state_cmd,
&exchange_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (0 != strcmp (exchange_url,
ges->exchange_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
s_keys = TALER_EXCHANGE_keys_to_json (old_keys);
if (NULL == s_keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
xkeys = TALER_EXCHANGE_keys_from_json (s_keys);
if (NULL == xkeys)
{
GNUNET_break (0);
json_dumpf (s_keys,
stderr,
JSON_INDENT (2));
json_decref (s_keys);
TALER_TESTING_interpreter_fail (is);
return;
}
json_decref (s_keys);
}
if (NULL != ges->master_priv_file) if (NULL != ges->master_priv_file)
{ {
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
@ -127,17 +223,19 @@ get_exchange_run (void *cls,
&ges->master_priv.eddsa_priv)) &ges->master_priv.eddsa_priv))
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_EXCHANGE_keys_decref (xkeys);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
} }
ges->is = is; ges->is = is;
ges->exchange ges->exchange
= TALER_EXCHANGE_connect (TALER_TESTING_interpreter_get_context (is), = TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is),
ges->exchange_url, ges->exchange_url,
&cert_cb, xkeys,
ges, &cert_cb,
TALER_EXCHANGE_OPTION_END); ges);
TALER_EXCHANGE_keys_decref (xkeys);
if (NULL == ges->exchange) if (NULL == ges->exchange)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -163,9 +261,11 @@ get_exchange_cleanup (void *cls,
if (NULL != ges->exchange) if (NULL != ges->exchange)
{ {
TALER_EXCHANGE_disconnect (ges->exchange); TALER_EXCHANGE_get_keys_cancel (ges->exchange);
ges->exchange = NULL; ges->exchange = NULL;
} }
TALER_EXCHANGE_keys_decref (ges->keys);
ges->keys = NULL;
GNUNET_free (ges->master_priv_file); GNUNET_free (ges->master_priv_file);
GNUNET_free (ges->exchange_url); GNUNET_free (ges->exchange_url);
GNUNET_free (ges); GNUNET_free (ges);
@ -189,17 +289,16 @@ get_exchange_traits (void *cls,
{ {
struct GetExchangeState *ges = cls; struct GetExchangeState *ges = cls;
unsigned int off = (NULL == ges->master_priv_file) ? 1 : 0; unsigned int off = (NULL == ges->master_priv_file) ? 1 : 0;
struct TALER_EXCHANGE_Keys *keys
= TALER_EXCHANGE_get_keys (ges->exchange);
if (NULL != keys) if (NULL != ges->keys)
{ {
struct TALER_TESTING_Trait traits[] = { struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_master_priv (&ges->master_priv), TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_master_pub (&keys->master_pub), TALER_TESTING_make_trait_master_pub (&ges->keys->master_pub),
TALER_TESTING_make_trait_exchange (ges->exchange), TALER_TESTING_make_trait_keys (ges->keys),
TALER_TESTING_make_trait_keys (keys),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url), TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -212,8 +311,9 @@ get_exchange_traits (void *cls,
{ {
struct TALER_TESTING_Trait traits[] = { struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_master_priv (&ges->master_priv), TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_exchange (ges->exchange),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url), TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -284,6 +384,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange ( TALER_TESTING_cmd_get_exchange (
const char *label, const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys, bool wait_for_keys,
bool load_private_key) bool load_private_key)
{ {
@ -291,6 +392,7 @@ TALER_TESTING_cmd_get_exchange (
ges = GNUNET_new (struct GetExchangeState); ges = GNUNET_new (struct GetExchangeState);
ges->exchange_url = get_exchange_base_url (cfg); ges->exchange_url = get_exchange_base_url (cfg);
ges->last_keys_ref = last_keys_ref;
if (load_private_key) if (load_private_key)
ges->master_priv_file = get_exchange_master_priv_file (cfg); ges->master_priv_file = get_exchange_master_priv_file (cfg);
ges->wait_for_keys = wait_for_keys; ges->wait_for_keys = wait_for_keys;

View File

@ -78,7 +78,8 @@ check_kyc_cb (void *cls,
if (kcg->expected_response_code != ks->http_status) if (kcg->expected_response_code != ks->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
ks->http_status); ks->http_status,
kcg->expected_response_code);
return; return;
} }
switch (ks->http_status) switch (ks->http_status)

View File

@ -88,7 +88,8 @@ proof_kyc_cb (void *cls,
if (kcg->expected_response_code != kpr->http_status) if (kcg->expected_response_code != kpr->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
kpr->http_status); kpr->http_status,
kcg->expected_response_code);
return; return;
} }
switch (kpr->http_status) switch (kpr->http_status)

View File

@ -109,7 +109,8 @@ wallet_kyc_cb (void *cls,
if (kwg->expected_response_code != wkr->http_status) if (kwg->expected_response_code != wkr->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
wkr->http_status); wkr->http_status,
kwg->expected_response_code);
return; return;
} }
switch (wkr->http_status) switch (wkr->http_status)

View File

@ -163,7 +163,8 @@ deposit_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
if (MHD_HTTP_OK == dr->hr.http_status) if (MHD_HTTP_OK == dr->hr.http_status)

View File

@ -75,7 +75,8 @@ purse_delete_cb (void *cls,
if (pds->expected_response_code != pdr->hr.http_status) if (pds->expected_response_code != pdr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (pds->is, TALER_TESTING_unexpected_status (pds->is,
pdr->hr.http_status); pdr->hr.http_status,
pds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (pds->is); TALER_TESTING_interpreter_next (pds->is);

View File

@ -133,15 +133,13 @@ deposit_cb (void *cls,
const struct TALER_EXCHANGE_PurseDepositResponse *dr) const struct TALER_EXCHANGE_PurseDepositResponse *dr)
{ {
struct PurseDepositState *ds = cls; struct PurseDepositState *ds = cls;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (ds->is);
ds->dh = NULL; ds->dh = NULL;
GNUNET_assert (NULL != exchange);
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
if (MHD_HTTP_OK == dr->hr.http_status) if (MHD_HTTP_OK == dr->hr.http_status)
@ -197,10 +195,10 @@ deposit_cb (void *cls,
/* Deposits complete, create trait! */ /* Deposits complete, create trait! */
ds->reserve_history.type = TALER_EXCHANGE_RTT_MERGE; ds->reserve_history.type = TALER_EXCHANGE_RTT_MERGE;
{ {
const struct TALER_EXCHANGE_Keys *keys; struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_GlobalFee *gf; const struct TALER_EXCHANGE_GlobalFee *gf;
keys = TALER_EXCHANGE_get_keys (exchange); keys = TALER_TESTING_get_keys (ds->is);
GNUNET_assert (NULL != keys); GNUNET_assert (NULL != keys);
gf = TALER_EXCHANGE_get_global_fee (keys, gf = TALER_EXCHANGE_get_global_fee (keys,
*merge_timestamp); *merge_timestamp);

View File

@ -178,7 +178,8 @@ merge_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -90,7 +90,8 @@ recoup_cb (void *cls,
if (ps->expected_response_code != hr->http_status) if (ps->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
hr->http_status); hr->http_status,
ps->expected_response_code);
return; return;
} }

View File

@ -89,7 +89,8 @@ recoup_refresh_cb (void *cls,
if (rrs->expected_response_code != hr->http_status) if (rrs->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
hr->http_status); hr->http_status,
rrs->expected_response_code);
return; return;
} }

View File

@ -75,7 +75,7 @@ struct TALER_TESTING_FreshCoinData
* applicable. * applicable.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof; struct TALER_AgeCommitmentProof *age_commitment_proof;
struct TALER_AgeCommitmentHash *h_age_commitment; struct TALER_AgeCommitmentHash h_age_commitment;
/** /**
* The blinding key (needed for recoup operations). * The blinding key (needed for recoup operations).
@ -371,12 +371,8 @@ reveal_cb (void *cls,
struct RefreshRevealState *rrs = cls; struct RefreshRevealState *rrs = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr; const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr;
const struct TALER_TESTING_Command *melt_cmd; const struct TALER_TESTING_Command *melt_cmd;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (rrs->is);
rrs->rrh = NULL; rrs->rrh = NULL;
if (NULL == exchange)
return;
if (rrs->expected_response_code != hr->http_status) if (rrs->expected_response_code != hr->http_status)
{ {
if (0 != rrs->do_retry) if (0 != rrs->do_retry)
@ -406,7 +402,8 @@ reveal_cb (void *cls,
} }
} }
TALER_TESTING_unexpected_status (rrs->is, TALER_TESTING_unexpected_status (rrs->is,
hr->http_status); hr->http_status,
rrs->expected_response_code);
return; return;
} }
melt_cmd = TALER_TESTING_interpreter_lookup_command (rrs->is, melt_cmd = TALER_TESTING_interpreter_lookup_command (rrs->is,
@ -443,8 +440,13 @@ reveal_cb (void *cls,
return; return;
} }
fc->coin_priv = coin->coin_priv; fc->coin_priv = coin->coin_priv;
fc->age_commitment_proof = coin->age_commitment_proof;
fc->h_age_commitment = coin->h_age_commitment; if (NULL != coin->age_commitment_proof)
{
fc->age_commitment_proof =
TALER_age_commitment_proof_duplicate (coin->age_commitment_proof);
fc->h_age_commitment = coin->h_age_commitment;
}
TALER_denom_sig_deep_copy (&fc->sig, TALER_denom_sig_deep_copy (&fc->sig,
&coin->sig); &coin->sig);
@ -562,7 +564,11 @@ refresh_reveal_cleanup (void *cls,
} }
for (unsigned int j = 0; j < rrs->num_fresh_coins; j++) for (unsigned int j = 0; j < rrs->num_fresh_coins; j++)
{
TALER_denom_sig_free (&rrs->fresh_coins[j].sig); TALER_denom_sig_free (&rrs->fresh_coins[j].sig);
TALER_age_commitment_proof_free (rrs->fresh_coins[j].age_commitment_proof);
GNUNET_free (rrs->fresh_coins[j].age_commitment_proof);
}
GNUNET_free (rrs->fresh_coins); GNUNET_free (rrs->fresh_coins);
GNUNET_free (rrs->psa); GNUNET_free (rrs->psa);
@ -650,7 +656,8 @@ link_cb (void *cls,
} }
} }
TALER_TESTING_unexpected_status (rls->is, TALER_TESTING_unexpected_status (rls->is,
hr->http_status); hr->http_status,
rls->expected_response_code);
return; return;
} }
reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
@ -941,8 +948,10 @@ melt_cb (void *cls,
return; return;
} }
} }
TALER_TESTING_unexpected_status (rms->is, TALER_TESTING_unexpected_status_with_body (rms->is,
hr->http_status); hr->http_status,
rms->expected_response_code,
hr->reply);
return; return;
} }
if (MHD_HTTP_OK == hr->http_status) if (MHD_HTTP_OK == hr->http_status)
@ -1006,12 +1015,8 @@ melt_run (void *cls,
NULL NULL
}; };
const char **melt_fresh_amounts; const char **melt_fresh_amounts;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
rms->cmd = cmd; rms->cmd = cmd;
if (NULL == exchange)
return;
if (NULL == (melt_fresh_amounts = rms->melt_fresh_amounts)) if (NULL == (melt_fresh_amounts = rms->melt_fresh_amounts))
melt_fresh_amounts = default_melt_fresh_amounts; melt_fresh_amounts = default_melt_fresh_amounts;
rms->is = is; rms->is = is;
@ -1028,12 +1033,12 @@ melt_run (void *cls,
{ {
struct TALER_Amount melt_amount; struct TALER_Amount melt_amount;
struct TALER_Amount fresh_amount; struct TALER_Amount fresh_amount;
const struct TALER_AgeCommitmentProof *age_commitment_proof; const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL;
const struct TALER_AgeCommitmentHash *h_age_commitment; const struct TALER_AgeCommitmentHash *h_age_commitment = NULL;
const struct TALER_DenominationSignature *melt_sig; const struct TALER_DenominationSignature *melt_sig;
const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
const struct TALER_TESTING_Command *coin_command; const struct TALER_TESTING_Command *coin_command;
bool age_restricted; bool age_restricted_denom;
if (NULL == (coin_command if (NULL == (coin_command
= TALER_TESTING_interpreter_lookup_command ( = TALER_TESTING_interpreter_lookup_command (
@ -1098,7 +1103,10 @@ melt_run (void *cls,
/* Melt amount starts with the melt fee of the old coin; we'll add the /* Melt amount starts with the melt fee of the old coin; we'll add the
values and withdraw fees of the fresh coins next */ values and withdraw fees of the fresh coins next */
melt_amount = melt_denom_pub->fees.refresh; melt_amount = melt_denom_pub->fees.refresh;
age_restricted = melt_denom_pub->key.age_mask.bits != 0; age_restricted_denom = melt_denom_pub->key.age_mask.bits != 0;
GNUNET_assert (age_restricted_denom == (NULL != age_commitment_proof));
GNUNET_assert ((NULL == age_commitment_proof) ||
(0 < age_commitment_proof->commitment.num));
for (unsigned int i = 0; i<num_fresh_coins; i++) for (unsigned int i = 0; i<num_fresh_coins; i++)
{ {
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk; const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
@ -1115,9 +1123,9 @@ melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is); TALER_TESTING_interpreter_fail (rms->is);
return; return;
} }
fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (exchange), fresh_pk = TALER_TESTING_find_pk (TALER_TESTING_get_keys (rms->is),
&fresh_amount, &fresh_amount,
age_restricted); age_restricted_denom);
if (NULL == fresh_pk) if (NULL == fresh_pk)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1143,13 +1151,20 @@ melt_run (void *cls,
rms->refresh_data.melt_amount = melt_amount; rms->refresh_data.melt_amount = melt_amount;
rms->refresh_data.melt_sig = *melt_sig; rms->refresh_data.melt_sig = *melt_sig;
rms->refresh_data.melt_pk = *melt_denom_pub; rms->refresh_data.melt_pk = *melt_denom_pub;
rms->refresh_data.melt_age_commitment_proof = age_commitment_proof;
rms->refresh_data.melt_h_age_commitment = h_age_commitment; if (NULL != age_commitment_proof)
{
GNUNET_assert (NULL != h_age_commitment);
rms->refresh_data.melt_age_commitment_proof = age_commitment_proof;
rms->refresh_data.melt_h_age_commitment = h_age_commitment;
}
rms->refresh_data.fresh_pks = rms->fresh_pks; rms->refresh_data.fresh_pks = rms->fresh_pks;
rms->refresh_data.fresh_pks_len = num_fresh_coins; rms->refresh_data.fresh_pks_len = num_fresh_coins;
GNUNET_assert (age_restricted == GNUNET_assert (age_restricted_denom ==
(NULL != age_commitment_proof)); (NULL != age_commitment_proof));
GNUNET_assert ((NULL == age_commitment_proof) ||
(0 < age_commitment_proof->commitment.num));
rms->rmh = TALER_EXCHANGE_melt ( rms->rmh = TALER_EXCHANGE_melt (
TALER_TESTING_interpreter_get_context (is), TALER_TESTING_interpreter_get_context (is),
@ -1202,6 +1217,7 @@ melt_cleanup (void *cls,
TALER_denom_pub_free (&rms->fresh_pks[i].key); TALER_denom_pub_free (&rms->fresh_pks[i].key);
GNUNET_free (rms->fresh_pks); GNUNET_free (rms->fresh_pks);
} }
GNUNET_free (rms->mbds); GNUNET_free (rms->mbds);
GNUNET_free (rms->melt_fresh_amounts); GNUNET_free (rms->melt_fresh_amounts);
GNUNET_free (rms); GNUNET_free (rms);
@ -1413,7 +1429,7 @@ refresh_reveal_traits (void *cls,
rrs->fresh_coins[index].age_commitment_proof), rrs->fresh_coins[index].age_commitment_proof),
TALER_TESTING_make_trait_h_age_commitment ( TALER_TESTING_make_trait_h_age_commitment (
index, index,
rrs->fresh_coins[index].h_age_commitment), &rrs->fresh_coins[index].h_age_commitment),
TALER_TESTING_make_trait_denom_pub ( TALER_TESTING_make_trait_denom_pub (
index, index,
rrs->fresh_coins[index].pk), rrs->fresh_coins[index].pk),
@ -1431,6 +1447,7 @@ refresh_reveal_traits (void *cls,
&rrs->psa[index]), &rrs->psa[index]),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
return TALER_TESTING_get_trait (traits, return TALER_TESTING_get_trait (traits,
ret, ret,
trait, trait,

View File

@ -83,7 +83,8 @@ refund_cb (void *cls,
if (rs->expected_response_code != hr->http_status) if (rs->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (rs->is, TALER_TESTING_unexpected_status (rs->is,
hr->http_status); hr->http_status,
rs->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (rs->is); TALER_TESTING_interpreter_next (rs->is);

View File

@ -230,19 +230,15 @@ reserve_history_cb (void *cls,
struct HistoryState *ss = cls; struct HistoryState *ss = cls;
struct TALER_TESTING_Interpreter *is = ss->is; struct TALER_TESTING_Interpreter *is = ss->is;
struct TALER_Amount eb; struct TALER_Amount eb;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
ss->rsh = NULL; ss->rsh = NULL;
if (NULL == exchange)
return;
if (MHD_HTTP_OK == rs->hr.http_status) if (MHD_HTTP_OK == rs->hr.http_status)
{ {
const struct TALER_EXCHANGE_Keys *keys; struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_GlobalFee *gf; const struct TALER_EXCHANGE_GlobalFee *gf;
ss->reserve_history.type = TALER_EXCHANGE_RTT_HISTORY; ss->reserve_history.type = TALER_EXCHANGE_RTT_HISTORY;
keys = TALER_EXCHANGE_get_keys (exchange); keys = TALER_TESTING_get_keys (is);
GNUNET_assert (NULL != keys); GNUNET_assert (NULL != keys);
gf = TALER_EXCHANGE_get_global_fee (keys, gf = TALER_EXCHANGE_get_global_fee (keys,
rs->ts); rs->ts);
@ -343,11 +339,7 @@ history_run (void *cls,
{ {
struct HistoryState *ss = cls; struct HistoryState *ss = cls;
const struct TALER_TESTING_Command *create_reserve; const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ss->is = is; ss->is = is;
create_reserve create_reserve
= TALER_TESTING_interpreter_lookup_command (is, = TALER_TESTING_interpreter_lookup_command (is,

View File

@ -165,11 +165,7 @@ open_run (void *cls,
struct OpenState *ss = cls; struct OpenState *ss = cls;
const struct TALER_TESTING_Command *create_reserve; const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_PurseDeposit cp[GNUNET_NZL (ss->cpl)]; struct TALER_EXCHANGE_PurseDeposit cp[GNUNET_NZL (ss->cpl)];
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ss->is = is; ss->is = is;
create_reserve create_reserve
= TALER_TESTING_interpreter_lookup_command (is, = TALER_TESTING_interpreter_lookup_command (is,

View File

@ -154,7 +154,8 @@ purse_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status) if (ds->expected_response_code != dr->hr.http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status); dr->hr.http_status,
ds->expected_response_code);
return; return;
} }
switch (dr->hr.http_status) switch (dr->hr.http_status)
@ -184,12 +185,8 @@ purse_run (void *cls,
struct ReservePurseState *ds = cls; struct ReservePurseState *ds = cls;
const struct TALER_ReservePrivateKeyP *reserve_priv; const struct TALER_ReservePrivateKeyP *reserve_priv;
const struct TALER_TESTING_Command *ref; const struct TALER_TESTING_Command *ref;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd; (void) cmd;
if (NULL == exchange)
return;
ds->is = is; ds->is = is;
ref = TALER_TESTING_interpreter_lookup_command (ds->is, ref = TALER_TESTING_interpreter_lookup_command (ds->is,
ds->reserve_ref); ds->reserve_ref);

View File

@ -314,11 +314,7 @@ status_run (void *cls,
{ {
struct StatusState *ss = cls; struct StatusState *ss = cls;
const struct TALER_TESTING_Command *create_reserve; const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ss->is = is; ss->is = is;
create_reserve create_reserve
= TALER_TESTING_interpreter_lookup_command (is, = TALER_TESTING_interpreter_lookup_command (is,

View File

@ -79,7 +79,8 @@ success_cb (
if (rs->expected_response_code != hr->http_status) if (rs->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (rs->is, TALER_TESTING_unexpected_status (rs->is,
hr->http_status); hr->http_status,
rs->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (rs->is); TALER_TESTING_interpreter_next (rs->is);

View File

@ -79,7 +79,8 @@ success_cb (
if (rs->expected_response_code != hr->http_status) if (rs->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (rs->is, TALER_TESTING_unexpected_status (rs->is,
hr->http_status); hr->http_status,
rs->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (rs->is); TALER_TESTING_interpreter_next (rs->is);

View File

@ -110,6 +110,7 @@ run_fakebank_cleanup (void *cls,
} }
GNUNET_free (rfs->ba.wire_gateway_url); GNUNET_free (rfs->ba.wire_gateway_url);
GNUNET_free (rfs->bank_url); GNUNET_free (rfs->bank_url);
GNUNET_free (rfs->currency);
GNUNET_free (rfs); GNUNET_free (rfs);
} }
@ -194,7 +195,9 @@ TALER_TESTING_cmd_run_fakebank (
(unsigned int) fakebank_port, (unsigned int) fakebank_port,
exchange_xtalerbank_account); exchange_xtalerbank_account);
GNUNET_free (exchange_xtalerbank_account); GNUNET_free (exchange_xtalerbank_account);
GNUNET_free (exchange_payto_uri);
} }
GNUNET_free (exchange_payto_uri);
rfs->ba.method = TALER_BANK_AUTH_NONE; rfs->ba.method = TALER_BANK_AUTH_NONE;
{ {
struct TALER_TESTING_Command cmd = { struct TALER_TESTING_Command cmd = {

View File

@ -1,144 +0,0 @@
/*
This file is part of TALER
(C) 2018-2023 Taler Systems SA
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 testing/testing_api_cmd_serialize_keys.c
* @brief Lets tests use the keys serialization API.
* @author Marcello Stanisci
*/
#include "platform.h"
#include <jansson.h>
#include "taler_testing_lib.h"
/**
* Internal state for a serialize-keys CMD.
*/
struct SerializeKeysState
{
/**
* Serialized keys.
*/
json_t *keys;
/**
* Exchange URL. Needed because the exchange gets disconnected
* from, after keys serialization. This value is then needed by
* subsequent commands that have to reconnect to the exchange.
*/
char *exchange_url;
};
/**
* Run the command.
*
* @param cls closure.
* @param cmd the command to execute.
* @param is the interpreter state.
*/
static void
serialize_keys_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct SerializeKeysState *sks = cls;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
sks->keys = TALER_EXCHANGE_serialize_data (exchange);
if (NULL == sks->keys)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
}
sks->exchange_url
= GNUNET_strdup (
TALER_EXCHANGE_get_base_url (exchange));
TALER_TESTING_interpreter_next (is);
}
/**
* Cleanup the state of a "serialize keys" CMD.
*
* @param cls closure.
* @param cmd the command which is being cleaned up.
*/
static void
serialize_keys_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct SerializeKeysState *sks = cls;
if (NULL != sks->keys)
json_decref (sks->keys);
GNUNET_free (sks->exchange_url);
GNUNET_free (sks);
}
/**
* Offer serialized keys as trait.
*
* @param cls closure.
* @param[out] ret result.
* @param trait name of the trait.
* @param index index number of the object to offer.
* @return #GNUNET_OK on success.
*/
static enum GNUNET_GenericReturnValue
serialize_keys_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
struct SerializeKeysState *sks = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_exchange_keys (sks->keys),
TALER_TESTING_make_trait_exchange_url (sks->exchange_url),
TALER_TESTING_trait_end ()
};
return TALER_TESTING_get_trait (traits,
ret,
trait,
index);
}
struct TALER_TESTING_Command
TALER_TESTING_cmd_serialize_keys (const char *label)
{
struct SerializeKeysState *sks;
sks = GNUNET_new (struct SerializeKeysState);
{
struct TALER_TESTING_Command cmd = {
.cls = sks,
.label = label,
.run = serialize_keys_run,
.cleanup = serialize_keys_cleanup,
.traits = serialize_keys_traits
};
return cmd;
}
}

View File

@ -98,7 +98,8 @@ set_officer_cb (void *cls,
if (MHD_HTTP_NO_CONTENT != hr->http_status) if (MHD_HTTP_NO_CONTENT != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
MHD_HTTP_NO_CONTENT);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -90,7 +90,8 @@ wire_add_cb (void *cls,
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -108,7 +108,8 @@ take_aml_decision_cb (
if (ds->expected_response != hr->http_status) if (ds->expected_response != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -133,7 +133,8 @@ track_transfer_cb (void *cls,
if (tts->expected_response_code != hr->http_status) if (tts->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
hr->http_status); hr->http_status,
tts->expected_response_code);
return; return;
} }
@ -309,12 +310,8 @@ track_transfer_run (void *cls,
struct TrackTransferState *tts = cls; struct TrackTransferState *tts = cls;
struct TALER_WireTransferIdentifierRawP wtid; struct TALER_WireTransferIdentifierRawP wtid;
const struct TALER_WireTransferIdentifierRawP *wtid_ptr; const struct TALER_WireTransferIdentifierRawP *wtid_ptr;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
tts->cmd = cmd; tts->cmd = cmd;
if (NULL == exchange)
return;
/* If no reference is given, we'll use a all-zeros /* If no reference is given, we'll use a all-zeros
* WTID */ * WTID */
memset (&wtid, memset (&wtid,

View File

@ -80,7 +80,8 @@ wire_add_cb (void *cls,
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -80,7 +80,9 @@ wire_del_cb (void *cls,
if (ds->expected_response_code != hr->http_status) if (ds->expected_response_code != hr->http_status)
{ {
TALER_TESTING_unexpected_status (ds->is, TALER_TESTING_unexpected_status (ds->is,
hr->http_status); hr->http_status,
ds->expected_response_code);
return; return;
} }
TALER_TESTING_interpreter_next (ds->is); TALER_TESTING_interpreter_next (ds->is);

View File

@ -144,10 +144,10 @@ struct WithdrawState
/** /**
* If age > 0, put here the corresponding age commitment with its proof and * If age > 0, put here the corresponding age commitment with its proof and
* its hash, respectivelly, NULL otherwise. * its hash, respectivelly.
*/ */
struct TALER_AgeCommitmentProof *age_commitment_proof; struct TALER_AgeCommitmentProof age_commitment_proof;
struct TALER_AgeCommitmentHash *h_age_commitment; struct TALER_AgeCommitmentHash h_age_commitment;
/** /**
* Reserve history entry that corresponds to this operation. * Reserve history entry that corresponds to this operation.
@ -284,7 +284,8 @@ reserve_withdraw_cb (void *cls,
} }
} }
TALER_TESTING_unexpected_status (is, TALER_TESTING_unexpected_status (is,
wr->hr.http_status); wr->hr.http_status,
ws->expected_response_code);
return; return;
} }
switch (wr->hr.http_status) switch (wr->hr.http_status)
@ -347,7 +348,6 @@ withdraw_run (void *cls,
const struct TALER_ReservePrivateKeyP *rp; const struct TALER_ReservePrivateKeyP *rp;
const struct TALER_TESTING_Command *create_reserve; const struct TALER_TESTING_Command *create_reserve;
const struct TALER_EXCHANGE_DenomPublicKey *dpk; const struct TALER_EXCHANGE_DenomPublicKey *dpk;
struct TALER_EXCHANGE_Handle *exchange;
ws->cmd = cmd; ws->cmd = cmd;
ws->is = is; ws->is = is;
@ -369,12 +369,9 @@ withdraw_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
exchange = TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
if (NULL == ws->exchange_url) if (NULL == ws->exchange_url)
ws->exchange_url ws->exchange_url
= GNUNET_strdup (TALER_EXCHANGE_get_base_url (exchange)); = GNUNET_strdup (TALER_TESTING_get_exchange_url (is));
ws->reserve_priv = *rp; ws->reserve_priv = *rp;
GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv,
&ws->reserve_pub.eddsa_pub); &ws->reserve_pub.eddsa_pub);
@ -441,7 +438,7 @@ withdraw_run (void *cls,
struct TALER_EXCHANGE_WithdrawCoinInput wci = { struct TALER_EXCHANGE_WithdrawCoinInput wci = {
.pk = ws->pk, .pk = ws->pk,
.ps = &ws->ps, .ps = &ws->ps,
.ach = ws->h_age_commitment .ach = 0 < ws->age ? &ws->h_age_commitment : NULL
}; };
ws->wsh = TALER_EXCHANGE_withdraw ( ws->wsh = TALER_EXCHANGE_withdraw (
TALER_TESTING_interpreter_get_context (is), TALER_TESTING_interpreter_get_context (is),
@ -492,16 +489,8 @@ withdraw_cleanup (void *cls,
TALER_EXCHANGE_destroy_denomination_key (ws->pk); TALER_EXCHANGE_destroy_denomination_key (ws->pk);
ws->pk = NULL; ws->pk = NULL;
} }
if (NULL != ws->age_commitment_proof) if (ws->age > 0)
{ TALER_age_commitment_proof_free (&ws->age_commitment_proof);
TALER_age_commitment_proof_free (ws->age_commitment_proof);
ws->age_commitment_proof = NULL;
}
if (NULL != ws->h_age_commitment)
{
GNUNET_free (ws->h_age_commitment);
ws->h_age_commitment = NULL;
}
GNUNET_free (ws->exchange_url); GNUNET_free (ws->exchange_url);
GNUNET_free (ws->reserve_payto_uri); GNUNET_free (ws->reserve_payto_uri);
GNUNET_free (ws); GNUNET_free (ws);
@ -548,9 +537,13 @@ withdraw_traits (void *cls,
TALER_TESTING_make_trait_payto_uri (ws->reserve_payto_uri), TALER_TESTING_make_trait_payto_uri (ws->reserve_payto_uri),
TALER_TESTING_make_trait_exchange_url (ws->exchange_url), TALER_TESTING_make_trait_exchange_url (ws->exchange_url),
TALER_TESTING_make_trait_age_commitment_proof (0, TALER_TESTING_make_trait_age_commitment_proof (0,
ws->age_commitment_proof), 0 < ws->age
? &ws->age_commitment_proof
: NULL),
TALER_TESTING_make_trait_h_age_commitment (0, TALER_TESTING_make_trait_h_age_commitment (0,
ws->h_age_commitment), 0 < ws->age
? &ws->h_age_commitment
: NULL),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };
@ -576,13 +569,9 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
ws->age = age; ws->age = age;
if (0 < age) if (0 < age)
{ {
struct TALER_AgeCommitmentProof *acp;
struct TALER_AgeCommitmentHash *hac;
struct GNUNET_HashCode seed; struct GNUNET_HashCode seed;
struct TALER_AgeMask mask; struct TALER_AgeMask mask;
acp = GNUNET_new (struct TALER_AgeCommitmentProof);
hac = GNUNET_new (struct TALER_AgeCommitmentHash);
mask = TALER_extensions_get_age_restriction_mask (); mask = TALER_extensions_get_age_restriction_mask ();
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&seed, &seed,
@ -593,7 +582,7 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
&mask, &mask,
age, age,
&seed, &seed,
acp)) &ws->age_commitment_proof))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to generate age commitment for age %d at %s\n", "Failed to generate age commitment for age %d at %s\n",
@ -601,10 +590,8 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
label); label);
GNUNET_assert (0); GNUNET_assert (0);
} }
TALER_age_commitment_hash (&acp->commitment, TALER_age_commitment_hash (&ws->age_commitment_proof.commitment,
hac); &ws->h_age_commitment);
ws->age_commitment_proof = acp;
ws->h_age_commitment = hac;
} }
ws->reserve_reference = reserve_reference; ws->reserve_reference = reserve_reference;

View File

@ -75,33 +75,6 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
} }
struct TALER_EXCHANGE_Handle *
TALER_TESTING_get_exchange (struct TALER_TESTING_Interpreter *is)
{
struct TALER_EXCHANGE_Handle *exchange;
const struct TALER_TESTING_Command *exchange_cmd;
exchange_cmd
= TALER_TESTING_interpreter_get_command (is,
"exchange");
if (NULL == exchange_cmd)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_exchange (exchange_cmd,
&exchange))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
return exchange;
}
const char * const char *
TALER_TESTING_get_exchange_url (struct TALER_TESTING_Interpreter *is) TALER_TESTING_get_exchange_url (struct TALER_TESTING_Interpreter *is)
{ {

View File

@ -464,6 +464,9 @@ void
TALER_age_proof_free ( TALER_age_proof_free (
struct TALER_AgeProof *proof) struct TALER_AgeProof *proof)
{ {
if (NULL == proof)
return;
if (NULL != proof->keys) if (NULL != proof->keys)
{ {
GNUNET_CRYPTO_zero_keys ( GNUNET_CRYPTO_zero_keys (
@ -479,26 +482,71 @@ TALER_age_proof_free (
void void
TALER_age_commitment_proof_free ( TALER_age_commitment_proof_free (
struct TALER_AgeCommitmentProof *cp) struct TALER_AgeCommitmentProof *acp)
{ {
if (NULL != cp->proof.keys) if (NULL == acp)
return;
if (NULL != acp->proof.keys)
{ {
GNUNET_CRYPTO_zero_keys ( GNUNET_CRYPTO_zero_keys (
cp->proof.keys, acp->proof.keys,
sizeof(*cp->proof.keys) * cp->proof.num); sizeof(*acp->proof.keys) * acp->proof.num);
GNUNET_free (cp->proof.keys); GNUNET_free (acp->proof.keys);
cp->proof.keys = NULL; acp->proof.keys = NULL;
} }
if (NULL != cp->commitment.keys) if (NULL != acp->commitment.keys)
{ {
GNUNET_free (cp->commitment.keys); GNUNET_free (acp->commitment.keys);
cp->commitment.keys = NULL; acp->commitment.keys = NULL;
} }
} }
struct TALER_AgeCommitmentProof *
TALER_age_commitment_proof_duplicate (
const struct TALER_AgeCommitmentProof *acp)
{
struct TALER_AgeCommitmentProof *nacp;
GNUNET_assert (NULL != acp);
GNUNET_assert (__builtin_popcount (acp->commitment.mask.bits) - 1 ==
(int) acp->commitment.num);
nacp = GNUNET_new (struct TALER_AgeCommitmentProof);
TALER_age_commitment_proof_deep_copy (acp,nacp);
return nacp;
}
void
TALER_age_commitment_proof_deep_copy (
const struct TALER_AgeCommitmentProof *acp,
struct TALER_AgeCommitmentProof *nacp)
{
GNUNET_assert (NULL != acp);
GNUNET_assert (__builtin_popcount (acp->commitment.mask.bits) - 1 ==
(int) acp->commitment.num);
*nacp = *acp;
nacp->commitment.keys =
GNUNET_new_array (acp->commitment.num,
struct TALER_AgeCommitmentPublicKeyP);
nacp->proof.keys =
GNUNET_new_array (acp->proof.num,
struct TALER_AgeCommitmentPrivateKeyP);
for (size_t i = 0; i < acp->commitment.num; i++)
nacp->commitment.keys[i] = acp->commitment.keys[i];
for (size_t i = 0; i < acp->proof.num; i++)
nacp->proof.keys[i] = acp->proof.keys[i];
}
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TALER_JSON_parse_age_groups (const json_t *root, TALER_JSON_parse_age_groups (const json_t *root,
struct TALER_AgeMask *mask) struct TALER_AgeMask *mask)
@ -571,19 +619,16 @@ TALER_parse_age_group_string (
} }
char * const char *
TALER_age_mask_to_string ( TALER_age_mask_to_string (
const struct TALER_AgeMask *mask) const struct TALER_AgeMask *mask)
{ {
static char buf[256] = {0};
uint32_t bits = mask->bits; uint32_t bits = mask->bits;
unsigned int n = 0; unsigned int n = 0;
char *buf = GNUNET_malloc (32 * 3); // max characters possible
char *pos = buf; char *pos = buf;
if (NULL == buf) memset (buf, 0, sizeof(buf));
{
return buf;
}
while (bits != 0) while (bits != 0)
{ {

View File

@ -461,4 +461,54 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
} }
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Structure we hash to compute the group key for
* a denomination group.
*/
struct DenominationGroupP
{
/**
* Value of coins in this denomination group.
*/
struct TALER_AmountNBO value;
/**
* Fee structure for all coins in the group.
*/
struct TALER_DenomFeeSetNBOP fees;
/**
* Age mask for the denomiation, in NBO.
*/
uint32_t age_mask GNUNET_PACKED;
/**
* Cipher used for the denomination, in NBO.
*/
uint32_t cipher GNUNET_PACKED;
};
GNUNET_NETWORK_STRUCT_END
void
TALER_denomination_group_get_key (
const struct TALER_DenominationGroup *dg,
struct GNUNET_HashCode *key)
{
struct DenominationGroupP dgp = {
.age_mask = htonl (dg->age_mask.bits),
.cipher = htonl (dg->cipher)
};
TALER_amount_hton (&dgp.value,
&dg->value);
TALER_denom_fee_set_hton (&dgp.fees,
&dg->fees);
GNUNET_CRYPTO_hash (&dgp,
sizeof (dgp),
key);
}
/* end of crypto.c */ /* end of crypto.c */