diff options
Diffstat (limited to 'src/mint/mint_db.c')
-rw-r--r-- | src/mint/mint_db.c | 932 |
1 files changed, 452 insertions, 480 deletions
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 | */ | ||
69 | int | ||
70 | TALER_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)) | 60 | int |
109 | { | 61 | TALER_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 | */ | ||
131 | int | 82 | int |
132 | TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, | 83 | TALER_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 | |||
178 | int | 100 | int |
179 | TALER_MINT_DB_get_reserve (PGconn *db_conn, | 101 | TALER_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 | ")", |
700 | int | 622 | 11, NULL); |
701 | TALER_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 | */ | ||
724 | int | ||
725 | TALER_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 | */ | ||
748 | int | ||
749 | TALER_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 | |||
1499 | int | ||
1500 | TALER_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 | |||
1536 | int | ||
1537 | TALER_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 | |||
1583 | int | 1383 | int |
1584 | TALER_db_get_link (PGconn *db_conn, | 1384 | TALER_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 | */ | ||
1564 | static void | ||
1565 | db_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 | */ | ||
1747 | int | 1579 | int |
1748 | TALER_MINT_DB_init_deposits (PGconn *conn, int tmp) | 1580 | TALER_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 | */ | ||
1600 | PGconn * | ||
1601 | TALER_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 | */ | ||
1784 | int | 1640 | int |
1785 | TALER_MINT_DB_prepare_deposits (PGconn *db_conn) | 1641 | TALER_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 | */ | ||
1667 | int | ||
1668 | TALER_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 | */ | ||
1837 | int | 1692 | int |
1838 | TALER_MINT_DB_insert_deposit (PGconn *db_conn, | 1693 | TALER_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 | */ | ||
1873 | int | 1723 | int |
1874 | TALER_MINT_DB_get_deposit (PGconn *db_conn, | 1724 | TALER_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 | |||
1943 | EXITIF_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 | */ |
1958 | PGconn * | 1785 | int |
1959 | TALER_MINT_DB_get_connection (void) | 1786 | TALER_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 | */ | ||
1840 | int | ||
1841 | TALER_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 | */ |
1996 | static void | 1878 | int |
1997 | db_conn_destroy (void *cls) | 1879 | TALER_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 | */ |
2011 | int | 1922 | int |
2012 | TALER_MINT_DB_init (const char *connection_cfg) | 1923 | TALER_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 | */ | ||
2026 | int | 1963 | int |
2027 | TALER_TALER_DB_extract_amount_nbo (PGresult *result, | 1964 | TALER_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 | */ | ||
2048 | int | 2006 | int |
2049 | TALER_TALER_DB_extract_amount (PGresult *result, | 2007 | TALER_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 | */ | ||
2025 | struct TALER_MINT_DB_TransactionList * | ||
2026 | TALER_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 */ | ||