aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-28 22:18:53 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-28 22:18:53 +0100
commit1466048e4d19a198a33d1f224dbb5a25fa42b9c2 (patch)
tree5ac4f3b667309e7c5a0f0f6b3ae3b3ce610da73b
parentfd1bcfecfa0698f1c29f8f530e511034f92546c7 (diff)
downloadexchange-1466048e4d19a198a33d1f224dbb5a25fa42b9c2.tar.gz
exchange-1466048e4d19a198a33d1f224dbb5a25fa42b9c2.zip
cleaning up mint_db API
-rw-r--r--src/mint/mint.h30
-rw-r--r--src/mint/mint_db.c932
-rw-r--r--src/mint/mint_db.h447
-rw-r--r--src/mint/taler-mint-httpd_db.c79
-rw-r--r--src/mint/taler-mint-httpd_deposit.c23
-rw-r--r--src/mint/test_mint_deposits.c40
6 files changed, 892 insertions, 659 deletions
diff --git a/src/mint/mint.h b/src/mint/mint.h
index b29162b20..1e1221157 100644
--- a/src/mint/mint.h
+++ b/src/mint/mint.h
@@ -35,36 +35,6 @@
35 35
36 36
37 37
38/**
39 * Information we keep for a withdrawn coin to reproduce
40 * the /withdraw operation if needed, and to have proof
41 * that a reserve was drained by this amount.
42 */
43struct CollectableBlindcoin
44{
45
46 /**
47 * Our signature over the (blinded) coin.
48 */
49 struct GNUNET_CRYPTO_rsa_Signature *sig;
50
51 /**
52 * Denomination key (which coin was generated).
53 */
54 struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
55
56 /**
57 * Public key of the reserve that was drained.
58 */
59 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
60
61 /**
62 * Signature confirming the withdrawl, matching @e reserve_pub,
63 * @e denom_pub and @e h_blind.
64 */
65 struct GNUNET_CRYPTO_EddsaSignature reserve_sig;
66};
67
68 38
69/** 39/**
70 * Global information for a refreshing session. 40 * Global information for a refreshing session.
diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c
index 0f233a5ae..dcde03dc1 100644
--- a/src/mint/mint_db.c
+++ b/src/mint/mint_db.c
@@ -54,127 +54,49 @@ static char *TALER_MINT_db_connection_cfg_str;
54 } while (0) 54 } while (0)
55 55
56 56
57/**
58 * Locate the response for a /withdraw request under the
59 * key of the hash of the blinded message.
60 *
61 * @param db_conn database connection to use
62 * @param h_blind hash of the blinded message
63 * @param collectable corresponding collectable coin (blind signature)
64 * if a coin is found
65 * @return #GNUNET_SYSERR on internal error
66 * #GNUNET_NO if the collectable was not found
67 * #GNUNET_YES on success
68 */
69int
70TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn,
71 const struct GNUNET_HashCode *h_blind,
72 struct CollectableBlindcoin *collectable)
73{
74 PGresult *result;
75 struct TALER_DB_QueryParam params[] = {
76 TALER_DB_QUERY_PARAM_PTR (h_blind),
77 TALER_DB_QUERY_PARAM_END
78 };
79 char *sig_buf;
80 size_t sig_buf_size;
81 57
82 result = TALER_DB_exec_prepared (db_conn,
83 "get_collectable_blindcoins",
84 params);
85
86 if (PGRES_TUPLES_OK != PQresultStatus (result))
87 {
88 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
89 "Query failed: %s\n",
90 PQresultErrorMessage (result));
91 PQclear (result);
92 return GNUNET_SYSERR;
93 }
94 if (0 == PQntuples (result))
95 {
96 PQclear (result);
97 return GNUNET_NO;
98 }
99 58
100 struct TALER_DB_ResultSpec rs[] = {
101 TALER_DB_RESULT_SPEC_VAR("blind_sig", &sig_buf, &sig_buf_size),
102 TALER_DB_RESULT_SPEC("denom_pub", &collectable->denom_pub),
103 TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig),
104 TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub),
105 TALER_DB_RESULT_SPEC_END
106 };
107 59
108 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) 60int
109 { 61TALER_TALER_DB_extract_amount_nbo (PGresult *result,
110 GNUNET_break (0); 62 unsigned int row,
111 PQclear (result); 63 int indices[3],
64 struct TALER_AmountNBO *denom_nbo)
65{
66 if ((indices[0] < 0) || (indices[1] < 0) || (indices[2] < 0))
67 return GNUNET_NO;
68 if (sizeof (uint32_t) != PQgetlength (result, row, indices[0]))
112 return GNUNET_SYSERR; 69 return GNUNET_SYSERR;
113 } 70 if (sizeof (uint32_t) != PQgetlength (result, row, indices[1]))
114 PQclear (result); 71 return GNUNET_SYSERR;
72 if (PQgetlength (result, row, indices[2]) > TALER_CURRENCY_LEN)
73 return GNUNET_SYSERR;
74 denom_nbo->value = *(uint32_t *) PQgetvalue (result, row, indices[0]);
75 denom_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, indices[1]);
76 memset (denom_nbo->currency, 0, TALER_CURRENCY_LEN);
77 memcpy (denom_nbo->currency, PQgetvalue (result, row, indices[2]), PQgetlength (result, row, indices[2]));
115 return GNUNET_OK; 78 return GNUNET_OK;
116} 79}
117 80
118 81
119/**
120 * Store collectable bit coin under the corresponding
121 * hash of the blinded message.
122 *
123 * @param db_conn database connection to use
124 * @param h_blind hash of the blinded message
125 * @param collectable corresponding collectable coin (blind signature)
126 * if a coin is found
127 * @return #GNUNET_SYSERR on internal error
128 * #GNUNET_NO if the collectable was not found
129 * #GNUNET_YES on success
130 */
131int 82int
132TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, 83TALER_TALER_DB_extract_amount (PGresult *result,
133 const struct GNUNET_HashCode *h_blind, 84 unsigned int row,
134 const struct CollectableBlindcoin *collectable) 85 int indices[3],
86 struct TALER_Amount *denom)
135{ 87{
136 PGresult *result; 88 struct TALER_AmountNBO denom_nbo;
137 char *sig_buf; 89 int res;
138 size_t sig_buf_size;
139
140 sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig,
141 &sig_buf);
142 {
143 struct TALER_DB_QueryParam params[] = {
144 TALER_DB_QUERY_PARAM_PTR (&h_blind),
145 TALER_DB_QUERY_PARAM_PTR_SIZED (sig_buf, sig_buf_size),
146 TALER_DB_QUERY_PARAM_PTR (&collectable->denom_pub),
147 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub),
148 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig),
149 TALER_DB_QUERY_PARAM_END
150 };
151
152 result = TALER_DB_exec_prepared (db_conn,
153 "insert_collectable_blindcoins",
154 params);
155 if (PGRES_COMMAND_OK != PQresultStatus (result))
156 {
157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
158 "Query failed: %s\n",
159 PQresultErrorMessage (result));
160 PQclear (result);
161 return GNUNET_SYSERR;
162 }
163 90
164 if (0 != strcmp ("1", PQcmdTuples (result))) 91 res = TALER_TALER_DB_extract_amount_nbo (result, row, indices, &denom_nbo);
165 { 92 if (GNUNET_OK != res)
166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 93 return res;
167 "Insert failed (updated '%s' tupes instead of '1')\n", 94 *denom = TALER_amount_ntoh (denom_nbo);
168 PQcmdTuples (result));
169 PQclear (result);
170 return GNUNET_SYSERR;
171 }
172 PQclear (result);
173 }
174 return GNUNET_OK; 95 return GNUNET_OK;
175} 96}
176 97
177 98
99
178int 100int
179TALER_MINT_DB_get_reserve (PGconn *db_conn, 101TALER_MINT_DB_get_reserve (PGconn *db_conn,
180 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub, 102 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub,
@@ -681,88 +603,51 @@ TALER_MINT_DB_prepare (PGconn *db_conn)
681 } 603 }
682 PQclear (result); 604 PQclear (result);
683 605
684 if (GNUNET_OK != TALER_MINT_DB_prepare_deposits (db_conn)) 606 result = PQprepare (db_conn, "insert_deposit",
685 { 607 "INSERT INTO deposits ("
686 GNUNET_break (0); 608 "coin_pub,"
687 return GNUNET_SYSERR; 609 "denom_pub,"
688 } 610 "transaction_id,"
689 611 "amount_value,"
690 return GNUNET_OK; 612 "amount_fraction,"
691} 613 "amount_currency,"
692 614 "merchant_pub,"
693 615 "h_contract,"
694/** 616 "h_wire,"
695 * Roll back the current transaction of a database connection. 617 "coin_sig,"
696 * 618 "wire"
697 * @param db_conn the database connection 619 ") VALUES ("
698 * @return GNUNET_OK on success 620 "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11"
699 */ 621 ")",
700int 622 11, NULL);
701TALER_MINT_DB_rollback (PGconn *db_conn) 623 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
702{
703 PGresult *result;
704
705 result = PQexec(db_conn, "ROLLBACK");
706 if (PGRES_COMMAND_OK != PQresultStatus (result))
707 {
708 PQclear (result);
709 GNUNET_break (0);
710 return GNUNET_SYSERR;
711 }
712
713 PQclear (result); 624 PQclear (result);
714 return GNUNET_OK;
715}
716
717
718/**
719 * Roll back the current transaction of a database connection.
720 *
721 * @param db_conn the database connection
722 * @return GNUNET_OK on success
723 */
724int
725TALER_MINT_DB_commit (PGconn *db_conn)
726{
727 PGresult *result;
728
729 result = PQexec(db_conn, "COMMIT");
730 if (PGRES_COMMAND_OK != PQresultStatus (result))
731 {
732 PQclear (result);
733 GNUNET_break (0);
734 return GNUNET_SYSERR;
735 }
736 625
626 result = PQprepare (db_conn, "get_deposit",
627 "SELECT "
628 "coin_pub,"
629 "denom_pub,"
630 "transaction_id,"
631 "amount_value,"
632 "amount_fraction,"
633 "amount_currency,"
634 "merchant_pub,"
635 "h_contract,"
636 "h_wire,"
637 "coin_sig"
638 " FROM deposits WHERE ("
639 "coin_pub = $1"
640 ")",
641 1, NULL);
642 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
737 PQclear (result); 643 PQclear (result);
738 return GNUNET_OK;
739}
740 644
645 return GNUNET_OK;
741 646
742/** 647 EXITIF_exit:
743 * Start a transaction. 648 break_db_err (result);
744 *
745 * @param db_conn the database connection
746 * @return GNUNET_OK on success
747 */
748int
749TALER_MINT_DB_transaction (PGconn *db_conn)
750{
751 PGresult *result;
752
753 result = PQexec(db_conn, "BEGIN");
754 if (PGRES_COMMAND_OK != PQresultStatus (result))
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757 "Can't start transaction: %s\n",
758 PQresultErrorMessage (result));
759 PQclear (result);
760 GNUNET_break (0);
761 return GNUNET_SYSERR;
762 }
763
764 PQclear (result); 649 PQclear (result);
765 return GNUNET_OK; 650 return GNUNET_SYSERR;
766} 651}
767 652
768 653
@@ -1495,91 +1380,6 @@ TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn,
1495} 1380}
1496 1381
1497 1382
1498
1499int
1500TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
1501 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1502 uint16_t oldcoin_index,
1503 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
1504 const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub)
1505{
1506 uint16_t oldcoin_index_nbo = htons (oldcoin_index);
1507 char *buf;
1508 size_t buf_size;
1509 PGresult *result;
1510
1511 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub,
1512 &buf);
1513 {
1514 struct TALER_DB_QueryParam params[] = {
1515 TALER_DB_QUERY_PARAM_PTR(session_pub),
1516 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1517 TALER_DB_QUERY_PARAM_PTR(coin_pub),
1518 TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size),
1519 TALER_DB_QUERY_PARAM_END
1520 };
1521 result = TALER_DB_exec_prepared (db_conn, "insert_refresh_melt", params);
1522 }
1523 GNUNET_free (buf);
1524 if (PGRES_COMMAND_OK != PQresultStatus (result))
1525 {
1526 break_db_err (result);
1527 PQclear (result);
1528 return GNUNET_SYSERR;
1529 }
1530 PQclear (result);
1531 return GNUNET_OK;
1532}
1533
1534
1535
1536int
1537TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
1538 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1539 uint16_t oldcoin_index,
1540 struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub)
1541{
1542 uint16_t oldcoin_index_nbo = htons (oldcoin_index);
1543 struct TALER_DB_QueryParam params[] = {
1544 TALER_DB_QUERY_PARAM_PTR(session_pub),
1545 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1546 TALER_DB_QUERY_PARAM_END
1547 };
1548
1549 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_melt", params);
1550
1551 if (PGRES_TUPLES_OK != PQresultStatus (result))
1552 {
1553 break_db_err (result);
1554 PQclear (result);
1555 return GNUNET_SYSERR;
1556 }
1557
1558 if (0 == PQntuples (result))
1559 {
1560 PQclear (result);
1561 return GNUNET_NO;
1562 }
1563
1564 GNUNET_assert (1 == PQntuples (result));
1565
1566 struct TALER_DB_ResultSpec rs[] = {
1567 TALER_DB_RESULT_SPEC("coin_pub", coin_pub),
1568 TALER_DB_RESULT_SPEC_END
1569 };
1570
1571 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1572 {
1573 PQclear (result);
1574 GNUNET_break (0);
1575 return GNUNET_SYSERR;
1576 }
1577
1578 PQclear (result);
1579 return GNUNET_OK;
1580}
1581
1582
1583int 1383int
1584TALER_db_get_link (PGconn *db_conn, 1384TALER_db_get_link (PGconn *db_conn,
1585 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, 1385 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
@@ -1744,319 +1544,491 @@ TALER_db_get_transfer (PGconn *db_conn,
1744} 1544}
1745 1545
1746 1546
1547
1548
1549
1550// Chaos
1551////////////////////////////////////////////////////////////////
1552// Order
1553
1554
1555
1556
1557
1558
1559/**
1560 * Close thread-local database connection when a thread is destroyed.
1561 *
1562 * @param closure we get from pthreads (the db handle)
1563 */
1564static void
1565db_conn_destroy (void *cls)
1566{
1567 PGconn *db_conn = cls;
1568 if (NULL != db_conn)
1569 PQfinish (db_conn);
1570}
1571
1572
1573/**
1574 * Initialize database subsystem.
1575 *
1576 * @param connection_cfg configuration to use to talk to DB
1577 * @return #GNUNET_OK on success
1578 */
1747int 1579int
1748TALER_MINT_DB_init_deposits (PGconn *conn, int tmp) 1580TALER_MINT_DB_init (const char *connection_cfg)
1749{ 1581{
1750 const char *tmp_str = (1 == tmp) ? "TEMPORARY" : ""; 1582 if (0 != pthread_key_create (&db_conn_threadlocal,
1751 char *sql; 1583 &db_conn_destroy))
1752 PGresult *res; 1584 {
1753 int ret; 1585 fprintf (stderr,
1586 "Can't create pthread key.\n");
1587 return GNUNET_SYSERR;
1588 }
1589 TALER_MINT_db_connection_cfg_str = GNUNET_strdup (connection_cfg);
1590 return GNUNET_OK;
1591}
1592
1593
1594/**
1595 * Get the thread-local database-handle.
1596 * Connect to the db if the connection does not exist yet.
1597 *
1598 * @return the database connection, or NULL on error
1599 */
1600PGconn *
1601TALER_MINT_DB_get_connection (void)
1602{
1603 PGconn *db_conn;
1604
1605 if (NULL != (db_conn = pthread_getspecific (db_conn_threadlocal)))
1606 return db_conn;
1607
1608 db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str);
1609
1610 if (CONNECTION_OK != PQstatus (db_conn))
1611 {
1612 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1613 "db connection failed: %s\n",
1614 PQerrorMessage (db_conn));
1615 GNUNET_break (0);
1616 return NULL;
1617 }
1754 1618
1755 res = NULL; 1619 if (GNUNET_OK != TALER_MINT_DB_prepare (db_conn))
1756 (void) GNUNET_asprintf (&sql, 1620 {
1757 "CREATE %1$s TABLE IF NOT EXISTS deposits (" 1621 GNUNET_break (0);
1758 " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)" 1622 return NULL;
1759 ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)"
1760 ",transaction_id INT8 NOT NULL"
1761 ",amount_value INT4 NOT NULL"
1762 ",amount_fraction INT4 NOT NULL"
1763 ",amount_currency VARCHAR(4) NOT NULL"
1764 ",merchant_pub BYTEA NOT NULL"
1765 ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)"
1766 ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)"
1767 ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)"
1768 ",wire TEXT NOT NULL"
1769 ")",
1770 tmp_str);
1771 res = PQexec (conn, sql);
1772 GNUNET_free (sql);
1773 if (PGRES_COMMAND_OK != PQresultStatus (res))
1774 {
1775 break_db_err (res);
1776 ret = GNUNET_SYSERR;
1777 } 1623 }
1778 else 1624 if (0 != pthread_setspecific (db_conn_threadlocal,
1779 ret = GNUNET_OK; 1625 db_conn))
1780 PQclear (res); 1626 {
1781 return ret; 1627 GNUNET_break (0);
1628 return NULL;
1629 }
1630 return db_conn;
1782} 1631}
1783 1632
1633
1634/**
1635 * Start a transaction.
1636 *
1637 * @param db_conn the database connection
1638 * @return #GNUNET_OK on success
1639 */
1784int 1640int
1785TALER_MINT_DB_prepare_deposits (PGconn *db_conn) 1641TALER_MINT_DB_transaction (PGconn *db_conn)
1786{ 1642{
1787 PGresult *result; 1643 PGresult *result;
1788 1644
1789 result = PQprepare (db_conn, "insert_deposit", 1645 result = PQexec(db_conn, "BEGIN");
1790 "INSERT INTO deposits (" 1646 if (PGRES_COMMAND_OK != PQresultStatus (result))
1791 "coin_pub," 1647 {
1792 "denom_pub," 1648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1793 "transaction_id," 1649 "Can't start transaction: %s\n",
1794 "amount_value," 1650 PQresultErrorMessage (result));
1795 "amount_fraction," 1651 PQclear (result);
1796 "amount_currency," 1652 GNUNET_break (0);
1797 "merchant_pub," 1653 return GNUNET_SYSERR;
1798 "h_contract," 1654 }
1799 "h_wire,"
1800 "coin_sig,"
1801 "wire"
1802 ") VALUES ("
1803 "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11"
1804 ")",
1805 11, NULL);
1806 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
1807 PQclear (result);
1808 1655
1809 result = PQprepare (db_conn, "get_deposit",
1810 "SELECT "
1811 "coin_pub,"
1812 "denom_pub,"
1813 "transaction_id,"
1814 "amount_value,"
1815 "amount_fraction,"
1816 "amount_currency,"
1817 "merchant_pub,"
1818 "h_contract,"
1819 "h_wire,"
1820 "coin_sig"
1821 " FROM deposits WHERE ("
1822 "coin_pub = $1"
1823 ")",
1824 1, NULL);
1825 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
1826 PQclear (result); 1656 PQclear (result);
1827
1828 return GNUNET_OK; 1657 return GNUNET_OK;
1658}
1659
1660
1661/**
1662 * Roll back the current transaction of a database connection.
1663 *
1664 * @param db_conn the database connection
1665 * @return #GNUNET_OK on success
1666 */
1667int
1668TALER_MINT_DB_rollback (PGconn *db_conn)
1669{
1670 PGresult *result;
1671
1672 result = PQexec(db_conn,
1673 "ROLLBACK");
1674 if (PGRES_COMMAND_OK != PQresultStatus (result))
1675 {
1676 PQclear (result);
1677 GNUNET_break (0);
1678 return GNUNET_SYSERR;
1679 }
1829 1680
1830 EXITIF_exit:
1831 break_db_err (result);
1832 PQclear (result); 1681 PQclear (result);
1833 return GNUNET_SYSERR; 1682 return GNUNET_OK;
1834} 1683}
1835 1684
1836 1685
1686/**
1687 * Commit the current transaction of a database connection.
1688 *
1689 * @param db_conn the database connection
1690 * @return #GNUNET_OK on success
1691 */
1837int 1692int
1838TALER_MINT_DB_insert_deposit (PGconn *db_conn, 1693TALER_MINT_DB_commit (PGconn *db_conn)
1839 const struct Deposit *deposit)
1840{ 1694{
1841 struct TALER_DB_QueryParam params[]= {
1842 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub),
1843 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_pub), // FIXME!
1844 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_sig), // FIXME!
1845 TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id),
1846 TALER_DB_QUERY_PARAM_PTR (&deposit->purpose), // FIXME: enum Ok here?
1847 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.value),
1848 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.fraction),
1849 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->amount.currency,
1850 strlen (deposit->amount.currency)),
1851 TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub),
1852 TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract),
1853 TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire),
1854 TALER_DB_QUERY_PARAM_PTR (&deposit->csig),
1855 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->wire,
1856 strlen ("FIXME")), // FIXME! json!
1857 TALER_DB_QUERY_PARAM_END
1858 };
1859 PGresult *result; 1695 PGresult *result;
1860 1696
1861 result = TALER_DB_exec_prepared (db_conn, "insert_deposit", params); 1697 result = PQexec(db_conn,
1698 "COMMIT");
1862 if (PGRES_COMMAND_OK != PQresultStatus (result)) 1699 if (PGRES_COMMAND_OK != PQresultStatus (result))
1863 { 1700 {
1864 break_db_err (result);
1865 PQclear (result); 1701 PQclear (result);
1702 GNUNET_break (0);
1866 return GNUNET_SYSERR; 1703 return GNUNET_SYSERR;
1867 } 1704 }
1705
1868 PQclear (result); 1706 PQclear (result);
1869 return GNUNET_OK; 1707 return GNUNET_OK;
1870} 1708}
1871 1709
1872 1710
1711/**
1712 * Locate the response for a /withdraw request under the
1713 * key of the hash of the blinded message.
1714 *
1715 * @param db_conn database connection to use
1716 * @param h_blind hash of the blinded message
1717 * @param collectable corresponding collectable coin (blind signature)
1718 * if a coin is found
1719 * @return #GNUNET_SYSERR on internal error
1720 * #GNUNET_NO if the collectable was not found
1721 * #GNUNET_YES on success
1722 */
1873int 1723int
1874TALER_MINT_DB_get_deposit (PGconn *db_conn, 1724TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn,
1875 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, 1725 const struct GNUNET_HashCode *h_blind,
1876 struct Deposit *deposit) 1726 struct CollectableBlindcoin *collectable)
1877{ 1727{
1728 PGresult *result;
1878 struct TALER_DB_QueryParam params[] = { 1729 struct TALER_DB_QueryParam params[] = {
1879 TALER_DB_QUERY_PARAM_PTR (coin_pub), 1730 TALER_DB_QUERY_PARAM_PTR (h_blind),
1880 TALER_DB_QUERY_PARAM_END 1731 TALER_DB_QUERY_PARAM_END
1881 }; 1732 };
1882 PGresult *result; 1733 char *sig_buf;
1734 size_t sig_buf_size;
1883 1735
1884 memset (deposit, 0, sizeof (struct Deposit));
1885 result = TALER_DB_exec_prepared (db_conn, 1736 result = TALER_DB_exec_prepared (db_conn,
1886 "get_deposit", 1737 "get_collectable_blindcoins",
1887 params); 1738 params);
1739
1888 if (PGRES_TUPLES_OK != PQresultStatus (result)) 1740 if (PGRES_TUPLES_OK != PQresultStatus (result))
1889 { 1741 {
1890 break_db_err (result); 1742 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1891 goto EXITIF_exit; 1743 "Query failed: %s\n",
1744 PQresultErrorMessage (result));
1745 PQclear (result);
1746 return GNUNET_SYSERR;
1892 } 1747 }
1893
1894 if (0 == PQntuples (result)) 1748 if (0 == PQntuples (result))
1895 { 1749 {
1896 PQclear (result); 1750 PQclear (result);
1897 return GNUNET_NO; 1751 return GNUNET_NO;
1898 } 1752 }
1899 1753
1900 if (1 != PQntuples (result)) 1754 struct TALER_DB_ResultSpec rs[] = {
1901 { 1755 TALER_DB_RESULT_SPEC_VAR("blind_sig", &sig_buf, &sig_buf_size),
1902 GNUNET_break (0); 1756 TALER_DB_RESULT_SPEC("denom_pub", &collectable->denom_pub),
1903 goto EXITIF_exit; 1757 TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig),
1904 } 1758 TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub),
1759 TALER_DB_RESULT_SPEC_END
1760 };
1905 1761
1762 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1906 { 1763 {
1907 char *denom_sig_buf; 1764 GNUNET_break (0);
1908 size_t denom_sig_buf_size; 1765 PQclear (result);
1909 char *dk_buf; 1766 return GNUNET_SYSERR;
1910 size_t dk_buf_size;
1911
1912 struct TALER_DB_ResultSpec rs[] = {
1913 TALER_DB_RESULT_SPEC ("coin_pub", &deposit->coin.coin_pub),
1914 TALER_DB_RESULT_SPEC_VAR ("denom_pub", &dk_buf, &dk_buf_size),
1915 TALER_DB_RESULT_SPEC_VAR ("denom_sig", &denom_sig_buf, &denom_sig_buf_size),
1916 TALER_DB_RESULT_SPEC ("transaction_id", &deposit->transaction_id),
1917 TALER_DB_RESULT_SPEC ("merchant_pub", &deposit->merchant_pub),
1918 TALER_DB_RESULT_SPEC ("h_contract", &deposit->h_contract),
1919 TALER_DB_RESULT_SPEC ("h_wire", &deposit->h_wire),
1920 TALER_DB_RESULT_SPEC ("purpose", &deposit->purpose),
1921 // FIXME: many fields missing...
1922 TALER_DB_RESULT_SPEC_END
1923 };
1924 EXITIF (GNUNET_OK !=
1925 TALER_DB_extract_result (result, rs, 0));
1926 EXITIF (GNUNET_OK !=
1927 TALER_DB_extract_amount (result, 0,
1928 "amount_value",
1929 "amount_fraction",
1930 "amount_currency",
1931 &deposit->amount));
1932 deposit->coin.denom_sig
1933 = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_buf,
1934 denom_sig_buf_size);
1935 deposit->coin.denom_pub
1936 = GNUNET_CRYPTO_rsa_public_key_decode (dk_buf,
1937 dk_buf_size);
1938 } 1767 }
1939
1940 PQclear (result); 1768 PQclear (result);
1941 return GNUNET_OK; 1769 return GNUNET_OK;
1942
1943EXITIF_exit:
1944 PQclear (result);
1945 GNUNET_free_non_null (deposit);
1946 deposit = NULL;
1947 return GNUNET_SYSERR;
1948} 1770}
1949 1771
1950 1772
1951
1952/** 1773/**
1953 * Get the thread-local database-handle. 1774 * Store collectable bit coin under the corresponding
1954 * Connect to the db if the connection does not exist yet. 1775 * hash of the blinded message.
1955 * 1776 *
1956 * @param the database connection, or NULL on error 1777 * @param db_conn database connection to use
1778 * @param h_blind hash of the blinded message
1779 * @param collectable corresponding collectable coin (blind signature)
1780 * if a coin is found
1781 * @return #GNUNET_SYSERR on internal error
1782 * #GNUNET_NO if the collectable was not found
1783 * #GNUNET_YES on success
1957 */ 1784 */
1958PGconn * 1785int
1959TALER_MINT_DB_get_connection (void) 1786TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn,
1787 const struct GNUNET_HashCode *h_blind,
1788 const struct CollectableBlindcoin *collectable)
1960{ 1789{
1961 PGconn *db_conn; 1790 PGresult *result;
1791 char *sig_buf;
1792 size_t sig_buf_size;
1962 1793
1963 if (NULL != (db_conn = pthread_getspecific (db_conn_threadlocal))) 1794 sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig,
1964 return db_conn; 1795 &sig_buf);
1796 {
1797 struct TALER_DB_QueryParam params[] = {
1798 TALER_DB_QUERY_PARAM_PTR (&h_blind),
1799 TALER_DB_QUERY_PARAM_PTR_SIZED (sig_buf, sig_buf_size),
1800 TALER_DB_QUERY_PARAM_PTR (&collectable->denom_pub),
1801 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub),
1802 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig),
1803 TALER_DB_QUERY_PARAM_END
1804 };
1965 1805
1966 db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str); 1806 result = TALER_DB_exec_prepared (db_conn,
1807 "insert_collectable_blindcoins",
1808 params);
1809 if (PGRES_COMMAND_OK != PQresultStatus (result))
1810 {
1811 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1812 "Query failed: %s\n",
1813 PQresultErrorMessage (result));
1814 PQclear (result);
1815 return GNUNET_SYSERR;
1816 }
1967 1817
1968 if (CONNECTION_OK != PQstatus (db_conn)) 1818 if (0 != strcmp ("1", PQcmdTuples (result)))
1969 { 1819 {
1970 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1820 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1971 "db connection failed: %s\n", 1821 "Insert failed (updated '%s' tupes instead of '1')\n",
1972 PQerrorMessage (db_conn)); 1822 PQcmdTuples (result));
1973 GNUNET_break (0); 1823 PQclear (result);
1974 return NULL; 1824 return GNUNET_SYSERR;
1825 }
1826 PQclear (result);
1975 } 1827 }
1828 return GNUNET_OK;
1829}
1976 1830
1977 if (GNUNET_OK != TALER_MINT_DB_prepare (db_conn)) 1831
1832/**
1833 * Check if we have the specified deposit already in the database.
1834 *
1835 * @param db_conn database connection
1836 * @param deposit deposit to search for
1837 * @return #GNUNET_YES if we know this operation,
1838 * #GNUNET_NO if this deposit is unknown to us
1839 */
1840int
1841TALER_MINT_DB_have_deposit (PGconn *db_conn,
1842 const struct Deposit *deposit)
1843{
1844 struct TALER_DB_QueryParam params[] = {
1845 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), // FIXME
1846 TALER_DB_QUERY_PARAM_END
1847 };
1848 PGresult *result;
1849
1850 result = TALER_DB_exec_prepared (db_conn,
1851 "get_deposit",
1852 params);
1853 if (PGRES_TUPLES_OK !=
1854 PQresultStatus (result))
1978 { 1855 {
1979 GNUNET_break (0); 1856 break_db_err (result);
1980 return NULL; 1857 PQclear (result);
1858 return GNUNET_SYSERR;
1981 } 1859 }
1982 if (0 != pthread_setspecific (db_conn_threadlocal, db_conn)) 1860
1861 if (0 == PQntuples (result))
1983 { 1862 {
1984 GNUNET_break (0); 1863 PQclear (result);
1985 return NULL; 1864 return GNUNET_NO;
1986 } 1865 }
1987 return db_conn; 1866 return GNUNET_YES;
1988} 1867}
1989 1868
1990 1869
1991/** 1870/**
1992 * Close thread-local database connection when a thread is destroyed. 1871 * Insert information about deposited coin into the
1872 * database.
1993 * 1873 *
1994 * @param closure we get from pthreads (the db handle) 1874 * @param db_conn connection to the database
1875 * @param deposit deposit information to store
1876 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1995 */ 1877 */
1996static void 1878int
1997db_conn_destroy (void *cls) 1879TALER_MINT_DB_insert_deposit (PGconn *db_conn,
1880 const struct Deposit *deposit)
1998{ 1881{
1999 PGconn *db_conn = cls; 1882 struct TALER_DB_QueryParam params[]= {
2000 if (NULL != db_conn) 1883 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub),
2001 PQfinish (db_conn); 1884 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_pub), // FIXME!
1885 TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_sig), // FIXME!
1886 TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id),
1887 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.value),
1888 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.fraction),
1889 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->amount.currency,
1890 strlen (deposit->amount.currency)),
1891 TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub),
1892 TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract),
1893 TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire),
1894 TALER_DB_QUERY_PARAM_PTR (&deposit->csig),
1895 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->wire,
1896 strlen ("FIXME")), // FIXME! json!
1897 TALER_DB_QUERY_PARAM_END
1898 };
1899 PGresult *result;
1900
1901 result = TALER_DB_exec_prepared (db_conn, "insert_deposit", params);
1902 if (PGRES_COMMAND_OK != PQresultStatus (result))
1903 {
1904 break_db_err (result);
1905 PQclear (result);
1906 return GNUNET_SYSERR;
1907 }
1908 PQclear (result);
1909 return GNUNET_OK;
2002} 1910}
2003 1911
2004 1912
2005/** 1913/**
2006 * Initialize database subsystem. 1914 * Test if the given /refresh/melt request is known to us.
2007 * 1915 *
2008 * @param connection_cfg configuration to use to talk to DB 1916 * @param db_conn database connection
2009 * @return #GNUNET_OK on success 1917 * @param melt melt operation
1918 * @return #GNUNET_YES if known,
1919 * #GNUENT_NO if not,
1920 * #GNUNET_SYSERR on internal error
2010 */ 1921 */
2011int 1922int
2012TALER_MINT_DB_init (const char *connection_cfg) 1923TALER_MINT_DB_have_refresh_melt (PGconn *db_conn,
1924 const struct RefreshMelt *melt)
2013{ 1925{
1926 uint16_t oldcoin_index_nbo = htons (melt->oldcoin_index);
1927 struct TALER_DB_QueryParam params[] = {
1928 TALER_DB_QUERY_PARAM_PTR(&melt->session_pub),
1929 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1930 TALER_DB_QUERY_PARAM_END
1931 };
2014 1932
2015 if (0 != pthread_key_create (&db_conn_threadlocal, &db_conn_destroy)) 1933 PGresult *result = TALER_DB_exec_prepared (db_conn,
1934 "get_refresh_melt",
1935 params);
1936 if (PGRES_TUPLES_OK != PQresultStatus (result))
2016 { 1937 {
2017 fprintf (stderr, 1938 break_db_err (result);
2018 "Can't create pthread key.\n"); 1939 PQclear (result);
2019 return GNUNET_SYSERR; 1940 return GNUNET_SYSERR;
2020 } 1941 }
2021 TALER_MINT_db_connection_cfg_str = GNUNET_strdup (connection_cfg); 1942
2022 return GNUNET_OK; 1943 if (0 == PQntuples (result))
1944 {
1945 PQclear (result);
1946 return GNUNET_NO;
1947 }
1948 GNUNET_break (1 == PQntuples (result));
1949 PQclear (result);
1950 return GNUNET_YES;
2023} 1951}
2024 1952
2025 1953
1954
1955/**
1956 * Store the given /refresh/melt request in the database.
1957 *
1958 * @param db_conn database connection
1959 * @param melt melt operation
1960 * @return #GNUNET_OK on success
1961 * #GNUNET_SYSERR on internal error
1962 */
2026int 1963int
2027TALER_TALER_DB_extract_amount_nbo (PGresult *result, 1964TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
2028 unsigned int row, 1965 const struct RefreshMelt *melt)
2029 int indices[3],
2030 struct TALER_AmountNBO *denom_nbo)
2031{ 1966{
2032 if ((indices[0] < 0) || (indices[1] < 0) || (indices[2] < 0)) 1967 uint16_t oldcoin_index_nbo = htons (melt->oldcoin_index);
2033 return GNUNET_NO; 1968 char *buf;
2034 if (sizeof (uint32_t) != PQgetlength (result, row, indices[0])) 1969 size_t buf_size;
2035 return GNUNET_SYSERR; 1970 PGresult *result;
2036 if (sizeof (uint32_t) != PQgetlength (result, row, indices[1])) 1971
2037 return GNUNET_SYSERR; 1972 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub,
2038 if (PQgetlength (result, row, indices[2]) > TALER_CURRENCY_LEN) 1973 &buf);
1974 {
1975 struct TALER_DB_QueryParam params[] = {
1976 TALER_DB_QUERY_PARAM_PTR(&melt->session_pub),
1977 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1978 TALER_DB_QUERY_PARAM_PTR(&melt->coin.coin_pub),
1979 TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size),
1980 TALER_DB_QUERY_PARAM_END
1981 };
1982 result = TALER_DB_exec_prepared (db_conn, "insert_refresh_melt", params);
1983 }
1984 GNUNET_free (buf);
1985 if (PGRES_COMMAND_OK != PQresultStatus (result))
1986 {
1987 break_db_err (result);
1988 PQclear (result);
2039 return GNUNET_SYSERR; 1989 return GNUNET_SYSERR;
2040 denom_nbo->value = *(uint32_t *) PQgetvalue (result, row, indices[0]); 1990 }
2041 denom_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, indices[1]); 1991 PQclear (result);
2042 memset (denom_nbo->currency, 0, TALER_CURRENCY_LEN);
2043 memcpy (denom_nbo->currency, PQgetvalue (result, row, indices[2]), PQgetlength (result, row, indices[2]));
2044 return GNUNET_OK; 1992 return GNUNET_OK;
2045} 1993}
2046 1994
2047 1995
1996/**
1997 * Get information about melted coin details from the database.
1998 *
1999 * @param db_conn database connection
2000 * @param session session key of the melt operation
2001 * @param oldcoin_index index of the coin to retrieve
2002 * @param melt melt data to fill in
2003 * @return #GNUNET_OK on success
2004 * #GNUNET_SYSERR on internal error
2005 */
2048int 2006int
2049TALER_TALER_DB_extract_amount (PGresult *result, 2007TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
2050 unsigned int row, 2008 const struct GNUNET_CRYPTO_EddsaPublicKey *session,
2051 int indices[3], 2009 uint16_t oldcoin_index,
2052 struct TALER_Amount *denom) 2010 struct RefreshMelt *melt)
2053{ 2011{
2054 struct TALER_AmountNBO denom_nbo; 2012 GNUNET_break (0);
2055 int res; 2013 return GNUNET_SYSERR;
2014}
2056 2015
2057 res = TALER_TALER_DB_extract_amount_nbo (result, row, indices, &denom_nbo); 2016
2058 if (GNUNET_OK != res) 2017/**
2059 return res; 2018 * Compile a list of all (historic) transactions performed
2060 *denom = TALER_amount_ntoh (denom_nbo); 2019 * with the given coin (/refresh/melt and /deposit operations).
2061 return GNUNET_OK; 2020 *
2021 * @param db_conn database connection
2022 * @param coin_pub coin to investigate
2023 * @return list of transactions, NULL if coin is fresh
2024 */
2025struct TALER_MINT_DB_TransactionList *
2026TALER_MINT_DB_get_coin_transactions (PGconn *db_conn,
2027 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub)
2028{
2029 GNUNET_break (0); // FIXME: implement!
2030 return NULL;
2062} 2031}
2032
2033
2034/* end of mint_db.c */
diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h
index b38b82b94..6e1fb4753 100644
--- a/src/mint/mint_db.h
+++ b/src/mint/mint_db.h
@@ -30,57 +30,12 @@
30#include "mint.h" 30#include "mint.h"
31 31
32 32
33int
34TALER_MINT_DB_prepare (PGconn *db_conn);
35
36 33
37/** 34/**
38 * Locate the response for a /withdraw request under the 35 * FIXME.
39 * key of the hash of the blinded message.
40 *
41 * @param db_conn database connection to use
42 * @param h_blind hash of the blinded message
43 * @param collectable corresponding collectable coin (blind signature)
44 * if a coin is found
45 * @return #GNUNET_SYSERR on internal error
46 * #GNUNET_NO if the collectable was not found
47 * #GNUNET_YES on success
48 */ 36 */
49int 37int
50TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, 38TALER_MINT_DB_prepare (PGconn *db_conn);
51 const struct GNUNET_HashCode *h_blind,
52 struct CollectableBlindcoin *collectable);
53
54
55/**
56 * Store collectable bit coin under the corresponding
57 * hash of the blinded message.
58 *
59 * @param db_conn database connection to use
60 * @param h_blind hash of the blinded message
61 * @param collectable corresponding collectable coin (blind signature)
62 * if a coin is found
63 * @return #GNUNET_SYSERR on internal error
64 * #GNUNET_NO if the collectable was not found
65 * #GNUNET_YES on success
66 */
67int
68TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn,
69 const struct GNUNET_HashCode *h_blind,
70 const struct CollectableBlindcoin *collectable);
71
72
73int
74TALER_MINT_DB_rollback (PGconn *db_conn);
75
76
77int
78TALER_MINT_DB_transaction (PGconn *db_conn);
79
80
81int
82TALER_MINT_DB_commit (PGconn *db_conn);
83
84 39
85 40
86/** 41/**
@@ -151,6 +106,9 @@ TALER_MINT_DB_update_reserve (PGconn *db_conn,
151 106
152 107
153 108
109
110
111
154int 112int
155TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, 113TALER_MINT_DB_insert_refresh_order (PGconn *db_conn,
156 uint16_t newcoin_index, 114 uint16_t newcoin_index,
@@ -163,8 +121,6 @@ TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
163 struct RefreshSession *r_session); 121 struct RefreshSession *r_session);
164 122
165 123
166
167
168/** 124/**
169 * FIXME 125 * FIXME
170 */ 126 */
@@ -201,10 +157,6 @@ TALER_MINT_DB_insert_known_coin (PGconn *db_conn,
201 const struct KnownCoin *known_coin); 157 const struct KnownCoin *known_coin);
202 158
203 159
204
205
206
207
208int 160int
209TALER_MINT_DB_create_refresh_session (PGconn *db_conn, 161TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
210 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); 162 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);
@@ -276,19 +228,6 @@ TALER_MINT_DB_set_reveal_ok (PGconn *db_conn,
276 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); 228 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);
277 229
278 230
279int
280TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
281 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
282 uint16_t oldcoin_index,
283 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
284 const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub);
285
286
287int
288TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
289 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
290 uint16_t oldcoin_index,
291 struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub);
292 231
293 232
294/** 233/**
@@ -320,13 +259,139 @@ TALER_db_get_transfer (PGconn *db_conn,
320 struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, 259 struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub,
321 struct GNUNET_HashCode *shared_secret_enc); 260 struct GNUNET_HashCode *shared_secret_enc);
322 261
262
323int 263int
324TALER_MINT_DB_init_deposits (PGconn *db_conn, int temporary); 264TALER_TALER_DB_extract_amount (PGresult *result,
265 unsigned int row,
266 int indices[3],
267 struct TALER_Amount *denom);
268
269int
270TALER_TALER_DB_extract_amount_nbo (PGresult *result,
271 unsigned int row,
272 int indices[3],
273 struct TALER_AmountNBO *denom_nbo);
325 274
326 275
276
277
278
279// Chaos
280////////////////////////////////////////////////////////////////
281// Order
282
283
284
285/**
286 * Initialize database subsystem.
287 */
288int
289TALER_MINT_DB_init (const char *connection_cfg);
290
291
292/**
293 * Get the thread-local database-handle.
294 * Connect to the db if the connection does not exist yet.
295 *
296 * @param the database connection, or NULL on error
297 */
298PGconn *
299TALER_MINT_DB_get_connection (void);
300
301
302/**
303 * Start a transaction.
304 *
305 * @return #GNUNET_OK on success
306 */
307int
308TALER_MINT_DB_transaction (PGconn *db_conn);
309
310
311/**
312 * Commit a transaction.
313 *
314 * @return #GNUNET_OK on success
315 */
316int
317TALER_MINT_DB_commit (PGconn *db_conn);
318
319
320/**
321 * Abort/rollback a transaction.
322 *
323 * @return #GNUNET_OK on success
324 */
327int 325int
328TALER_MINT_DB_prepare_deposits (PGconn *db_conn); 326TALER_MINT_DB_rollback (PGconn *db_conn);
327
328
329
330/**
331 * Information we keep for a withdrawn coin to reproduce
332 * the /withdraw operation if needed, and to have proof
333 * that a reserve was drained by this amount.
334 */
335struct CollectableBlindcoin
336{
337
338 /**
339 * Our signature over the (blinded) coin.
340 */
341 struct GNUNET_CRYPTO_rsa_Signature *sig;
342
343 /**
344 * Denomination key (which coin was generated).
345 */
346 struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub;
347
348 /**
349 * Public key of the reserve that was drained.
350 */
351 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
329 352
353 /**
354 * Signature confirming the withdrawl, matching @e reserve_pub,
355 * @e denom_pub and @e h_blind.
356 */
357 struct GNUNET_CRYPTO_EddsaSignature reserve_sig;
358};
359
360
361/**
362 * Locate the response for a /withdraw request under the
363 * key of the hash of the blinded message.
364 *
365 * @param db_conn database connection to use
366 * @param h_blind hash of the blinded message
367 * @param collectable corresponding collectable coin (blind signature)
368 * if a coin is found
369 * @return #GNUNET_SYSERR on internal error
370 * #GNUNET_NO if the collectable was not found
371 * #GNUNET_YES on success
372 */
373int
374TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn,
375 const struct GNUNET_HashCode *h_blind,
376 struct CollectableBlindcoin *collectable);
377
378
379/**
380 * Store collectable bit coin under the corresponding
381 * hash of the blinded message.
382 *
383 * @param db_conn database connection to use
384 * @param h_blind hash of the blinded message
385 * @param collectable corresponding collectable coin (blind signature)
386 * if a coin is found
387 * @return #GNUNET_SYSERR on internal error
388 * #GNUNET_NO if the collectable was not found
389 * #GNUNET_YES on success
390 */
391int
392TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn,
393 const struct GNUNET_HashCode *h_blind,
394 const struct CollectableBlindcoin *collectable);
330 395
331 396
332/** 397/**
@@ -384,59 +449,253 @@ struct Deposit
384 */ 449 */
385 struct TALER_Amount amount; 450 struct TALER_Amount amount;
386 451
387 /** 452};
388 * Type of the deposit (also purpose of the signature). Either
389 * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT.
390 */
391 uint32_t purpose; // FIXME: bad type, use ENUM!
392 453
393 454
394}; 455/**
456 * Check if we have the specified deposit already in the database.
457 *
458 * @param db_conn database connection
459 * @param deposit deposit to search for
460 * @return #GNUNET_YES if we know this operation,
461 * #GNUNET_NO if this deposit is unknown to us,
462 * #GNUNET_SYSERR on internal error
463 */
464int
465TALER_MINT_DB_have_deposit (PGconn *db_conn,
466 const struct Deposit *deposit);
395 467
396 468
469/**
470 * Insert information about deposited coin into the
471 * database.
472 *
473 * @param db_conn connection to the database
474 * @param deposit deposit information to store
475 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
476 */
397int 477int
398TALER_MINT_DB_insert_deposit (PGconn *db_conn, 478TALER_MINT_DB_insert_deposit (PGconn *db_conn,
399 const struct Deposit *deposit); 479 const struct Deposit *deposit);
400 480
401 481
402// FIXME: with fractional deposits, we need more than 482/**
403// just the coin key to lookup deposits... 483 * Specification for a /refresh/melt operation.
404int 484 */
405TALER_MINT_DB_get_deposit (PGconn *db_conn, 485struct RefreshMelt
406 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, 486{
407 struct Deposit *r_deposit); 487 /**
488 * Information about the coin that is being melted.
489 */
490 struct TALER_CoinPublicInfo coin;
408 491
492 /**
493 * Public key of the melting session.
494 */
495 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
409 496
497 /**
498 * Signature over the melting operation.
499 */
500 struct GNUNET_CRYPTO_EcdsaSignature coin_sig;
410 501
502 /**
503 * How much value is being melted?
504 */
505 struct TALER_Amount amount;
506
507 /**
508 * What is the index of this coin in the melting session?
509 */
510 uint16_t oldcoin_index;
511
512};
411 513
412 514
413/** 515/**
414 * Get the thread-local database-handle. 516 * Test if the given /refresh/melt request is known to us.
415 * Connect to the db if the connection does not exist yet.
416 * 517 *
417 * @param the database connection, or NULL on error 518 * @param db_conn database connection
519 * @param melt melt operation
520 * @return #GNUNET_YES if known,
521 * #GNUENT_NO if not,
522 * #GNUNET_SYSERR on internal error
418 */ 523 */
419PGconn * 524int
420TALER_MINT_DB_get_connection (void); 525TALER_MINT_DB_have_refresh_melt (PGconn *db_conn,
526 const struct RefreshMelt *melt);
421 527
422 528
529/**
530 * Store the given /refresh/melt request in the database.
531 *
532 * @param db_conn database connection
533 * @param melt melt operation
534 * @return #GNUNET_OK on success
535 * #GNUNET_SYSERR on internal error
536 */
423int 537int
424TALER_MINT_DB_init (const char *connection_cfg); 538TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
539 const struct RefreshMelt *melt);
540
541
542/**
543 * Get information about melted coin details from the database.
544 *
545 * @param db_conn database connection
546 * @param session session key of the melt operation
547 * @param oldcoin_index index of the coin to retrieve
548 * @param melt melt data to fill in
549 * @return #GNUNET_OK on success
550 * #GNUNET_SYSERR on internal error
551 */
552int
553TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
554 const struct GNUNET_CRYPTO_EddsaPublicKey *session,
555 uint16_t oldcoin_index,
556 struct RefreshMelt *melt);
557
558
559/**
560 * Specification for a /lock operation.
561 */
562struct Lock
563{
564 /**
565 * Information about the coin that is being melted.
566 */
567 struct TALER_CoinPublicInfo coin;
425 568
569 /**
570 * Signature over the melting operation.
571 */
572 const struct GNUNET_CRYPTO_EcdsaSignature coin_sig;
426 573
574 /**
575 * How much value is being melted?
576 */
577 struct TALER_Amount amount;
578
579 // FIXME: more needed...
580};
427 581
428 582
583/**
584 * Test if the given /lock request is known to us.
585 *
586 * @param db_conn database connection
587 * @param lock lock operation
588 * @return #GNUNET_YES if known,
589 * #GNUENT_NO if not,
590 * #GNUNET_SYSERR on internal error
591 */
429int 592int
430TALER_TALER_DB_extract_amount (PGresult *result, 593TALER_MINT_DB_have_lock (PGconn *db_conn,
431 unsigned int row, 594 const struct Lock *lock);
432 int indices[3],
433 struct TALER_Amount *denom);
434 595
596
597/**
598 * Store the given /lock request in the database.
599 *
600 * @param db_conn database connection
601 * @param lock lock operation
602 * @return #GNUNET_OK on success
603 * #GNUNET_SYSERR on internal error
604 */
435int 605int
436TALER_TALER_DB_extract_amount_nbo (PGresult *result, 606TALER_MINT_DB_insert_lock (PGconn *db_conn,
437 unsigned int row, 607 const struct Lock *lock);
438 int indices[3], 608
439 struct TALER_AmountNBO *denom_nbo); 609
610/**
611 * Enumeration to classify the different types of transactions
612 * that can be done with a coin.
613 */
614enum TALER_MINT_DB_TransactionType
615{
616 /**
617 * /deposit operation.
618 */
619 TALER_MINT_DB_TT_DEPOSIT = 0,
620
621 /**
622 * /refresh/melt operation.
623 */
624 TALER_MINT_DB_TT_REFRESH_MELT = 1,
625
626 /**
627 * /lock operation.
628 */
629 TALER_MINT_DB_TT_LOCK = 2
630};
631
632
633/**
634 * List of transactions we performed for a particular coin.
635 */
636struct TALER_MINT_DB_TransactionList
637{
638
639 /**
640 * Next pointer in the NULL-terminated linked list.
641 */
642 struct TALER_MINT_DB_TransactionList *next;
643
644 /**
645 * Type of the transaction, determines what is stored in @e details.
646 */
647 enum TALER_MINT_DB_TransactionType type;
648
649 /**
650 * Details about the transaction, depending on @e type.
651 */
652 union
653 {
654
655 /**
656 * Details if transaction was a /deposit operation.
657 */
658 struct Deposit *deposit;
659
660 /**
661 * Details if transaction was a /refresh/melt operation.
662 */
663 struct RefreshMelt *melt;
664
665 /**
666 * Details if transaction was a /lock operation.
667 */
668 struct Lock *lock;
669
670 } details;
671
672};
673
674
675/**
676 * Compile a list of all (historic) transactions performed
677 * with the given coin (/refresh/melt and /deposit operations).
678 *
679 * @param db_conn database connection
680 * @param coin_pub coin to investigate
681 * @return list of transactions, NULL if coin is fresh
682 */
683struct TALER_MINT_DB_TransactionList *
684TALER_MINT_DB_get_coin_transactions (PGconn *db_conn,
685 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub);
686
687
688/**
689 * Free linked list of transactions.
690 *
691 * @param list list to free
692 */
693void
694TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list);
695
696
697
698
440 699
441 700
442#endif /* _NEURO_MINT_DB_H */ 701#endif /* _NEURO_MINT_DB_H */
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
index f64e1508d..6dffbcd63 100644
--- a/src/mint/taler-mint-httpd_db.c
+++ b/src/mint/taler-mint-httpd_db.c
@@ -55,31 +55,35 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
55 const struct Deposit *deposit) 55 const struct Deposit *deposit)
56{ 56{
57 PGconn *db_conn; 57 PGconn *db_conn;
58 struct Deposit existing_deposit; 58 struct TALER_MINT_DB_TransactionList *tl;
59 int res;
60 59
61 if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) 60 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
62 { 61 {
63 GNUNET_break (0); 62 GNUNET_break (0);
64 return TALER_MINT_reply_internal_db_error (connection); 63 return TALER_MINT_reply_internal_db_error (connection);
65 } 64 }
66 res = TALER_MINT_DB_get_deposit (db_conn, 65 if (GNUNET_YES ==
67 &deposit->coin.coin_pub, 66 TALER_MINT_DB_have_deposit (db_conn,
68 &existing_deposit); 67 deposit))
69 if (GNUNET_YES == res) 68 {
69 return TALER_MINT_reply_deposit_success (connection,
70 &deposit->coin.coin_pub,
71 &deposit->h_wire,
72 &deposit->h_contract,
73 deposit->transaction_id,
74 &deposit->merchant_pub,
75 &deposit->amount);
76 }
77 if (GNUNET_OK !=
78 TALER_MINT_DB_transaction (db_conn))
79 {
80 GNUNET_break (0);
81 return TALER_MINT_reply_internal_db_error (connection);
82 }
83 tl = TALER_MINT_DB_get_coin_transactions (db_conn,
84 &deposit->coin.coin_pub);
85 if (NULL != tl)
70 { 86 {
71 // FIXME: memory leak
72 // FIXME: memcmp will not actually work here
73 if (0 == memcmp (&existing_deposit,
74 deposit,
75 sizeof (struct Deposit)))
76 return TALER_MINT_reply_deposit_success (connection,
77 &deposit->coin.coin_pub,
78 &deposit->h_wire,
79 &deposit->h_contract,
80 deposit->transaction_id,
81 &deposit->merchant_pub,
82 &deposit->amount);
83 // FIXME: in the future, check if there's enough credits 87 // FIXME: in the future, check if there's enough credits
84 // left on the coin. For now: refuse 88 // left on the coin. For now: refuse
85 // FIXME: return more information here 89 // FIXME: return more information here
@@ -87,15 +91,9 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
87 MHD_HTTP_FORBIDDEN, 91 MHD_HTTP_FORBIDDEN,
88 "{s:s}", 92 "{s:s}",
89 "error", 93 "error",
90 "double spending"); 94 "double spending");
91 } 95 }
92 96
93 if (GNUNET_SYSERR == res)
94 {
95 GNUNET_break (0);
96 /* FIXME: return error message to client via MHD! */
97 return MHD_NO;
98 }
99 97
100 { 98 {
101 struct KnownCoin known_coin; 99 struct KnownCoin known_coin;
@@ -153,6 +151,14 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
153} 151}
154 152
155 153
154
155
156
157
158
159
160
161
156/** 162/**
157 * Sign a reserve's status with the current signing key. 163 * Sign a reserve's status with the current signing key.
158 * FIXME: not sure why we do this. Should just return 164 * FIXME: not sure why we do this. Should just return
@@ -474,6 +480,7 @@ refresh_accept_melts (struct MHD_Connection *connection,
474 struct KnownCoin known_coin; 480 struct KnownCoin known_coin;
475 // money the customer gets by melting the current coin 481 // money the customer gets by melting the current coin
476 struct TALER_Amount coin_gain; 482 struct TALER_Amount coin_gain;
483 struct RefreshMelt melt;
477 484
478 dki = &(TALER_MINT_get_denom_key (key_state, 485 dki = &(TALER_MINT_get_denom_key (key_state,
479 coin_public_infos[i].denom_pub)->issue); 486 coin_public_infos[i].denom_pub)->issue);
@@ -523,10 +530,17 @@ refresh_accept_melts (struct MHD_Connection *connection,
523 return GNUNET_SYSERR; 530 return GNUNET_SYSERR;
524 } 531 }
525 532
533 // FIXME: test first if coin was already melted
534 // in this session, etc.
535
536 melt.coin = coin_public_infos[i];
537 melt.session_pub = *session_pub;
538 // melt.coin_sig = FIXME;
539 // melt.amount = FIXME;
540 melt.oldcoin_index = i;
526 if (GNUNET_OK != 541 if (GNUNET_OK !=
527 TALER_MINT_DB_insert_refresh_melt (db_conn, session_pub, i, 542 TALER_MINT_DB_insert_refresh_melt (db_conn,
528 &coin_public_infos[i].coin_pub, 543 &melt))
529 coin_public_infos[i].denom_pub))
530 { 544 {
531 GNUNET_break (0); 545 GNUNET_break (0);
532 return GNUNET_SYSERR; 546 return GNUNET_SYSERR;
@@ -934,9 +948,9 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
934 for (j = 0; j < refresh_session.num_oldcoins; j++) 948 for (j = 0; j < refresh_session.num_oldcoins; j++)
935 { 949 {
936 struct RefreshCommitLink commit_link; 950 struct RefreshCommitLink commit_link;
937 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
938 struct TALER_TransferSecret transfer_secret; 951 struct TALER_TransferSecret transfer_secret;
939 struct TALER_LinkSecret shared_secret; 952 struct TALER_LinkSecret shared_secret;
953 struct RefreshMelt melt;
940 954
941 res = TALER_MINT_DB_get_refresh_commit_link (db_conn, 955 res = TALER_MINT_DB_get_refresh_commit_link (db_conn,
942 refresh_session_pub, 956 refresh_session_pub,
@@ -949,7 +963,10 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
949 return MHD_NO; 963 return MHD_NO;
950 } 964 }
951 965
952 res = TALER_MINT_DB_get_refresh_melt (db_conn, refresh_session_pub, j, &coin_pub); 966 res = TALER_MINT_DB_get_refresh_melt (db_conn,
967 refresh_session_pub,
968 j,
969 &melt);
953 if (GNUNET_OK != res) 970 if (GNUNET_OK != res)
954 { 971 {
955 GNUNET_break (0); 972 GNUNET_break (0);
@@ -962,7 +979,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
962 /* FIXME: ECDHE/ECDSA-key type confusion! Can we reduce/avoid this? */ 979 /* FIXME: ECDHE/ECDSA-key type confusion! Can we reduce/avoid this? */
963 if (GNUNET_OK != 980 if (GNUNET_OK !=
964 GNUNET_CRYPTO_ecc_ecdh ((const struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_privs[i+off][j], 981 GNUNET_CRYPTO_ecc_ecdh ((const struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_privs[i+off][j],
965 (const struct GNUNET_CRYPTO_EcdhePublicKey *) &coin_pub, 982 (const struct GNUNET_CRYPTO_EcdhePublicKey *) &melt.coin.coin_pub,
966 &transfer_secret.key)) 983 &transfer_secret.key))
967 { 984 {
968 GNUNET_break (0); 985 GNUNET_break (0);
diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c
index 1e496d5a5..ec75c3ec0 100644
--- a/src/mint/taler-mint-httpd_deposit.c
+++ b/src/mint/taler-mint-httpd_deposit.c
@@ -112,8 +112,6 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
112 * 112 *
113 * @param connection the MHD connection to handle 113 * @param connection the MHD connection to handle
114 * @param root root of the posted JSON 114 * @param root root of the posted JSON
115 * @param purpose is this a #TALER_SIGNATURE_WALLET_DEPOSIT or
116 * #TALER_SIGNATURE_INCREMENTAL_WALLET_DEPOSIT // FIXME: bad type, use enum!
117 * @param amount how much should be deposited 115 * @param amount how much should be deposited
118 * @param wire json describing the wire details (?) 116 * @param wire json describing the wire details (?)
119 * @return MHD result code 117 * @return MHD result code
@@ -121,7 +119,6 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
121static int 119static int
122parse_and_handle_deposit_request (struct MHD_Connection *connection, 120parse_and_handle_deposit_request (struct MHD_Connection *connection,
123 const json_t *root, 121 const json_t *root,
124 uint32_t purpose,
125 const struct TALER_Amount *amount, 122 const struct TALER_Amount *amount,
126 const json_t *wire) 123 const json_t *wire)
127{ 124{
@@ -187,7 +184,6 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
187 GNUNET_free (wire_enc); 184 GNUNET_free (wire_enc);
188 185
189 deposit.wire = wire; 186 deposit.wire = wire;
190 deposit.purpose = purpose;
191 deposit.amount = *amount; 187 deposit.amount = *amount;
192 res = verify_and_execute_deposit (connection, 188 res = verify_and_execute_deposit (connection,
193 &deposit); 189 &deposit);
@@ -223,9 +219,7 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
223{ 219{
224 json_t *json; 220 json_t *json;
225 json_t *wire; 221 json_t *wire;
226 const char *deposit_type;
227 int res; 222 int res;
228 uint32_t purpose;
229 struct TALER_Amount amount; 223 struct TALER_Amount amount;
230 json_t *f; 224 json_t *f;
231 225
@@ -240,7 +234,6 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
240 return MHD_YES; 234 return MHD_YES;
241 if (-1 == json_unpack (json, 235 if (-1 == json_unpack (json,
242 "{s:s, s:o, f:o}", 236 "{s:s, s:o, f:o}",
243 "type", &deposit_type,
244 "wire", &wire, 237 "wire", &wire,
245 "f", &f)) 238 "f", &f))
246 { 239 {
@@ -267,24 +260,8 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
267 json_decref (json); 260 json_decref (json);
268 return MHD_YES; 261 return MHD_YES;
269 } 262 }
270 /* FIXME: use array search and enum, this is ugly */
271 if (0 == strcmp ("DIRECT_DEPOSIT", deposit_type))
272 purpose = TALER_SIGNATURE_WALLET_DEPOSIT;
273 else if (0 == strcmp ("INCREMENTAL_DEPOSIT", deposit_type))
274 purpose = TALER_SIGNATURE_INCREMENTAL_WALLET_DEPOSIT;
275 else
276 {
277 GNUNET_break_op (0);
278 json_decref (wire);
279 json_decref (json);
280 return TALER_MINT_reply_json_pack (connection,
281 MHD_HTTP_BAD_REQUEST,
282 "{s:s}",
283 "error", "Bad format");
284 }
285 res = parse_and_handle_deposit_request (connection, 263 res = parse_and_handle_deposit_request (connection,
286 json, 264 json,
287 purpose,
288 &amount, 265 &amount,
289 wire); 266 wire);
290 json_decref (wire); 267 json_decref (wire);
diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c
index 00664cbbf..045485b20 100644
--- a/src/mint/test_mint_deposits.c
+++ b/src/mint/test_mint_deposits.c
@@ -52,6 +52,44 @@ static int persistent;
52static int result; 52static int result;
53 53
54 54
55int
56TALER_MINT_DB_init_deposits (PGconn *conn, int tmp)
57{
58 const char *tmp_str = (1 == tmp) ? "TEMPORARY" : "";
59 char *sql;
60 PGresult *res;
61 int ret;
62
63 res = NULL;
64 (void) GNUNET_asprintf (&sql,
65 "CREATE %1$s TABLE IF NOT EXISTS deposits ("
66 " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)"
67 ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)"
68 ",transaction_id INT8 NOT NULL"
69 ",amount_value INT4 NOT NULL"
70 ",amount_fraction INT4 NOT NULL"
71 ",amount_currency VARCHAR(4) NOT NULL"
72 ",merchant_pub BYTEA NOT NULL"
73 ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)"
74 ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)"
75 ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)"
76 ",wire TEXT NOT NULL"
77 ")",
78 tmp_str);
79 res = PQexec (conn, sql);
80 GNUNET_free (sql);
81 if (PGRES_COMMAND_OK != PQresultStatus (res))
82 {
83 break_db_err (res);
84 ret = GNUNET_SYSERR;
85 }
86 else
87 ret = GNUNET_OK;
88 PQclear (res);
89 return ret;
90}
91
92
55static void 93static void
56do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 94do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
57{ 95{
@@ -89,7 +127,7 @@ run (void *cls, char *const *args, const char *cfgfile,
89 &do_shutdown, NULL); 127 &do_shutdown, NULL);
90 EXITIF (NULL == (conn = PQconnectdb(DB_URI))); 128 EXITIF (NULL == (conn = PQconnectdb(DB_URI)));
91 EXITIF (GNUNET_OK != TALER_MINT_DB_init_deposits (conn, !persistent)); 129 EXITIF (GNUNET_OK != TALER_MINT_DB_init_deposits (conn, !persistent));
92 EXITIF (GNUNET_OK != TALER_MINT_DB_prepare_deposits (conn)); 130 EXITIF (GNUNET_OK != TALER_MINT_DB_prepare (conn));
93 deposit = GNUNET_malloc (sizeof (struct Deposit) + sizeof (wire)); 131 deposit = GNUNET_malloc (sizeof (struct Deposit) + sizeof (wire));
94 /* Makeup a random coin public key */ 132 /* Makeup a random coin public key */
95 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 133 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,