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
# 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
# numer of 16 directories.
# number of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# 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
\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
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

View File

@ -43,8 +43,8 @@
\end{figure}
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
pratice, we expect most owners of bank accounts crossing the KYB threshold to
are an {\bf individual} (not incorporated) or a {\bf business}.\footnote{In
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
individual operating a business without a separate legal entity.} This then
determines which types of attributes are collected in the KYB process

View File

@ -43,7 +43,7 @@
\end{figure}
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
by a business.} This then determines which types of attributes are collected
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-helper-auditor-render.py \
auditor.conf \
setup.sh \
test-sync-in.conf \
test-sync-out.conf \
generate-auditor-basedb.sh \

View File

@ -1,14 +1,27 @@
[exchange-offline]
MASTER_PRIV_FILE = auditor-basedb.mpriv
[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/
[instance-default]
KEYFILE = ${TALER_DATA_HOME}/merchant/default.priv
NAME = Merchant Inc.
[taler]
CURRENCY = TESTKUDOS
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]
PAYTO_URI = payto://iban/SANDBOXX/DE989651?receiver-name=Exchange+Company
enable_debit = yes
enable_credit = yes
ENABLE_DEBIT = YES
ENABLE_CREDIT = YES
[exchange-accountcredentials-1]
WIRE_GATEWAY_URL = http://localhost:8082/facades/test-facade/taler-wire-gateway/
@ -16,24 +29,38 @@ WIRE_GATEWAY_AUTH_METHOD = basic
USERNAME = exchange
PASSWORD = x
[merchant-account-merchant]
PAYTO_URI = payto://x-taler-bank/localhost/42
HONOR_default = YES
ACTIVE_default = YES
[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
[merchantdb-postgres]
CONFIG = postgres:///auditor-basedb
[merchant-exchange-default]
MASTER_KEY = RKNMPRGXCX35H11WEYXDXYHPR7NX2QK9BG15MT0QEF75PC5KR470
MASTER_KEY = M4FGP18EQFXFGGFQ1AWXHACN2JX0SMVK9CNF6459Z1WG18JSN0BG
EXCHANGE_BASE_URL = http://localhost:8081/
CURRENCY = TESTKUDOS
[payments-generator]
currency = TESTKUDOS
instance = default
bank = http://localhost:8082/
merchant = http://localhost:9966/
exchange_admin = http://localhost:18080/
exchange-admin = http://localhost:18080/
exchange = http://localhost:8081/
[bank]
HTTP_PORT = 8082
[libeufin-nexus]
DB_CONNECTION="jdbc:postgresql://localhost/auditor-basedb?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432"
[libeufin-sandbox]
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]
value = TESTKUDOS:0.01
@ -130,61 +157,3 @@ fee_refresh = TESTKUDOS:0.03
fee_refund = TESTKUDOS:0.01
CIPHER = RSA
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
# Script to generate the basic database for auditor
# testing from a 'correct' interaction between exchange,
# wallet and merchant.
# This file is in the public domain.
#
# Creates $BASEDB.sql, $BASEDB.fees,
# $BASEDB.{mpub,mpriv}.
# Default $BASEDB is "auditor-basedb", override via $1.
# Script to generate the basic database for auditor testing from a 'correct'
# interaction between exchange, wallet and merchant.
#
# Currently must be run online as it interacts with
# bank.test.taler.net; also requires the wallet CLI
# to be installed and in the path. Furthermore, the
# user running this script must be Postgres superuser
# and be allowed to create/drop databases.
# Creates "$1.sql".
#
# Requires the wallet CLI to be installed and in the path. Furthermore, the
# user running this script must be Postgres superuser and be allowed to
# create/drop databases.
#
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?
BASEDB=${1:-"auditor-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}`
BASEDB="$1"
export WALLET_DB=${BASEDB:-"wallet"}.wdb
. setup.sh
# delete existing wallet database
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"
echo -n "Testing for curl ..."
curl --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
CONF="generate-auditor-basedb.conf"
# reset database
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`
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
MASTER_PRIV_FILE=$1.mpriv
MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE`
taler-config -f -c ${CONF} -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE}
rm -f "${MASTER_PRIV_FILE}"
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`
EXCHANGE_URL=$(taler-config -c "$CONF" -s EXCHANGE -o BASE_URL)
MERCHANT_PORT=$(taler-config -c "$CONF" -s MERCHANT -o PORT)
MERCHANT_URL="http://localhost:${MERCHANT_PORT}/"
BANK_PORT=$(taler-config -c "$CONF" -s BANK -o HTTP_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"
# run wallet CLI
echo "Running wallet"
# delete existing wallet database
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 '
{
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 EXCHANGE_URL "$EXCHANGE_URL" \
--arg BANK_URL "$BANK_URL/demobanks/default/access-api/"
)" &> ${MY_TMP_DIR}/taler-wallet-cli.log
echo "Shutting down services"
exit_cleanup
)" &> taler-wallet-cli.log
echo " DONE"
# Dump database
echo "Dumping database ${BASEDB}(-libeufin).sql"
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
mkdir -p "$(dirname "$BASEDB")"
echo $MASTER_PUB > ${BASEDB}.mpub
echo "Dumping database ${BASEDB}.sql"
pg_dump -O "auditor-basedb" | sed -e '/AS integer/d' > "${BASEDB}.sql"
# clean up
echo "Final clean up"
dropdb $TARGET_DB
echo -n "Final clean up ..."
kill -TERM "$SETUP_PID"
wait
unset SETUP_PID
dropdb "auditor-basedb"
echo " DONE"
echo "====================================="
echo " Finished generation of $BASEDB"
echo "Finished generation of ${BASEDB}.sql"
echo "====================================="
exit 0

View File

@ -8,405 +8,50 @@
set -eu
# set -x
# Cleanup to run whenever we exit
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
}
. setup.sh
function get_payto_uri() {
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"
echo -n "Testing for curl ..."
curl --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
# reset database
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`
CONF="generate-auditor-basedb.conf"
# 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
MASTER_PRIV_FILE=$1.mpriv
MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE`
taler-config -f -c $CONF -s exchange-offline -o MASTER_PRIV_FILE -V ${MASTER_PRIV_FILE}
mkdir -p $MASTER_PRIV_DIR
rm -f "${MASTER_PRIV_FILE}"
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`
EXCHANGE_URL=$(taler-config -c "$CONF" -s EXCHANGE -o BASE_URL)
MERCHANT_PORT=$(taler-config -c "$CONF" -s MERCHANT -o PORT)
MERCHANT_URL="http://localhost:${MERCHANT_PORT}/"
BANK_PORT=$(taler-config -c "$CONF" -s BANK -o HTTP_PORT)
BANK_URL="http://localhost:1${BANK_PORT}"
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
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"
# run wallet CLI
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 '
{
amount: "TESTKUDOS:8",
@ -414,57 +59,85 @@ taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api --expect-success 'with
exchangeBaseUrl: $EXCHANGE_URL,
}' \
--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 $coins
echo "$COINS"
# 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
export rd=$(echo "$coins" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .denom_pub_hash')
echo "Revoking denomination ${rd} (to affect coin ${rc})"
export rd=$(echo "$COINS" | jq -r '[.coins[] | select((.denom_value == "TESTKUDOS:2"))][0] | .denom_pub_hash')
echo -n "Revoking denomination ${rd} (to affect coin ${rc}) ..."
# 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
taler-exchange-offline -c $CONF \
revoke-denomination "${rd}" upload &> ${MY_TMP_DIR}/taler-exchange-offline-revoke.log
taler-exchange-offline \
-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
# Re-sign replacement keys
taler-auditor-offline -c $CONF \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log
taler-auditor-offline \
-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
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
taler-wallet-cli --wallet-db=$WALLET_DB exchanges update \
-f $EXCHANGE_URL
taler-wallet-cli \
--wallet-db="$WALLET_DB" \
exchanges \
update \
-f "$EXCHANGE_URL"
# 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
taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'testPay' \
taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
api \
'testPay' \
"$(jq -n '
{
amount: "TESTKUDOS:1",
merchantBaseUrl: $MERCHANT_URL,
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"
@ -477,9 +150,6 @@ echo "Will refresh coin ${rrc} of denomination ${zombie_denom}"
# Find all other coins, which will be suspended
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)
export TIMETRAVEL="--timetravel=604800000000"
@ -510,8 +180,15 @@ do
done
echo "Refreshing coin $rrc"
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB advanced force-refresh "$rrc"
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB run-until-done
taler-wallet-cli \
"$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
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
echo "Revoking ${fresh_denom} (to affect coin ${freshc})"
taler-exchange-offline -c $CONF \
revoke-denomination "${fresh_denom}" upload &> ${MY_TMP_DIR}/taler-exchange-offline-revoke-2.log
taler-exchange-offline \
-c "$CONF" \
revoke-denomination \
"${fresh_denom}" \
upload &> taler-exchange-offline-revoke-2.log
sleep 1 # Give exchange time to create replacmenent key
# Re-sign replacement keys
taler-auditor-offline -c $CONF \
download sign upload &> ${MY_TMP_DIR}/taler-auditor-offline.log
taler-auditor-offline \
-c "$CONF" \
download \
sign \
upload &> taler-auditor-offline.log
# 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
taler-wallet-cli $TIMETRAVEL --wallet-db=$WALLET_DB exchanges update \
-f $EXCHANGE_URL
taler-wallet-cli \
"$TIMETRAVEL"\
--wallet-db="$WALLET_DB" \
exchanges update \
-f "$EXCHANGE_URL"
# 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)"
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=$!
# Wait for merchant to be again available
for n in `seq 1 50`
do
@ -580,7 +277,10 @@ taler-wallet-cli $TIMETRAVEL --no-throttle --wallet-db=$WALLET_DB api 'testPay'
}' \
--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"
@ -588,26 +288,24 @@ echo "Shutting down services"
exit_cleanup
# Where do we write the result?
export BASEDB=${1:-"revoke-basedb"}
# Dump database
echo "Dumping database"
echo "Dumping PostgreSQL database: ${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
echo "Dumping database ${BASEDB}.sql"
pg_dump -O "auditor-basedb" | sed -e '/AS integer/d' > "${BASEDB}.sql"
rm ${TARGET_DB}-sandbox.sqlite3 ${TARGET_DB}-nexus.sqlite3 # libeufin DB
cd $ORIGIN
echo $MASTER_PUB > ${BASEDB}.mpub
echo "Final clean up"
dropdb $TARGET_DB
# clean up
echo -n "Final clean up ..."
kill -TERM "$SETUP_PID"
wait
unset SETUP_PID
dropdb "auditor-basedb"
echo " DONE"
echo "====================================="
echo " Finished generation of $BASEDB "
echo "Finished generation of ${BASEDB}.sql"
echo "====================================="
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
#
# 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
# terms of the GNU General Public License as published by the Free Software
@ -49,17 +49,7 @@ VALGRIND=""
# history request.
LIBEUFIN_SETTLE_TIME=1
# Exit, with status code "skip" (no 'real' failure)
function exit_skip() {
echo "SKIPPING test: $1"
exit 77
}
# Exit, with error message (hard failure)
function exit_fail() {
echo "FAILING test: $1"
exit 1
}
. setup.sh
# Stop libeufin sandbox and nexus (if running)
function stop_libeufin()
@ -2002,12 +1992,12 @@ function check_with_database()
{
BASEDB=$1
CONF=$1.conf
ORIGIN=`pwd`
MY_TMP_DIR=`dirname $1`
ORIGIN=$(pwd)
MY_TMP_DIR=$(dirname $1)
echo "Running test suite with database $BASEDB using configuration $CONF"
MASTER_PRIV_FILE=${BASEDB}.mpriv
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}"
@ -2037,7 +2027,7 @@ function check_with_database()
# ####### Setup globals ######
# Postgres database to use
export DB=auditor-basedb
export DB="auditor-basedb"
# test required commands exist
echo "Testing for jq"
@ -2059,12 +2049,12 @@ INITDB_BIN=$(command -v initdb) || true
if [[ ! -z "$INITDB_BIN" ]]; then
echo " FOUND (in path) at" $INITDB_BIN
else
HAVE_INITDB=`find /usr -name "initdb" | head -1 2> /dev/null | grep postgres` || exit_skip " MISSING"
echo " FOUND at" `dirname $HAVE_INITDB`
INITDB_BIN=`echo $HAVE_INITDB | grep bin/initdb | grep postgres | sort -n | tail -n1`
HAVE_INITDB=$(find /usr -name "initdb" | head -1 2> /dev/null | grep postgres) || exit_skip " MISSING"
echo " FOUND at" $(dirname $HAVE_INITDB)
INITDB_BIN=$(echo $HAVE_INITDB | grep bin/initdb | grep postgres | sort -n | tail -n1)
fi
POSTGRES_PATH=`dirname $INITDB_BIN`
MYDIR=`mktemp -d /tmp/taler-auditor-basedbXXXXXX`
POSTGRES_PATH=$(dirname $INITDB_BIN)
MYDIR=$(mktemp -d /tmp/taler-auditor-basedbXXXXXX)
echo "Using $MYDIR for logging and temporary data"
TMPDIR="$MYDIR/postgres/"
mkdir -p $TMPDIR
@ -2089,9 +2079,9 @@ PGHOST="$TMPDIR/sockets"
export PGHOST
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
check_with_database $MYDIR/$DB
check_with_database "$MYDIR/$DB"
if test x$fail != x0
then
exit $fail

View File

@ -1,6 +1,6 @@
/*
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
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.
*/
static struct TALER_EXCHANGE_Handle *exchange;
static struct TALER_EXCHANGE_GetKeysHandle *exchange;
/**
@ -219,7 +219,7 @@ do_shutdown (void *cls)
}
if (NULL != exchange)
{
TALER_EXCHANGE_disconnect (exchange);
TALER_EXCHANGE_get_keys_cancel (exchange);
exchange = NULL;
}
if (NULL != nxt)
@ -646,22 +646,23 @@ do_upload (char *const *args)
*
* @param cls closure with the `char **` remaining args
* @param kr response data
* @param keys key data from the exchange
*/
static void
keys_cb (
void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr)
const struct TALER_EXCHANGE_KeysResponse *kr,
struct TALER_EXCHANGE_Keys *keys)
{
char *const *args = cls;
exchange = NULL;
switch (kr->hr.http_status)
{
case MHD_HTTP_OK:
if (! json_is_object (kr->hr.reply))
if (NULL == kr->hr.reply)
{
GNUNET_break (0);
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
test_shutdown ();
global_ret = EXIT_FAILURE;
return;
@ -673,8 +674,6 @@ keys_cb (
kr->hr.hint,
kr->hr.http_status,
(unsigned int) kr->hr.ec);
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
test_shutdown ();
global_ret = EXIT_FAILURE;
return;
@ -692,9 +691,8 @@ keys_cb (
json_decref (in);
in = NULL;
}
TALER_EXCHANGE_disconnect (exchange);
exchange = NULL;
next (args);
TALER_EXCHANGE_keys_decref (keys);
}
@ -721,11 +719,11 @@ do_download (char *const *args)
global_ret = EXIT_NOTCONFIGURED;
return;
}
exchange = TALER_EXCHANGE_connect (ctx,
exchange_url,
&keys_cb,
(void *) args,
TALER_EXCHANGE_OPTION_END);
exchange = TALER_EXCHANGE_get_keys (ctx,
exchange_url,
NULL,
&keys_cb,
(void *) args);
GNUNET_free (exchange_url);
}

View File

@ -20,8 +20,8 @@ KYC_AML_TRIGGER = true
# in the database. Should be a high-entropy nonce.
ATTRIBUTE_ENCRYPTION_KEY = SET_ME_PLEASE
# Set to NO to disable tipping.
ENABLE_TIPPING = YES
# Set to NO to disable rewards.
ENABLE_REWARDS = YES
# How long do we allow /keys to be cached at most? The actual
# 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;
/**
* 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
@ -1943,15 +1943,15 @@ exchange_serve_process_config (void)
"Amount in section `exchange' under `AML_THRESHOLD' uses the wrong currency!\n");
return GNUNET_SYSERR;
}
TEH_enable_tipping
TEH_enable_rewards
= GNUNET_CONFIGURATION_get_value_yesno (
TEH_cfg,
"exchange",
"ENABLE_TIPPING");
if (GNUNET_SYSERR == TEH_enable_tipping)
"ENABLE_REWARDS");
if (GNUNET_SYSERR == TEH_enable_rewards)
{
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;
}
if (GNUNET_OK !=

View File

@ -65,9 +65,9 @@ extern int TEH_check_invariants_flag;
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.

View File

@ -106,7 +106,7 @@ free_age_withdraw_context_resources (struct AgeWithdrawContext *awc)
* @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_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
* @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 ksh The handle to the current state of (denomination) keys in the exchange
* @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
* @return true on success (denomination valid), false otherwise
*/
@ -402,10 +402,10 @@ denomination_is_valid (
*
* @param connection The HTTP connection to the client
* @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[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.
* @return GNUNET_OK if the denominations are valid and support age-restriction
* GNUNET_SYSERR otherwise
@ -511,8 +511,7 @@ static enum GNUNET_GenericReturnValue
verify_reserve_signature (
struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
enum MHD_Result *mhd_ret
)
enum MHD_Result *mhd_ret)
{
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
@ -824,10 +823,7 @@ age_withdraw_transaction (void *cls,
* 2.) age withdraw was successful.
*
* @param connection HTTP-connection to the client
* @param h_commitment Original commitment
* @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 awc The context for the current age withdraw request
* @param[out] result On error, a HTTP-response will be queued and result set accordingly
* @return GNUNET_OK on success, GNUNET_SYSERR otherwise
*/

View File

@ -81,8 +81,6 @@ struct AgeRevealContext
* memory for those.
*
* @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[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
@ -223,7 +221,7 @@ find_original_commitment (
return GNUNET_SYSERR;
}
}
/* after unsuccessfull retries*/
/* after unsuccessful retries*/
*result = TALER_MHD_reply_with_ec (connection,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"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
*
* @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 denom_pub_h The hash of the denomination for the planchet
* @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
* @return GNUNET_OK on success, GNUNET_SYSERR otherwise, with an error message
* 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->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
"do_insert_kyc_attributes");
/* FIXME-Christian: shouldn't we return in the error case? */
/* Continued below to return the response */
}
/* Finally, return result to main handler */
kat->cb (kat->cb_cls,

View File

@ -1,6 +1,6 @@
/*
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
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.
*/
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};
enum GNUNET_GenericReturnValue ret;
@ -1701,8 +1701,10 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
TALER_MHD_get_date_string (m.abs_time,
dat);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setting /keys 'Expires' header to '%s'\n",
dat);
"Setting /keys 'Expires' header to '%s' (rekey frequency is %s)\n",
dat,
GNUNET_TIME_relative2s (ksh->rekey_frequency,
false));
GNUNET_break (MHD_YES ==
MHD_add_response_header (response,
MHD_HTTP_HEADER_EXPIRES,
@ -1857,8 +1859,11 @@ create_krd (struct TEH_KeyStateHandle *ksh,
TEH_currency),
GNUNET_JSON_pack_string ("asset_type",
asset_type),
// FIXME: legacy, remove soon!
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",
&TEH_master_public_key),
GNUNET_JSON_pack_time_rel ("reserve_closing_delay",
@ -2105,8 +2110,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{
struct TEH_DenominationKey *dk;
struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
/* groupData is the value we store for each group meta-data */
struct groupData
/* GroupData is the value we store for each group meta-data */
struct GroupData
{
/**
* 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";
struct groupData *group;
struct GroupData *group;
json_t *list;
json_t *entry;
struct GNUNET_HashCode key;
@ -2221,25 +2226,19 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
.age_mask = dk->meta.age_mask,
};
memset (&meta.hash, 0, sizeof(meta.hash));
/* Search the group/JSON-blob for the key */
GNUNET_CRYPTO_hash (&meta, sizeof(meta), &key);
group =
(struct groupData *) GNUNET_CONTAINER_multihashmap_get (
denominations_by_group,
&key);
TALER_denomination_group_get_key (&meta,
&key);
group = GNUNET_CONTAINER_multihashmap_get (
denominations_by_group,
&key);
if (NULL == group)
{
/* There is no group for this meta-data yet, so we create a new group */
bool age_restricted = meta.age_mask.bits != 0;
char *cipher;
group = GNUNET_new (struct groupData);
memset (group, 0, sizeof(*group));
const char *cipher;
group = GNUNET_new (struct GroupData);
switch (meta.cipher)
{
case TALER_DENOMINATION_RSA:
@ -2253,9 +2252,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
}
group->json = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("cipher", cipher),
TALER_JSON_PACK_DENOM_FEES ("fee", &meta.fees),
TALER_JSON_pack_amount ("value", &meta.value));
GNUNET_JSON_pack_string ("cipher",
cipher),
TALER_JSON_PACK_DENOM_FEES ("fee",
&meta.fees),
TALER_JSON_pack_amount ("value",
&meta.value));
GNUNET_assert (NULL != group->json);
if (age_restricted)
@ -2294,17 +2296,16 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
{
case TALER_DENOMINATION_RSA:
key_spec =
GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
dk->denom_pub.details.
rsa_public_key);
GNUNET_JSON_pack_rsa_public_key (
"rsa_pub",
dk->denom_pub.details.rsa_public_key);
break;
case TALER_DENOMINATION_CS:
key_spec =
GNUNET_JSON_pack_data_varsize ("cs_pub",
&dk->denom_pub.details.
cs_public_key,
sizeof (dk->denom_pub.details.
cs_public_key));
GNUNET_JSON_pack_data_varsize (
"cs_pub",
&dk->denom_pub.details.cs_public_key,
sizeof (dk->denom_pub.details.cs_public_key));
break;
default:
GNUNET_assert (false);
@ -2347,7 +2348,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
{
struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
struct groupData *group = NULL;
struct GroupData *group = NULL;
iter =
GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
@ -2372,15 +2373,12 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
json_array_append_new (
grouped_denominations,
group->json));
/* Build the running XOR over all hash(_xor) */
GNUNET_CRYPTO_hash_xor (&group->hash_xor,
&grouped_hash_xor,
&grouped_hash_xor);
GNUNET_free (group);
}
GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
}
@ -2544,9 +2542,9 @@ build_key_state (struct HelperState *hs,
ksh->helpers = hs;
}
ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
GNUNET_YES);
true);
ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
GNUNET_NO /* MUST be NO! */);
false /* MUST be false! */);
ksh->auditors = json_array ();
GNUNET_assert (NULL != ksh->auditors);
/* 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->enabled = true;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"loaded new age restriction config with age groups: %s\n",
TALER_age_mask_to_string (&mask));
@ -112,7 +112,6 @@ static json_t *
age_restriction_manifest (
const struct TALER_Extension *ext)
{
char *mask_str;
json_t *conf;
GNUNET_assert (NULL != ext);
@ -124,12 +123,11 @@ age_restriction_manifest (
return json_null ();
}
mask_str = TALER_age_mask_to_string (&AR_config.mask);
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 (
GNUNET_JSON_pack_bool ("critical", ext->critical),

View File

@ -184,7 +184,7 @@ configure_extension (
{
struct LoadConfClosure *col = cls;
const char *name;
char *lib_name;
char lib_name[1024] = {0};
struct TALER_Extension *extension;
if (GNUNET_OK != col->error)
@ -199,17 +199,16 @@ configure_extension (
/* Load the extension library */
GNUNET_asprintf (&lib_name,
GNUNET_snprintf (lib_name,
sizeof(lib_name),
"libtaler_extension_%s",
name);
/* Lower-case extension name, config is case-insensitive */
for (unsigned int i = 0; i < strlen (lib_name); i++)
{
lib_name[i] = tolower (lib_name[i]);
}
extension = GNUNET_PLUGIN_load (
lib_name,
(void *) col->cfg);
extension = GNUNET_PLUGIN_load (lib_name,
(void *) col->cfg);
if (NULL == extension)
{
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.
@ -5947,33 +5947,54 @@ TALER_age_commitment_verify (
/**
* @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
TALER_age_commitment_free (
struct TALER_AgeCommitment *p);
struct TALER_AgeCommitment *ac);
/**
* @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
TALER_age_proof_free (
struct TALER_AgeProof *p);
struct TALER_AgeProof *ap);
/**
* @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
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
* 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);
/**
* 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

View File

@ -32,27 +32,6 @@
/* ********************* /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
@ -146,6 +125,7 @@ struct TALER_EXCHANGE_DenomPublicKey
* revoked by the exchange.
*/
bool revoked;
};
@ -260,6 +240,11 @@ struct TALER_EXCHANGE_Keys
*/
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.
*/
@ -280,6 +265,11 @@ struct TALER_EXCHANGE_Keys
*/
struct TALER_EXCHANGE_GlobalFee *global_fees;
/**
* Configuration data for extensions.
*/
json_t *extensions;
/**
* Supported Taler protocol version by the exchange.
* String in the format current:revision:age using the
@ -294,11 +284,18 @@ struct TALER_EXCHANGE_Keys
char *currency;
/**
* How long after a reserve went idle will the exchange close it?
* This is an approximate number, not cryptographically signed by
* the exchange (advisory-only, may change anytime).
* What is the base URL of the exchange that returned
* these keys?
*/
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
@ -307,16 +304,22 @@ struct TALER_EXCHANGE_Keys
struct TALER_Amount *wallet_balance_limit_without_kyc;
/**
* Length of the @e wallet_balance_limit_without_kyc
* array.
* How long after a reserve went idle will the exchange close it?
* 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.
*/
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
* denomination key in /keys.
@ -329,6 +332,12 @@ struct TALER_EXCHANGE_Keys
*/
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.
*/
@ -360,17 +369,15 @@ struct TALER_EXCHANGE_Keys
unsigned int denom_keys_size;
/**
* 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.
* Reference counter for this structure.
* Freed when it reaches 0.
*/
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
* 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 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
(*TALER_EXCHANGE_CertificationCallback) (
(*TALER_EXCHANGE_GetKeysCallback) (
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
* a particular exchange and keep the per-exchange information.
* @brief Handle for a GET /keys request.
*/
struct TALER_EXCHANGE_Handle;
struct TALER_EXCHANGE_GetKeysHandle;
/**
* Initialise a connection to the exchange. Will connect to the
* exchange and obtain information about the exchange's master public
* key and the exchange's auditor. The respective information will
* be passed to the @a cert_cb once available, and all future
* interactions with the exchange will be checked to be signed
* (where appropriate) by the respective master key.
* Fetch the main /keys resources from an exchange. Does an incremental
* fetch if @a last_keys is given. The obtained information will be passed to
* the @a cert_cb (possibly after first merging it with @a last_keys to
* produce a full picture; expired keys (for deposit) will be removed from @a
* last_keys if there are any).
*
* @param ctx the context
* @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,
* possibly called repeatedly if the information changes
* @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
*/
struct TALER_EXCHANGE_Handle *
TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_EXCHANGE_CertificationCallback cert_cb,
void *cert_cb_cls,
...);
struct TALER_EXCHANGE_GetKeysHandle *
TALER_EXCHANGE_get_keys (
struct GNUNET_CURL_Context *ctx,
const char *url,
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
* on disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more
* efficiently recover the state).
* Serialize the latest data from @a keys to be persisted
* (for example, to be used as @a last_keys later).
*
* @param exchange which exchange's key and wire data should be serialized
* @return NULL on error (i.e. no current data available); otherwise
* json object owned by the caller
* @param kd the key data to serialize
* @return NULL on error; otherwise JSON object owned by the caller
*/
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
*/
void
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
* @param j JSON keys data previously returned from #TALER_EXCHANGE_keys_to_json()
* @return NULL on error (i.e. invalid JSON); otherwise
* keys object with reference counter 1 owned by the caller
*/
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);
/**
* 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
* 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
*/
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_test_signing_key (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);
TALER_EXCHANGE_test_signing_key (
const struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ExchangePublicKeyP *pub);
/**
@ -736,7 +655,8 @@ TALER_EXCHANGE_get_global_fee (
* Create a copy of a denomination public key.
*
* @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 *
TALER_EXCHANGE_copy_denomination_key (
@ -745,9 +665,10 @@ TALER_EXCHANGE_copy_denomination_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.
* @deprecated
*/
void
TALER_EXCHANGE_destroy_denomination_key (
@ -2828,13 +2749,16 @@ TALER_EXCHANGE_batch_withdraw2_cancel (
*/
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
*/
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;
};
@ -2901,7 +2825,7 @@ typedef void
*
* @param curl_ctx The curl context
* @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 num_coins The number of elements in @e coin_inputs
* @param coin_inputs The input for the coins to withdraw
@ -2918,8 +2842,8 @@ TALER_EXCHANGE_age_withdraw (
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
size_t num_coins,
const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[
const static num_coins],
const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[const static
num_coins],
uint8_t max_age,
TALER_EXCHANGE_AgeWithdrawCallback res_cb,
void *res_cb_cls);
@ -3133,7 +3057,7 @@ struct TALER_EXCHANGE_RevealedCoinInfo
* Age commitment and its hash of the coin, might be NULL.
*/
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.
@ -3220,7 +3144,6 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
*
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param rms the fresh secret that defines 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
@ -3277,10 +3200,11 @@ struct TALER_EXCHANGE_LinkedCoinInfo
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;
struct TALER_AgeCommitmentHash *h_age_commitment;
bool has_age_commitment;
struct TALER_AgeCommitmentProof age_commitment_proof;
struct TALER_AgeCommitmentHash h_age_commitment;
/**
* 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 ("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.

View File

@ -57,18 +57,44 @@
*
* @param is interpreter to fail
* @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 { \
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, \
expected, \
TALER_TESTING_interpreter_get_current_label (is), \
__FILE__, \
__LINE__); \
TALER_TESTING_interpreter_fail (is); \
} 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
@ -85,7 +111,7 @@
__FILE__, \
__LINE__, \
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 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 load_private_key obtain private key from file indicated in @a cfg
* @return the command.
@ -631,6 +658,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange (
const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys,
bool load_private_key);
@ -1786,45 +1814,6 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_wait_service (const char *label,
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
* 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);
/**
* 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.
*
@ -2246,6 +2210,7 @@ TALER_TESTING_cmd_proof_kyc_oauth2 (
* KYC processes which also provides a @a birthdate in a response
*
* @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
*/
struct TALER_TESTING_Command
@ -2499,6 +2464,30 @@ TALER_TESTING_cmd_check_aml_decisions (
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 ********* */
@ -2657,13 +2646,13 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_row, const uint64_t) \
op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \
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_justification, const char) \
op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \
op (auditor_pub, const struct TALER_AuditorPublicKeyP) \
op (master_priv, const struct TALER_MasterPrivateKeyP) \
op (master_pub, const struct TALER_MasterPublicKeyP) \
op (aml_justification, const char) \
op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \
op (auditor_pub, const struct TALER_AuditorPublicKeyP) \
op (master_priv, const struct TALER_MasterPrivateKeyP) \
op (master_pub, const struct TALER_MasterPublicKeyP) \
op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \
op (purse_pub, const struct TALER_PurseContractPublicKeyP) \
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 (contract_terms, const json_t) \
op (wire_details, const json_t) \
op (exchange_keys, const json_t) \
op (exchange_url, const char) \
op (auditor_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 (claim_token, const struct TALER_ClaimTokenP) \
op (relative_time, const struct GNUNET_TIME_Relative) \
op (exchange, struct TALER_EXCHANGE_Handle) \
op (fakebank, struct TALER_FAKEBANK_Handle) \
op (keys, struct TALER_EXCHANGE_Keys) \
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)
/* ****************** 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

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"
*
* NOTE: This function uses a static buffer. It is not safe to call this
* function concurrently.
*
* @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.
*/
char *
const char *
TALER_age_mask_to_string (
const struct TALER_AgeMask *mask);

View File

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

View File

@ -95,7 +95,7 @@ struct TALER_AUDITOR_GetConfigHandle
* in the @a key_data.
*
* @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
* @return #TALER_EC_NONE on success
*/

View File

@ -382,7 +382,8 @@ reserve_age_withdraw_payment_required (
* HTTP /reserves/$RESERVE_PUB/age-withdraw request.
*
* @param cls the `struct TALER_EXCHANGE_AgeWithdrawHandle`
* @param aw2r response data
* @param response_code The HTTP response code
* @param response response data
*/
static void
handle_reserve_age_withdraw_finished (
@ -651,6 +652,7 @@ ERROR:
* Prepares the request URL for the age-withdraw request
*
* @param awh The handler
* @param exchange_url The base-URL to the exchange
*/
static
enum GNUNET_GenericReturnValue
@ -770,7 +772,7 @@ csr_withdraw_done (
*
* @param awh The handler to the age-withdraw
* @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
*/
static

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
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
terms of the GNU General Public License as published by the Free Software
@ -28,124 +28,6 @@
#include "taler_util.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
@ -156,9 +38,10 @@ struct TALER_EXCHANGE_Handle
* @param auditor_pub public key of the auditor
*/
typedef void
(*TEAH_AuditorCallback)(void *cls,
const char *auditor_url,
const struct TALER_AuditorPublicKeyP *auditor_pub);
(*TEAH_AuditorCallback)(
void *cls,
const char *auditor_url,
const struct TALER_AuditorPublicKeyP *auditor_pub);
/**
@ -171,50 +54,11 @@ typedef void
* @param ac_cls closure for @a ac
*/
void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys,
TEAH_AuditorCallback ac,
void *ac_cls);
TEAH_get_auditors_for_dc (
struct TALER_EXCHANGE_Keys *keys,
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 */
#endif

View File

@ -114,6 +114,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_TransferSecretP secret;
struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHashP c_hash;
struct TALER_AgeCommitmentHash *pah = NULL;
/* parse reply */
if (GNUNET_OK !=
@ -137,34 +138,35 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
&alg_values,
&bks);
lci->age_commitment_proof = NULL;
lci->h_age_commitment = NULL;
lci->has_age_commitment = false;
/* Derive the age commitment and calculate the hash */
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 ==
TALER_age_commitment_derive (
lh->age_commitment_proof,
&secret.key,
lci->age_commitment_proof));
&lci->age_commitment_proof));
TALER_age_commitment_hash (
&(lci->age_commitment_proof->commitment),
lci->h_age_commitment);
&lci->age_commitment_proof.commitment,
&lci->h_age_commitment);
lci->has_age_commitment = true;
pah = &lci->h_age_commitment;
}
if (GNUNET_OK !=
TALER_planchet_prepare (&rpub,
&alg_values,
&bks,
&lci->coin_priv,
lci->h_age_commitment,
&c_hash,
&pd))
TALER_planchet_prepare (
&rpub,
&alg_values,
&bks,
&lci->coin_priv,
pah,
&c_hash,
&pd))
{
GNUNET_break (0);
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_pub_free (&lcis[i].pub);
if (lcis[i].has_age_commitment)
TALER_age_commitment_proof_free (&lcis[i].age_commitment_proof);
}
}
return ret;
@ -513,6 +517,7 @@ TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh)
GNUNET_CURL_job_cancel (lh->job);
lh->job = NULL;
}
GNUNET_free (lh->url);
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,
&h_denom_pub);
TALER_wallet_melt_sign (&mh->md.melted_coin.melt_amount_with_fee,
&mh->md.melted_coin.fee_melt,
&mh->md.rc,
&h_denom_pub,
mh->md.melted_coin.h_age_commitment,
&mh->md.melted_coin.coin_priv,
&mh->coin_sig);
TALER_wallet_melt_sign (
&mh->md.melted_coin.melt_amount_with_fee,
&mh->md.melted_coin.fee_melt,
&mh->md.rc,
&h_denom_pub,
mh->md.melted_coin.h_age_commitment,
&mh->md.melted_coin.coin_priv,
&mh->coin_sig);
GNUNET_CRYPTO_eddsa_key_get_public (&mh->md.melted_coin.coin_priv.eddsa_priv,
&mh->coin_pub.eddsa_pub);
melt_obj = GNUNET_JSON_PACK (
@ -357,7 +358,7 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
GNUNET_JSON_pack_data_auto ("rc",
&mh->md.rc),
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",
mh->md.melted_coin.h_age_commitment)
: 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 *
TALER_EXCHANGE_melt (
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];
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);
}
@ -168,7 +173,8 @@ TALER_EXCHANGE_get_melt_data_ (
union TALER_DenominationBlindingKeyP *bks = &fcd->bks[i];
struct TALER_PlanchetDetail pd;
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,
j,
@ -182,22 +188,21 @@ TALER_EXCHANGE_get_melt_data_ (
&alg_values[j],
bks);
/* Handle age commitment, if present */
if (NULL != md->melted_coin.age_commitment_proof)
if (NULL != rd->melt_age_commitment_proof)
{
fcd->age_commitment_proof[i] = GNUNET_new (struct
TALER_AgeCommitmentProof);
ach = GNUNET_new (struct TALER_AgeCommitmentHash);
fcd->age_commitment_proofs[i] = GNUNET_new (struct
TALER_AgeCommitmentProof);
GNUNET_assert (GNUNET_OK ==
TALER_age_commitment_derive (
md->melted_coin.age_commitment_proof,
&trans_sec.key,
fcd->age_commitment_proof[i]));
fcd->age_commitment_proofs[i]));
TALER_age_commitment_hash (
&fcd->age_commitment_proof[i]->commitment,
ach);
&fcd->age_commitment_proofs[i]->commitment,
&ach);
pah = &ach;
}
if (TALER_DENOMINATION_CS == alg_values[j].cipher)
@ -208,7 +213,7 @@ TALER_EXCHANGE_get_melt_data_ (
&alg_values[j],
bks,
coin_priv,
ach,
pah,
&c_hash,
&pd))
{

View File

@ -101,10 +101,9 @@ struct FreshCoinData
/**
* 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
* indicate no age commitment/restriction on the particular coin.
* cut-and-choose dimension. NULL if age restriction is not applicable.
*/
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

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++)
{
struct TALER_EXCHANGE_RevealedCoinInfo *rci =
&rcis[i];
struct TALER_EXCHANGE_RevealedCoinInfo *rci = &rcis[i];
const struct FreshCoinData *fcd = &rrh->md.fcds[i];
const struct TALER_DenominationPublicKey *pk;
json_t *jsonai;
@ -140,25 +139,25 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
};
struct TALER_FreshCoin coin;
union TALER_DenominationBlindingKeyP bks;
const struct TALER_AgeCommitmentHash *pah = NULL;
rci->ps = fcd->ps[rrh->noreveal_index];
rci->bks = fcd->bks[rrh->noreveal_index];
rci->age_commitment_proof = fcd->age_commitment_proof[rrh->noreveal_index];
rci->h_age_commitment = NULL;
rci->age_commitment_proof = NULL;
pk = &fcd->fresh_pk;
jsonai = json_array_get (jsona, i);
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);
TALER_age_commitment_hash (
&rci->age_commitment_proof->commitment,
rci->h_age_commitment);
rci->age_commitment_proof =
fcd->age_commitment_proofs[rrh->noreveal_index];
TALER_age_commitment_hash (&rci->age_commitment_proof->commitment,
&rci->h_age_commitment);
pah = &rci->h_age_commitment;
}
if (GNUNET_OK !=
@ -180,18 +179,20 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
hence recomputing it here... */
GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv,
&coin_pub.eddsa_pub);
TALER_coin_pub_hash (&coin_pub,
rci->h_age_commitment,
&coin_hash);
TALER_coin_pub_hash (
&coin_pub,
pah,
&coin_hash);
if (GNUNET_OK !=
TALER_planchet_to_coin (pk,
&blind_sig,
&bks,
&rci->coin_priv,
rci->h_age_commitment,
&coin_hash,
&rrh->alg_values[i],
&coin))
TALER_planchet_to_coin (
pk,
&blind_sig,
&bks,
&rci->coin_priv,
pah,
&coin_hash,
&rrh->alg_values[i],
&coin))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@ -257,7 +258,10 @@ handle_refresh_reveal_finished (void *cls,
rrh->reveal_cb = NULL;
}
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
{
TALER_denom_sig_free (&rcis[i].sig);
TALER_age_commitment_proof_free (rcis[i].age_commitment_proof);
}
TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
return;
}
@ -303,7 +307,6 @@ handle_refresh_reveal_finished (void *cls,
}
/* FIXME: refactor this to use struct TALER_EXCHANGE_Handle */
struct TALER_EXCHANGE_RefreshesRevealHandle *
TALER_EXCHANGE_refreshes_reveal (
struct GNUNET_CURL_Context *ctx,
@ -408,20 +411,19 @@ TALER_EXCHANGE_refreshes_reveal (
}
/* 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)
{
GNUNET_assert (NULL != rd->melt_h_age_commitment);
GNUNET_assert (NULL != (old_age_commitment = json_array ()));
for (size_t i = 0; i < rd->melt_age_commitment_proof->commitment.num; i++)
{
GNUNET_assert (0 ==
json_array_append_new (
old_age_commitment,
GNUNET_JSON_from_data_auto (
&rd->melt_age_commitment_proof->
commitment.keys[i])));
enum GNUNET_GenericReturnValue ret;
ret = json_array_append_new (
old_age_commitment,
GNUNET_JSON_from_data_auto (
&rd->melt_age_commitment_proof->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 *dm = strchr (mime, '/');
const char *end;
if ( (NULL == da) ||
(NULL == dm) )
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
( ( (1 == da - accept_pattern) &&
('*' == *accept_pattern) ) ||
@ -138,8 +145,9 @@ mime_matches (const char *accept_pattern,
mime,
da - accept_pattern)) ) ) &&
( (0 == strcmp (da, "/*")) ||
(0 == strcasecmp (da,
dm)) );
(0 == strncasecmp (da,
dm,
end - da)) );
}
@ -150,9 +158,9 @@ TALER_MHD_xmime_matches (const char *accept_pattern,
char *ap = GNUNET_strdup (accept_pattern);
char *sptr;
for (const char *tok = strtok_r (ap, ";", &sptr);
for (const char *tok = strtok_r (ap, ",", &sptr);
NULL != tok;
tok = strtok_r (NULL, ";", &sptr))
tok = strtok_r (NULL, ",", &sptr))
{
if (mime_matches (tok,
mime))

View File

@ -59,9 +59,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_batch_withdraw.c \
testing_api_cmd_check_aml_decision.c \
testing_api_cmd_check_aml_decisions.c \
testing_api_cmd_check_keys.c \
testing_api_cmd_common.c \
testing_api_cmd_connect_with_state.c \
testing_api_cmd_contract_get.c \
testing_api_cmd_deposit.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_sign_key.c \
testing_api_cmd_run_fakebank.c \
testing_api_cmd_serialize_keys.c \
testing_api_cmd_set_officer.c \
testing_api_cmd_set_wire_fee.c \
testing_api_cmd_signal.c \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -69,13 +69,19 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
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),
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 ()
};

View File

@ -67,20 +67,9 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg,
NULL,
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
* config.

View File

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

View File

@ -59,6 +59,7 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_get_auditor ("get-auditor",
@ -145,7 +146,16 @@ run (void *cls,
false),
TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys",
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 ()
};

View File

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

View File

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

View File

@ -87,9 +87,9 @@ run (void *cls,
NULL),
TALER_TESTING_cmd_get_exchange ("get-exchange",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys"),
TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
CMD_EXEC_AGGREGATOR ("run-aggregator-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)
{
TALER_TESTING_unexpected_status (ds->is,
hr->http_status);
hr->http_status,
ds->expected_response_code);
return;
}
TALER_TESTING_interpreter_next (ds->is);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -199,7 +199,8 @@ batch_deposit_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status)
{
TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status);
dr->hr.http_status,
ds->expected_response_code);
return;
}
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
* its hash, respectivelly, NULL otherwise.
* its hash, respectivelly.
*/
struct TALER_AgeCommitmentProof *age_commitment_proof;
struct TALER_AgeCommitmentHash *h_age_commitment;
struct TALER_AgeCommitmentProof age_commitment_proof;
struct TALER_AgeCommitmentHash h_age_commitment;
/**
* 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)
{
TALER_TESTING_unexpected_status (is,
wr->hr.http_status);
wr->hr.http_status,
ws->expected_response_code);
return;
}
switch (wr->hr.http_status)
@ -253,12 +254,8 @@ batch_withdraw_run (void *cls,
const struct TALER_TESTING_Command *create_reserve;
const struct TALER_EXCHANGE_DenomPublicKey *dpk;
struct TALER_EXCHANGE_WithdrawCoinInput wcis[ws->num_coins];
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd;
if (NULL == exchange)
return;
ws->is = is;
create_reserve
= TALER_TESTING_interpreter_lookup_command (
@ -281,7 +278,7 @@ batch_withdraw_run (void *cls,
}
if (NULL == 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;
GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv,
&ws->reserve_pub.eddsa_pub);
@ -295,7 +292,7 @@ batch_withdraw_run (void *cls,
struct TALER_EXCHANGE_WithdrawCoinInput *wci = &wcis[i];
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,
ws->age > 0);
if (NULL == dpk)
@ -319,7 +316,7 @@ batch_withdraw_run (void *cls,
wci->pk = cs->pk;
wci->ps = &cs->ps;
wci->ach = cs->h_age_commitment;
wci->ach = &cs->h_age_commitment;
}
ws->wsh = TALER_EXCHANGE_batch_withdraw (
TALER_TESTING_interpreter_get_context (is),
@ -369,13 +366,8 @@ batch_withdraw_cleanup (void *cls,
TALER_EXCHANGE_destroy_denomination_key (cs->pk);
cs->pk = NULL;
}
if (NULL != 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);
if (0 < ws->age)
TALER_age_commitment_proof_free (&cs->age_commitment_proof);
}
GNUNET_free (ws->coins);
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_exchange_url (ws->exchange_url),
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,
cs->h_age_commitment),
ws->age > 0 ?
&cs->h_age_commitment :
NULL),
TALER_TESTING_trait_end ()
};
@ -476,13 +472,9 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
if (0 < age)
{
struct TALER_AgeCommitmentProof *acp;
struct TALER_AgeCommitmentHash *hac;
struct GNUNET_HashCode seed;
struct TALER_AgeMask mask;
acp = GNUNET_new (struct TALER_AgeCommitmentProof);
hac = GNUNET_new (struct TALER_AgeCommitmentHash);
mask = TALER_extensions_get_age_restriction_mask ();
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&seed,
@ -493,7 +485,7 @@ TALER_TESTING_cmd_batch_withdraw (const char *label,
&mask,
age,
&seed,
acp))
&cs->age_commitment_proof))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"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);
}
TALER_age_commitment_hash (&acp->commitment,
hac);
cs->age_commitment_proof = acp;
cs->h_age_commitment = hac;
TALER_age_commitment_hash (&cs->age_commitment_proof.commitment,
&cs->h_age_commitment);
}
if (GNUNET_OK !=

View File

@ -80,7 +80,8 @@ check_aml_decision_cb (void *cls,
if (ds->expected_http_status != adr->hr.http_status)
{
TALER_TESTING_unexpected_status (ds->is,
adr->hr.http_status);
adr->hr.http_status,
ds->expected_http_status);
return;
}
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)
{
TALER_TESTING_unexpected_status (ds->is,
adr->hr.http_status);
adr->hr.http_status,
ds->expected_http_status);
return;
}
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)
{
TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status);
dr->hr.http_status,
ds->expected_response_code);
return;
}
ref = TALER_TESTING_interpreter_lookup_command (ds->is,

View File

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

View File

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

View File

@ -46,7 +46,12 @@ struct GetExchangeState
/**
* 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.
@ -58,6 +63,17 @@ struct GetExchangeState
*/
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?
*/
@ -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
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;
const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr;
struct TALER_TESTING_Interpreter *is = ges->is;
ges->exchange = NULL;
ges->keys = keys;
switch (hr->http_status)
{
case MHD_HTTP_OK:
@ -82,11 +109,13 @@ cert_cb (void *cls,
TALER_TESTING_interpreter_next (is);
return;
}
ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date;
return;
default:
GNUNET_break (0);
TALER_EXCHANGE_disconnect (ges->exchange);
ges->exchange = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"/keys responded with HTTP status %u\n",
hr->http_status);
if (ges->wait_for_keys)
{
ges->wait_for_keys = false;
@ -111,6 +140,7 @@ get_exchange_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct GetExchangeState *ges = cls;
struct TALER_EXCHANGE_Keys *xkeys = NULL;
(void) cmd;
if (NULL == ges->exchange_url)
@ -119,6 +149,72 @@ get_exchange_run (void *cls,
TALER_TESTING_interpreter_fail (is);
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 (GNUNET_SYSERR ==
@ -127,17 +223,19 @@ get_exchange_run (void *cls,
&ges->master_priv.eddsa_priv))
{
GNUNET_break (0);
TALER_EXCHANGE_keys_decref (xkeys);
TALER_TESTING_interpreter_fail (is);
return;
}
}
ges->is = is;
ges->exchange
= TALER_EXCHANGE_connect (TALER_TESTING_interpreter_get_context (is),
ges->exchange_url,
&cert_cb,
ges,
TALER_EXCHANGE_OPTION_END);
= TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is),
ges->exchange_url,
xkeys,
&cert_cb,
ges);
TALER_EXCHANGE_keys_decref (xkeys);
if (NULL == ges->exchange)
{
GNUNET_break (0);
@ -163,9 +261,11 @@ get_exchange_cleanup (void *cls,
if (NULL != ges->exchange)
{
TALER_EXCHANGE_disconnect (ges->exchange);
TALER_EXCHANGE_get_keys_cancel (ges->exchange);
ges->exchange = NULL;
}
TALER_EXCHANGE_keys_decref (ges->keys);
ges->keys = NULL;
GNUNET_free (ges->master_priv_file);
GNUNET_free (ges->exchange_url);
GNUNET_free (ges);
@ -189,17 +289,16 @@ get_exchange_traits (void *cls,
{
struct GetExchangeState *ges = cls;
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[] = {
TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_master_pub (&keys->master_pub),
TALER_TESTING_make_trait_exchange (ges->exchange),
TALER_TESTING_make_trait_keys (keys),
TALER_TESTING_make_trait_master_pub (&ges->keys->master_pub),
TALER_TESTING_make_trait_keys (ges->keys),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_make_trait_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end ()
};
@ -212,8 +311,9 @@ get_exchange_traits (void *cls,
{
struct TALER_TESTING_Trait traits[] = {
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_timestamp (0,
&ges->my_denom_date),
TALER_TESTING_trait_end ()
};
@ -284,6 +384,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_get_exchange (
const char *label,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *last_keys_ref,
bool wait_for_keys,
bool load_private_key)
{
@ -291,6 +392,7 @@ TALER_TESTING_cmd_get_exchange (
ges = GNUNET_new (struct GetExchangeState);
ges->exchange_url = get_exchange_base_url (cfg);
ges->last_keys_ref = last_keys_ref;
if (load_private_key)
ges->master_priv_file = get_exchange_master_priv_file (cfg);
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)
{
TALER_TESTING_unexpected_status (is,
ks->http_status);
ks->http_status,
kcg->expected_response_code);
return;
}
switch (ks->http_status)

View File

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

View File

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

View File

@ -163,7 +163,8 @@ deposit_cb (void *cls,
if (ds->expected_response_code != dr->hr.http_status)
{
TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status);
dr->hr.http_status,
ds->expected_response_code);
return;
}
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)
{
TALER_TESTING_unexpected_status (pds->is,
pdr->hr.http_status);
pdr->hr.http_status,
pds->expected_response_code);
return;
}
TALER_TESTING_interpreter_next (pds->is);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -165,11 +165,7 @@ open_run (void *cls,
struct OpenState *ss = cls;
const struct TALER_TESTING_Command *create_reserve;
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;
create_reserve
= 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)
{
TALER_TESTING_unexpected_status (ds->is,
dr->hr.http_status);
dr->hr.http_status,
ds->expected_response_code);
return;
}
switch (dr->hr.http_status)
@ -184,12 +185,8 @@ purse_run (void *cls,
struct ReservePurseState *ds = cls;
const struct TALER_ReservePrivateKeyP *reserve_priv;
const struct TALER_TESTING_Command *ref;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd;
if (NULL == exchange)
return;
ds->is = is;
ref = TALER_TESTING_interpreter_lookup_command (ds->is,
ds->reserve_ref);

View File

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

View File

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

View File

@ -79,7 +79,8 @@ success_cb (
if (rs->expected_response_code != hr->http_status)
{
TALER_TESTING_unexpected_status (rs->is,
hr->http_status);
hr->http_status,
rs->expected_response_code);
return;
}
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->bank_url);
GNUNET_free (rfs->currency);
GNUNET_free (rfs);
}
@ -194,7 +195,9 @@ TALER_TESTING_cmd_run_fakebank (
(unsigned int) fakebank_port,
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;
{
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)
{
TALER_TESTING_unexpected_status (ds->is,
hr->http_status);
hr->http_status,
MHD_HTTP_NO_CONTENT);
return;
}
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)
{
TALER_TESTING_unexpected_status (ds->is,
hr->http_status);
hr->http_status,
ds->expected_response_code);
return;
}
TALER_TESTING_interpreter_next (ds->is);

View File

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

View File

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

View File

@ -464,6 +464,9 @@ void
TALER_age_proof_free (
struct TALER_AgeProof *proof)
{
if (NULL == proof)
return;
if (NULL != proof->keys)
{
GNUNET_CRYPTO_zero_keys (
@ -479,26 +482,71 @@ TALER_age_proof_free (
void
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 (
cp->proof.keys,
sizeof(*cp->proof.keys) * cp->proof.num);
acp->proof.keys,
sizeof(*acp->proof.keys) * acp->proof.num);
GNUNET_free (cp->proof.keys);
cp->proof.keys = NULL;
GNUNET_free (acp->proof.keys);
acp->proof.keys = NULL;
}
if (NULL != cp->commitment.keys)
if (NULL != acp->commitment.keys)
{
GNUNET_free (cp->commitment.keys);
cp->commitment.keys = NULL;
GNUNET_free (acp->commitment.keys);
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
TALER_JSON_parse_age_groups (const json_t *root,
struct TALER_AgeMask *mask)
@ -571,19 +619,16 @@ TALER_parse_age_group_string (
}
char *
const char *
TALER_age_mask_to_string (
const struct TALER_AgeMask *mask)
{
static char buf[256] = {0};
uint32_t bits = mask->bits;
unsigned int n = 0;
char *buf = GNUNET_malloc (32 * 3); // max characters possible
char *pos = buf;
if (NULL == buf)
{
return buf;
}
memset (buf, 0, sizeof(buf));
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 */