summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backenddb/merchant-0001.sql4
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c8
-rw-r--r--src/backenddb/test_merchantdb.c326
-rw-r--r--src/include/taler_merchantdb_plugin.h2
4 files changed, 326 insertions, 14 deletions
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index 1aa54253..beef2cd8 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -163,9 +163,9 @@ COMMENT ON COLUMN merchant_inventory.next_restock
CREATE TABLE IF NOT EXISTS merchant_inventory_locks
(product_serial BIGINT NOT NULL
REFERENCES merchant_inventory (product_serial) -- NO "ON DELETE CASCADE": locks prevent deletion!
- ,lock_uuid BYTEA NOT NULL CHECK (LENGTH(lock_uuid)=32)
+ ,lock_uuid BYTEA NOT NULL CHECK (LENGTH(lock_uuid)=16)
,total_locked BIGINT NOT NULL
- ,expiration TIMESTAMP NOT NULL
+ ,expiration INT8 NOT NULL
);
CREATE INDEX IF NOT EXISTS merchant_inventory_locks_by_expiration
ON merchant_inventory_locks
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 7c4b543a..f8f8e69d 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1008,7 +1008,7 @@ postgres_lock_product (void *cls,
const char *instance_id,
const char *product_id,
const struct GNUNET_Uuid *uuid,
- uint32_t quantity,
+ uint64_t quantity,
struct GNUNET_TIME_Absolute expiration_time)
{
struct PostgresClosure *pg = cls;
@@ -1016,7 +1016,7 @@ postgres_lock_product (void *cls,
GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (product_id),
GNUNET_PQ_query_param_auto_from_type (uuid),
- GNUNET_PQ_query_param_uint32 (&quantity),
+ GNUNET_PQ_query_param_uint64 (&quantity),
GNUNET_PQ_query_param_absolute_time (&expiration_time),
GNUNET_PQ_query_param_end
};
@@ -5885,10 +5885,10 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" JOIN ps USING (product_serial)"
" WHERE "
" total_stock - total_sold - total_lost - $4 >= "
- " (SELECT SUM(total_locked)"
+ " (SELECT COALESCE(SUM(total_locked), 0)"
" FROM merchant_inventory_locks"
" WHERE product_serial=ps.product_serial) + "
- " (SELECT SUM(total_locked)"
+ " (SELECT COALESCE(SUM(total_locked), 0)"
" FROM merchant_order_locks"
" WHERE product_serial=ps.product_serial)",
5),
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 2ee1f0eb..6826ec12 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -834,7 +834,6 @@ run_test_products (struct TestProducts_Closure *cls)
cls->product_ids));
/* Test locking */
- /*
struct GNUNET_Uuid uuid;
uuid.value[0] = 0x1287346a;
struct GNUNET_TIME_Absolute refund_deadline =
@@ -844,14 +843,13 @@ run_test_products (struct TestProducts_Closure *cls)
cls->is.id,
cls->product_ids[0],
&uuid,
- 0,
+ 1,
refund_deadline))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Lock product failed\n");
return 1;
}
- */
/* Test product deletion */
TEST_RET_ON_FAIL (test_delete_product (cls->is.id,
@@ -859,6 +857,15 @@ run_test_products (struct TestProducts_Closure *cls)
TEST_RET_ON_FAIL (test_lookup_products (cls->is.id,
1,
cls->product_ids));
+
+ /* Test unlocking */
+ if (1 != plugin->unlock_inventory (plugin->cls,
+ &uuid))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unlock inventory failed\n");
+ return 1;
+ }
TEST_RET_ON_FAIL (test_delete_product (cls->is.id,
cls->product_ids[0]));
TEST_RET_ON_FAIL (test_lookup_products (cls->is.id,
@@ -1928,6 +1935,182 @@ test_deposits (void *cls)
}
+static int
+test_lookup_transfer (const char *exchange_url,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_Amount *total_expected,
+ const struct TALER_Amount *fee_expected,
+ const struct GNUNET_TIME_Absolute *time_expected,
+ bool verified_expected)
+{
+ struct TALER_Amount total;
+ struct TALER_Amount fee;
+ struct GNUNET_TIME_Absolute time;
+ bool verified;
+ if (1 != plugin->lookup_transfer (plugin->cls,
+ exchange_url,
+ wtid,
+ &total,
+ &fee,
+ &time,
+ &verified))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer failed\n");
+ return 1;
+ }
+ if ((GNUNET_OK != TALER_amount_cmp_currency (total_expected,
+ &total)) ||
+ (0 != TALER_amount_cmp (total_expected,
+ &total)) ||
+ (GNUNET_OK != TALER_amount_cmp_currency (fee_expected,
+ &fee)) ||
+ (0 != TALER_amount_cmp (fee_expected,
+ &fee)) ||
+ (time_expected->abs_value_us != time.abs_value_us) ||
+ (verified_expected != verified))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer failed: mismatched data\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+struct TestLookupTransferSummary_Closure
+{
+ const char *order_id;
+ const struct TALER_Amount *deposit_value;
+ const struct TALER_Amount *deposit_fee;
+ int result;
+};
+
+
+static void
+lookup_transfer_summary_cb (void *cls,
+ const char *order_id,
+ const struct TALER_Amount *deposit_value,
+ const struct TALER_Amount *deposit_fee)
+{
+ struct TestLookupTransferSummary_Closure *cmp = cls;
+ if (NULL == cmp)
+ return;
+ if ((0 == strcmp (cmp->order_id,
+ order_id)) &&
+ (GNUNET_OK == TALER_amount_cmp_currency (cmp->deposit_value,
+ deposit_value)) &&
+ (0 == TALER_amount_cmp (cmp->deposit_value,
+ deposit_value)) &&
+ (GNUNET_OK == TALER_amount_cmp_currency (cmp->deposit_fee,
+ deposit_fee)) &&
+ (0 == TALER_amount_cmp (cmp->deposit_fee,
+ deposit_fee)))
+ cmp->result = 1;
+ else
+ cmp->result = 0;
+}
+
+
+static int
+test_lookup_transfer_summary (const char *exchange_url,
+ const struct
+ TALER_WireTransferIdentifierRawP *wtid,
+ const char *expected_order_id,
+ const struct TALER_Amount *expected_deposit_value,
+ const struct TALER_Amount *expected_deposit_fee)
+{
+ struct TestLookupTransferSummary_Closure cmp = {
+ .order_id = expected_order_id,
+ .deposit_value = expected_deposit_value,
+ .deposit_fee = expected_deposit_fee
+ };
+ if (1 != plugin->lookup_transfer_summary (plugin->cls,
+ exchange_url,
+ wtid,
+ &lookup_transfer_summary_cb,
+ &cmp))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer summary failed\n");
+ return 1;
+ }
+ if (1 != cmp.result)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer summary failed: mismatched data\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+struct TestLookupTransferDetails_Closure
+{
+ unsigned int details_to_cmp_length;
+ const struct TALER_TrackTransferDetails *details_to_cmp;
+ unsigned int *results_matching;
+ unsigned int results_length;
+};
+
+
+static void
+lookup_transfer_details_cb (void *cls,
+ unsigned int current_offset,
+ const struct TALER_TrackTransferDetails *details)
+{
+ if (NULL == cls)
+ return;
+ struct TestLookupTransferDetails_Closure *cmp = cls;
+ cmp->results_length += 1;
+}
+
+
+static int
+test_lookup_transfer_details (const char *exchange_url,
+ const struct
+ TALER_WireTransferIdentifierRawP *wtid,
+ unsigned int details_length,
+ const struct TALER_TrackTransferDetails *details)
+{
+ unsigned int results_matching[details_length];
+ memset (results_matching, 0, sizeof (unsigned int) * details_length);
+ struct TestLookupTransferDetails_Closure cmp = {
+ .details_to_cmp_length = details_length,
+ .details_to_cmp = details,
+ .results_matching = results_matching,
+ .results_length = 0
+ };
+ if (1 != plugin->lookup_transfer_details (plugin->cls,
+ exchange_url,
+ wtid,
+ &lookup_transfer_details_cb,
+ &cmp))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer details failed\n");
+ return 1;
+ }
+ if (details_length != cmp.results_length)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer details failed: incorrect number of results (%d)\n",
+ cmp.results_length);
+ return 1;
+ }
+ for (unsigned int i = 0; details_length > i; ++i)
+ {
+ if (1 != cmp.results_matching[i])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup transfer details failed: mismatched data\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
struct TestTransfers_Closure
{
/**
@@ -1949,12 +2132,66 @@ struct TestTransfers_Closure
* The account
*/
struct TALER_MERCHANTDB_AccountDetails account;
+
+ /**
+ * The exchange public key
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * The exchange private key
+ */
+ struct TALER_ExchangePrivateKeyP exchange_priv;
+
+ /**
+ * The exchange signature
+ */
+ struct TALER_ExchangeSignatureP exchange_sig;
+
+ /**
+ * The master public key
+ */
+ struct TALER_MasterPublicKeyP master_pub;
+
+ /**
+ * The master private key
+ */
+ struct TALER_MasterPrivateKeyP master_priv;
+
+ /**
+ * The master signature
+ */
+ struct TALER_MasterSignatureP master_sig;
+
+ /**
+ * The exchange signkey start date
+ */
+ struct GNUNET_TIME_Absolute signkey_start;
+
+ /**
+ * The exchange signkey expire date
+ */
+ struct GNUNET_TIME_Absolute signkey_expire;
+
+ /**
+ * The exchange signkey end date
+ */
+ struct GNUNET_TIME_Absolute signkey_end;
};
static void
pre_test_transfers (struct TestTransfers_Closure *cls)
{
+ struct TALER_ExchangeSigningKeyValidityPS exch_sign = {
+ .purpose = {
+ .size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS)),
+ .purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY)
+ }
+
+
+ };
+
/* Instance */
GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
@@ -1986,6 +2223,20 @@ pre_test_transfers (struct TestTransfers_Closure *cls)
&cls->account.salt);
cls->account.payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
cls->account.active = true;
+
+ /* Signing key */
+ GNUNET_CRYPTO_eddsa_key_create (&cls->exchange_priv.eddsa_priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (&cls->exchange_priv.eddsa_priv,
+ &cls->exchange_pub.eddsa_pub);
+ GNUNET_CRYPTO_eddsa_key_create (&cls->master_priv.eddsa_priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (&cls->master_priv.eddsa_priv,
+ &cls->master_pub.eddsa_pub);
+ GNUNET_CRYPTO_eddsa_sign (&cls->master_priv.eddsa_priv,
+ &exch_sign,
+ &cls->master_sig.eddsa_signature);
+ cls->signkey_start = GNUNET_TIME_absolute_get ();
+ cls->signkey_expire = GNUNET_TIME_absolute_get ();
+ cls->signkey_end = GNUNET_TIME_absolute_get ();
}
@@ -2000,10 +2251,16 @@ post_test_transfers (struct TestTransfers_Closure *cls)
static int
run_test_transfers (struct TestTransfers_Closure *cls)
{
+ const char *exchange_url = "exch-url";
struct TALER_WireTransferIdentifierRawP wtid = {
.raw = {0}
};
struct TALER_Amount amount;
+ struct TALER_Amount total_with_fee;
+ struct TALER_EXCHANGE_TransferData transfer_data = {
+ .exchange_pub = cls->exchange_pub,
+ .execution_time = GNUNET_TIME_absolute_get (),
+ };
/* Insert the instance */
TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
@@ -2020,7 +2277,7 @@ run_test_transfers (struct TestTransfers_Closure *cls)
&amount));
if (1 != plugin->insert_transfer (plugin->cls,
cls->is.id,
- "exch-url",
+ exchange_url,
&wtid,
&amount,
cls->account.payto_uri,
@@ -2031,10 +2288,21 @@ run_test_transfers (struct TestTransfers_Closure *cls)
return 1;
}
+ /* Insert a signing key */
+ if (1 != plugin->insert_exchange_signkey (plugin->cls,
+ &cls->master_pub,
+ &cls->exchange_pub,
+ cls->signkey_start,
+ cls->signkey_expire,
+ cls->signkey_end,
+ &cls->master_sig))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Insert signing key failed\n");
+ return 1;
+ }
+
/* Test transfer details */
- struct TALER_EXCHANGE_TransferData transfer_data = {
- .details_length = 0
- };
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:13",
&transfer_data.total_amount));
@@ -2053,6 +2321,50 @@ run_test_transfers (struct TestTransfers_Closure *cls)
return 1;
}
+ /* Test lookup transfer */
+ GNUNET_assert (0 <= TALER_amount_add (&total_with_fee,
+ &transfer_data.total_amount,
+ &transfer_data.wire_fee));
+ TEST_RET_ON_FAIL (test_lookup_transfer (exchange_url,
+ &wtid,
+ &total_with_fee,
+ &transfer_data.wire_fee,
+ &transfer_data.execution_time,
+ false));
+
+ /* Test set status to verified */
+ if (1 != plugin->set_transfer_status_to_verified (plugin->cls,
+ exchange_url,
+ &wtid))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Set transfer to verified failed\n");
+ return 1;
+ }
+ TEST_RET_ON_FAIL (test_lookup_transfer (exchange_url,
+ &wtid,
+ &total_with_fee,
+ &transfer_data.wire_fee,
+ &transfer_data.execution_time,
+ true));
+
+ /* Test lookup transfer summary */
+ /*
+ TEST_RET_ON_FAIL (test_lookup_transfer_summary (exchange_url,
+ &wtid,
+ "",
+ &amount,
+ &transfer_data.wire_fee));
+ */
+
+ /* Test lookup transfer details */
+ /*
+ TEST_RET_ON_FAIL (test_lookup_transfer_details (exchange_url,
+ &wtid,
+ 0,
+ NULL));
+ */
+
return 0;
}
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index 23ad9b84..93462a94 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -927,7 +927,7 @@ struct TALER_MERCHANTDB_Plugin
const char *instance_id,
const char *product_id,
const struct GNUNET_Uuid *uuid,
- uint32_t quantity,
+ uint64_t quantity,
struct GNUNET_TIME_Absolute expiration_time);