more documenting, checking for consistency between prepared statements and functional logic
This commit is contained in:
parent
d4f5af2151
commit
c3ab96b242
@ -181,6 +181,20 @@ TALER_amount_cmp_currency (const struct TALER_Amount *a1,
|
|||||||
const struct TALER_Amount *a2);
|
const struct TALER_Amount *a2);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if @a a1 and @a a2 are the same currency, NBO variant.
|
||||||
|
*
|
||||||
|
* @param a1 amount to test
|
||||||
|
* @param a2 amount to test
|
||||||
|
* @return #GNUNET_YES if @a a1 and @a a2 are the same currency
|
||||||
|
* #GNUNET_NO if the currencies are different
|
||||||
|
* #GNUNET_SYSERR if either amount is invalid
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_amount_cmp_currency_nbo (const struct TALER_AmountNBO *a1,
|
||||||
|
const struct TALER_AmountNBO *a2);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform saturating subtraction of amounts.
|
* Perform saturating subtraction of amounts.
|
||||||
*
|
*
|
||||||
|
@ -208,7 +208,7 @@ postgres_create_tables (void *cls,
|
|||||||
/* Denomination table for holding the publicly available information of
|
/* Denomination table for holding the publicly available information of
|
||||||
denominations keys. The denominations are to be referred to by using
|
denominations keys. The denominations are to be referred to by using
|
||||||
foreign keys. The denominations are deleted by a housekeeping tool;
|
foreign keys. The denominations are deleted by a housekeeping tool;
|
||||||
hence, do not use `ON DELETE CASCASE' on these rows in the tables
|
hence, do not use `ON DELETE CASCADE' on these rows in the tables
|
||||||
referencing these rows */
|
referencing these rows */
|
||||||
SQLEXEC ("CREATE TABLE IF NOT EXISTS denominations"
|
SQLEXEC ("CREATE TABLE IF NOT EXISTS denominations"
|
||||||
"(pub BYTEA PRIMARY KEY"
|
"(pub BYTEA PRIMARY KEY"
|
||||||
@ -267,9 +267,9 @@ postgres_create_tables (void *cls,
|
|||||||
TODO: maybe add timestamp of when the operation was performed, so we
|
TODO: maybe add timestamp of when the operation was performed, so we
|
||||||
can influence the reserves' expiration_date not just based on
|
can influence the reserves' expiration_date not just based on
|
||||||
incoming but also based on outgoing transactions?
|
incoming but also based on outgoing transactions?
|
||||||
TODO: is blind_ev really a _primary key_? Is this constraint useful? */
|
TODO: is h_blind_ev really a _primary key_? Is this constraint useful? */
|
||||||
SQLEXEC ("CREATE TABLE IF NOT EXISTS collectable_blindcoins"
|
SQLEXEC ("CREATE TABLE IF NOT EXISTS collectable_blindcoins"
|
||||||
"(blind_ev BYTEA PRIMARY KEY"
|
"(h_blind_ev BYTEA PRIMARY KEY"
|
||||||
",denom_pub BYTEA NOT NULL REFERENCES denominations (pub)"
|
",denom_pub BYTEA NOT NULL REFERENCES denominations (pub)"
|
||||||
",denom_sig BYTEA NOT NULL"
|
",denom_sig BYTEA NOT NULL"
|
||||||
",reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32) REFERENCES reserves (reserve_pub) ON DELETE CASCADE"
|
",reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32) REFERENCES reserves (reserve_pub) ON DELETE CASCADE"
|
||||||
@ -431,6 +431,7 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
PQclear (result); result = NULL; \
|
PQclear (result); result = NULL; \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
/* Used in #postgres_insert_denomination() */
|
||||||
PREPARE ("insert_denomination",
|
PREPARE ("insert_denomination",
|
||||||
"INSERT INTO denominations "
|
"INSERT INTO denominations "
|
||||||
"(pub"
|
"(pub"
|
||||||
@ -454,17 +455,23 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
"($1, $2, $3, $4, $5, $6,"
|
"($1, $2, $3, $4, $5, $6,"
|
||||||
"$7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17);",
|
"$7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17);",
|
||||||
14, NULL);
|
14, NULL);
|
||||||
PREPARE ("get_reserve",
|
|
||||||
|
/* FIXME: #3808: need a 'select_denominations' for auditor */
|
||||||
|
|
||||||
|
/* Used in #postgres_reserve_get() */
|
||||||
|
PREPARE ("reserve_get",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" current_balance_val"
|
" current_balance_val"
|
||||||
",current_balance_frac"
|
",current_balance_frac"
|
||||||
",current_balance_curr"
|
",current_balance_curr"
|
||||||
",expiration_date "
|
",expiration_date"
|
||||||
"FROM reserves "
|
" FROM reserves"
|
||||||
"WHERE reserve_pub=$1 "
|
" WHERE reserve_pub=$1"
|
||||||
"LIMIT 1; ",
|
" LIMIT 1;",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
PREPARE ("create_reserve",
|
|
||||||
|
/* Used in #postgres_reserves_in_insert() when the reserve is new */
|
||||||
|
PREPARE ("reserve_create",
|
||||||
"INSERT INTO reserves "
|
"INSERT INTO reserves "
|
||||||
"(reserve_pub"
|
"(reserve_pub"
|
||||||
",current_balance_val"
|
",current_balance_val"
|
||||||
@ -474,7 +481,8 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5);",
|
"($1, $2, $3, $4, $5);",
|
||||||
5, NULL);
|
5, NULL);
|
||||||
PREPARE ("update_reserve",
|
/* Used in #postgres_reserves_update() when the reserve is updated */
|
||||||
|
PREPARE ("reserve_update",
|
||||||
"UPDATE reserves"
|
"UPDATE reserves"
|
||||||
" SET"
|
" SET"
|
||||||
" expiration_date=$1 "
|
" expiration_date=$1 "
|
||||||
@ -482,7 +490,8 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",current_balance_frac=$3 "
|
",current_balance_frac=$3 "
|
||||||
"WHERE current_balance_curr=$4 AND reserve_pub=$5",
|
"WHERE current_balance_curr=$4 AND reserve_pub=$5",
|
||||||
5, NULL);
|
5, NULL);
|
||||||
PREPARE ("create_reserves_in_transaction",
|
/* Used in #postgres_reserves_in_insert() to store transaction details */
|
||||||
|
PREPARE ("reserves_in_add_transaction",
|
||||||
"INSERT INTO reserves_in "
|
"INSERT INTO reserves_in "
|
||||||
"(reserve_pub"
|
"(reserve_pub"
|
||||||
",balance_val"
|
",balance_val"
|
||||||
@ -493,19 +502,28 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5, $6);",
|
"($1, $2, $3, $4, $5, $6);",
|
||||||
6, NULL);
|
6, NULL);
|
||||||
PREPARE ("get_reserves_in_transactions",
|
/* Used in #postgres_get_reserve_history() to obtain inbound transactions
|
||||||
|
for a reserve */
|
||||||
|
PREPARE ("reserves_in_get_transactions",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" balance_val"
|
" balance_val"
|
||||||
",balance_frac"
|
",balance_frac"
|
||||||
",balance_curr"
|
",balance_curr"
|
||||||
",expiration_date"
|
",expiration_date" /* NOTE: not used (yet), #3817 */
|
||||||
",details"
|
",details" /* NOTE: not used (yet), #3817 */
|
||||||
" FROM reserves_in"
|
" FROM reserves_in"
|
||||||
" WHERE reserve_pub=$1",
|
" WHERE reserve_pub=$1",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
|
/* Used in #postgres_insert_collectable_blindcoin() to store
|
||||||
|
the signature of a blinded coin with the blinded coin's
|
||||||
|
details before returning it during /withdraw/sign. We store
|
||||||
|
the coin's denomination information (public key, signature)
|
||||||
|
and the blinded message as well as the reserve that the coin
|
||||||
|
is being withdrawn from and the signature of the message
|
||||||
|
authorizing the withdrawal. */
|
||||||
PREPARE ("insert_collectable_blindcoin",
|
PREPARE ("insert_collectable_blindcoin",
|
||||||
"INSERT INTO collectable_blindcoins "
|
"INSERT INTO collectable_blindcoins "
|
||||||
"(blind_ev"
|
"(h_blind_ev"
|
||||||
",denom_pub"
|
",denom_pub"
|
||||||
",denom_sig"
|
",denom_sig"
|
||||||
",reserve_pub"
|
",reserve_pub"
|
||||||
@ -513,6 +531,10 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5);",
|
"($1, $2, $3, $4, $5);",
|
||||||
5, NULL);
|
5, NULL);
|
||||||
|
/* Used in #postgres_get_collectable_blindcoin() to
|
||||||
|
locate the response for a /withdraw/sign request
|
||||||
|
using the hash of the blinded message. Used to
|
||||||
|
make sure /withdraw/sign requests are idempotent. */
|
||||||
PREPARE ("get_collectable_blindcoin",
|
PREPARE ("get_collectable_blindcoin",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" denom_pub"
|
" denom_pub"
|
||||||
@ -520,17 +542,23 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",reserve_sig"
|
",reserve_sig"
|
||||||
",reserve_pub"
|
",reserve_pub"
|
||||||
" FROM collectable_blindcoins"
|
" FROM collectable_blindcoins"
|
||||||
" WHERE blind_ev=$1",
|
" WHERE h_blind_ev=$1",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
|
/* Used during #postgres_get_reserve_history() to
|
||||||
|
obtain all of the /withdraw/sign operations that
|
||||||
|
have been performed on a given reserve. (i.e. to
|
||||||
|
demonstrate double-spending) */
|
||||||
PREPARE ("get_reserves_blindcoins",
|
PREPARE ("get_reserves_blindcoins",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" blind_ev"
|
" h_blind_ev"
|
||||||
",denom_pub"
|
",denom_pub"
|
||||||
",denom_sig"
|
",denom_sig"
|
||||||
",reserve_sig"
|
",reserve_sig"
|
||||||
" FROM collectable_blindcoins"
|
" FROM collectable_blindcoins"
|
||||||
" WHERE reserve_pub=$1;",
|
" WHERE reserve_pub=$1;",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
|
|
||||||
|
|
||||||
/* refreshing */
|
/* refreshing */
|
||||||
PREPARE ("get_refresh_session",
|
PREPARE ("get_refresh_session",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
@ -914,6 +942,17 @@ postgres_insert_denomination (void *cls,
|
|||||||
TALER_PQ_query_param_amount_nbo (&issue->fee_refresh),
|
TALER_PQ_query_param_amount_nbo (&issue->fee_refresh),
|
||||||
TALER_PQ_query_param_end
|
TALER_PQ_query_param_end
|
||||||
};
|
};
|
||||||
|
/* check fees match coin currency */
|
||||||
|
GNUNET_assert (GNUNET_YES ==
|
||||||
|
TALER_amount_cmp_currency_nbo (&issue->value,
|
||||||
|
&issue->fee_withdraw));
|
||||||
|
GNUNET_assert (GNUNET_YES ==
|
||||||
|
TALER_amount_cmp_currency_nbo (&issue->value,
|
||||||
|
&issue->fee_deposit));
|
||||||
|
GNUNET_assert (GNUNET_YES ==
|
||||||
|
TALER_amount_cmp_currency_nbo (&issue->value,
|
||||||
|
&issue->fee_refresh));
|
||||||
|
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"insert_denomination",
|
"insert_denomination",
|
||||||
params);
|
params);
|
||||||
@ -958,7 +997,7 @@ postgres_reserve_get (void *cls,
|
|||||||
};
|
};
|
||||||
|
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"get_reserve",
|
"reserve_get",
|
||||||
params);
|
params);
|
||||||
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
||||||
{
|
{
|
||||||
@ -1010,7 +1049,7 @@ postgres_reserves_update (void *cls,
|
|||||||
TALER_PQ_query_param_end
|
TALER_PQ_query_param_end
|
||||||
};
|
};
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"update_reserve",
|
"reserve_update",
|
||||||
params);
|
params);
|
||||||
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
||||||
{
|
{
|
||||||
@ -1082,7 +1121,7 @@ postgres_reserves_in_insert (void *cls,
|
|||||||
TALER_PQ_query_param_end
|
TALER_PQ_query_param_end
|
||||||
};
|
};
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"create_reserve",
|
"reserve_create",
|
||||||
params);
|
params);
|
||||||
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
||||||
{
|
{
|
||||||
@ -1122,7 +1161,7 @@ postgres_reserves_in_insert (void *cls,
|
|||||||
TALER_PQ_query_param_end
|
TALER_PQ_query_param_end
|
||||||
};
|
};
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"create_reserves_in_transaction",
|
"reserves_in_add_transaction",
|
||||||
params);
|
params);
|
||||||
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
if (PGRES_COMMAND_OK != PQresultStatus(result))
|
||||||
{
|
{
|
||||||
@ -1165,7 +1204,7 @@ postgres_reserves_in_insert (void *cls,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locate the response for a /withdraw request under the
|
* Locate the response for a /withdraw/sign request under the
|
||||||
* key of the hash of the blinded message.
|
* key of the hash of the blinded message.
|
||||||
*
|
*
|
||||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||||
@ -1239,8 +1278,8 @@ postgres_get_collectable_blindcoin (void *cls,
|
|||||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||||
* @param session database connection to use
|
* @param session database connection to use
|
||||||
* @param h_blind hash of the blinded message
|
* @param h_blind hash of the blinded message
|
||||||
* @param withdraw amount by which the reserve will be withdrawn with this
|
* @param withdraw amount by which the reserve will be reduced with this
|
||||||
* transaction
|
* transaction (coin value plus fee)
|
||||||
* @param collectable corresponding collectable coin (blind signature)
|
* @param collectable corresponding collectable coin (blind signature)
|
||||||
* if a coin is found
|
* if a coin is found
|
||||||
* @return #GNUNET_SYSERR on internal error
|
* @return #GNUNET_SYSERR on internal error
|
||||||
@ -1341,7 +1380,7 @@ postgres_get_reserve_history (void *cls,
|
|||||||
};
|
};
|
||||||
|
|
||||||
result = TALER_PQ_exec_prepared (session->conn,
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
"get_reserves_in_transactions",
|
"reserves_in_get_transactions",
|
||||||
params);
|
params);
|
||||||
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
||||||
{
|
{
|
||||||
@ -1354,6 +1393,12 @@ postgres_get_reserve_history (void *cls,
|
|||||||
"Asked to fetch history for an unknown reserve.\n");
|
"Asked to fetch history for an unknown reserve.\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
/* FIXME: maybe also use the 'expiration_date' and 'details'
|
||||||
|
values and return those as well? While right now they
|
||||||
|
are unnecessary, the 'expiration_date' should become the
|
||||||
|
original transfer date, and then it will be useful;
|
||||||
|
similarly, 'details' might become useful for reserve refunds
|
||||||
|
in the future. (#3817) */
|
||||||
while (0 < rows)
|
while (0 < rows)
|
||||||
{
|
{
|
||||||
bt = GNUNET_new (struct TALER_MINTDB_BankTransfer);
|
bt = GNUNET_new (struct TALER_MINTDB_BankTransfer);
|
||||||
@ -1386,7 +1431,7 @@ postgres_get_reserve_history (void *cls,
|
|||||||
PQclear (result);
|
PQclear (result);
|
||||||
result = NULL;
|
result = NULL;
|
||||||
{
|
{
|
||||||
struct GNUNET_HashCode blind_ev;
|
struct GNUNET_HashCode h_blind_ev;
|
||||||
struct TALER_ReserveSignatureP reserve_sig;
|
struct TALER_ReserveSignatureP reserve_sig;
|
||||||
struct TALER_MINTDB_CollectableBlindcoin *cbc;
|
struct TALER_MINTDB_CollectableBlindcoin *cbc;
|
||||||
struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
|
struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
|
||||||
@ -1410,7 +1455,7 @@ postgres_get_reserve_history (void *cls,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
struct TALER_PQ_ResultSpec rs[] = {
|
struct TALER_PQ_ResultSpec rs[] = {
|
||||||
TALER_PQ_result_spec_auto_from_type ("blind_ev", &blind_ev),
|
TALER_PQ_result_spec_auto_from_type ("h_blind_ev", &h_blind_ev),
|
||||||
TALER_PQ_result_spec_rsa_public_key ("denom_pub", &denom_pub),
|
TALER_PQ_result_spec_rsa_public_key ("denom_pub", &denom_pub),
|
||||||
TALER_PQ_result_spec_rsa_signature ("denom_sig", &denom_sig),
|
TALER_PQ_result_spec_rsa_signature ("denom_sig", &denom_sig),
|
||||||
TALER_PQ_result_spec_auto_from_type ("reserve_sig", &reserve_sig),
|
TALER_PQ_result_spec_auto_from_type ("reserve_sig", &reserve_sig),
|
||||||
@ -1430,7 +1475,7 @@ postgres_get_reserve_history (void *cls,
|
|||||||
cbc = GNUNET_new (struct TALER_MINTDB_CollectableBlindcoin);
|
cbc = GNUNET_new (struct TALER_MINTDB_CollectableBlindcoin);
|
||||||
cbc->sig.rsa_signature = denom_sig;
|
cbc->sig.rsa_signature = denom_sig;
|
||||||
cbc->denom_pub.rsa_public_key = denom_pub;
|
cbc->denom_pub.rsa_public_key = denom_pub;
|
||||||
cbc->h_coin_envelope = blind_ev;
|
cbc->h_coin_envelope = h_blind_ev;
|
||||||
cbc->reserve_pub = *reserve_pub;
|
cbc->reserve_pub = *reserve_pub;
|
||||||
cbc->reserve_sig = reserve_sig;
|
cbc->reserve_sig = reserve_sig;
|
||||||
rh_head->next = GNUNET_new (struct TALER_MINTDB_ReserveHistory);
|
rh_head->next = GNUNET_new (struct TALER_MINTDB_ReserveHistory);
|
||||||
|
@ -237,6 +237,20 @@ test_valid (const struct TALER_Amount *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if @a a is valid, NBO variant.
|
||||||
|
*
|
||||||
|
* @param a amount to test
|
||||||
|
* @return #GNUNET_YES if valid,
|
||||||
|
* #GNUNET_NO if invalid
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
test_valid_nbo (const struct TALER_AmountNBO *a)
|
||||||
|
{
|
||||||
|
return ('\0' != a->currency[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if @a a1 and @a a2 are the same currency.
|
* Test if @a a1 and @a a2 are the same currency.
|
||||||
*
|
*
|
||||||
@ -260,6 +274,29 @@ TALER_amount_cmp_currency (const struct TALER_Amount *a1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if @a a1 and @a a2 are the same currency, NBO variant.
|
||||||
|
*
|
||||||
|
* @param a1 amount to test
|
||||||
|
* @param a2 amount to test
|
||||||
|
* @return #GNUNET_YES if @a a1 and @a a2 are the same currency
|
||||||
|
* #GNUNET_NO if the currencies are different,
|
||||||
|
* #GNUNET_SYSERR if either amount is invalid
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_amount_cmp_currency_nbo (const struct TALER_AmountNBO *a1,
|
||||||
|
const struct TALER_AmountNBO *a2)
|
||||||
|
{
|
||||||
|
if ( (GNUNET_NO == test_valid_nbo (a1)) ||
|
||||||
|
(GNUNET_NO == test_valid_nbo (a2)) )
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
if (0 == strcasecmp (a1->currency,
|
||||||
|
a2->currency))
|
||||||
|
return GNUNET_YES;
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare the value/fraction of two amounts. Does not compare the currency.
|
* Compare the value/fraction of two amounts. Does not compare the currency.
|
||||||
* Comparing amounts of different currencies will cause the program to abort().
|
* Comparing amounts of different currencies will cause the program to abort().
|
||||||
|
Loading…
Reference in New Issue
Block a user