diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backenddb/merchant-0001.sql | 4 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 8 | ||||
-rw-r--r-- | src/backenddb/test_merchantdb.c | 326 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 2 |
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); |