From 795da06505cebc6953d9b42c12c69432436733ee Mon Sep 17 00:00:00 2001 From: catbref Date: Tue, 19 Jun 2018 16:49:42 +0100 Subject: [PATCH] Refactor stupid getResultSetBytes() method & fix migrate * Replaced occurances of "this.repository.getResultSetBytes(resultSet.getBinaryStream(index))" with "resultSet.getBytes(index)" * Replaced corresponding preparedStatement.setBinaryStream() with preparedStatement.setBytes() * Fixed migrate app so DB can be rebuilt using old v1 Qora client --- NOTES.md | 16 +- README.md | 5 +- src/migrate.java | 177 ++++++++++-------- .../hsqldb/HSQLDBAccountRepository.java | 2 +- .../hsqldb/HSQLDBAssetRepository.java | 4 +- .../hsqldb/HSQLDBBlockRepository.java | 12 +- src/repository/hsqldb/HSQLDBRepository.java | 26 --- ...SQLDBCancelOrderTransactionRepository.java | 2 +- ...HSQLDBIssueAssetTransactionRepository.java | 2 +- .../HSQLDBMessageTransactionRepository.java | 4 +- ...QLDBMultiPaymentTransactionRepository.java | 2 +- .../HSQLDBPaymentTransactionRepository.java | 2 +- .../HSQLDBTransactionRepository.java | 10 +- ...LDBTransferAssetTransactionRepository.java | 2 +- 14 files changed, 132 insertions(+), 134 deletions(-) diff --git a/NOTES.md b/NOTES.md index be70ccac..ba619ca6 100644 --- a/NOTES.md +++ b/NOTES.md @@ -28,18 +28,10 @@ as previously public key objects could be stored directly in MapDB. e.g. ```PaymentTransactions.sender```, so that all transactions by a specific Qora account can be quickly found without scanning all child tables. -- Trying to keep all SQL inside respective Java classes, -e.g. operations on ```Blocks``` table only done within ```Block.java```. +- SQL is contained within repository classes repository.* (interfaces) and repository.hsqldb.* (implementations). -- Some MapDB-based objects had Java Map<> obejcts as their values. These will need to be unpicked into separate tables. +- We use transfer objects in data.* -### Possible gen2 refactoring already +- "Business logic" is left in qora.* -- We might need to change ```Blocks.generator``` from Qora address in VARCHAR to public key in VARBINARY, -then derive address from public key as needed. - -- Ditto ```Transactions.creator``` and equivalent columns in child tables. - -- Extracting values from a ```ResultSet``` by column index is efficient but prone to mistakes -as the indexes have to be maintained by a human. There might be a better, general solution to this -without having to resort to importing an external ORM library. Maybe simply ```value = resultSet.getInt(columnIndex++)``` +- Some MapDB-based objects had Java Map<> objects as their values. These will need to be unpacked into separate tables. diff --git a/README.md b/README.md index 3e3b86c5..7837af25 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,7 @@ To use: - Use maven to fetch dependencies. - Build project. - Fire up an old-gen Qora node. -- Run ```src/test/update.java``` as a JUnit test to build DB structure. -- Run ```src/test/migrate.java``` as a JUnit test to migrate old Qora blocks to DB. +- Run ```src/migrate.java``` as a Java application to migrate old Qora blocks to DB. You should now be able to run ```src/test/load.java``` and ```src/test/save.java``` as JUnit tests demonstrating loading/saving Transactions from/to database. @@ -45,3 +44,5 @@ Another idea is to assign a shell alias in your ```.bashrc``` like: alias sqltool='rlwrap java -cp ${HSQLDB_JAR}:${SQLTOOL_JAR} org.hsqldb.cmdline.SqlTool --rcFile=${SQLTOOL_RC}' ``` So you can simply type: ```sqltool qora``` + +Don't forget to use ```SHUTDOWN;``` before exiting sqltool so that database files are closed cleanly. \ No newline at end of file diff --git a/src/migrate.java b/src/migrate.java index c8a68646..b9aa9b8c 100644 --- a/src/migrate.java +++ b/src/migrate.java @@ -1,7 +1,6 @@ import static org.junit.Assert.*; import java.io.BufferedReader; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -9,6 +8,7 @@ import java.math.BigDecimal; import java.net.URL; import java.nio.charset.Charset; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -35,6 +36,8 @@ import utils.Base58; public class migrate { + private static final String connectionUrl = "jdbc:hsqldb:file:db/test;create=true;close_result=true;sql.strict_exec=true;sql.enforce_names=true;sql.syntax_mys=true"; + private static final String GENESIS_ADDRESS = "QfGMeDQQUQePMpAmfLBJzgqyrM35RWxHGD"; private static final byte[] GENESIS_PUBLICKEY = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -77,6 +80,16 @@ public class migrate { } } + public static void savePublicKeys(Connection connection) throws SQLException { + PreparedStatement pStmt = connection.prepareStatement("INSERT IGNORE INTO Test_public_keys VALUES (?, ?)"); + + for (Entry entry : publicKeyByAddress.entrySet()) { + pStmt.setString(1, entry.getKey()); + pStmt.setBytes(2, entry.getValue()); + pStmt.execute(); + } + } + public static String formatWithPlaceholders(String... columns) { String[] placeholders = new String[columns.length]; Arrays.setAll(placeholders, (int i) -> "?"); @@ -97,11 +110,13 @@ public class migrate { publicKeyByAddress.put("QcDLhirHkSbR4TLYeShLzHw61B8UGTFusk", Base58.decode("HP58uWRBae654ze6ysmdyGv3qaDrr9BEk6cHv4WuiF7d")); // TODO convert to repository - Connection c = null; + Connection c = DriverManager.getConnection(connectionUrl); + + c.createStatement() + .execute("CREATE TABLE IF NOT EXISTS Test_public_keys ( address varchar(64), public_key varbinary(32) not null, primary key(address) )"); + c.createStatement().execute("CREATE INDEX IF NOT EXISTS Test_public_key_index ON Test_public_keys (public_key)"); test.Common.setRepository(); - Repository repository = RepositoryManager.getRepository(); - BlockRepository blockRepository = repository.getBlockRepository(); PreparedStatement blocksPStmt = c .prepareStatement("INSERT INTO Blocks " + formatWithPlaceholders("signature", "version", "reference", "transaction_count", "total_fees", @@ -126,7 +141,7 @@ public class migrate { PreparedStatement buyNamePStmt = c .prepareStatement("INSERT INTO BuyNameTransactions " + formatWithPlaceholders("signature", "buyer", "name", "seller", "amount")); PreparedStatement createPollPStmt = c - .prepareStatement("INSERT INTO CreatePollTransactions " + formatWithPlaceholders("signature", "creator", "poll", "description")); + .prepareStatement("INSERT INTO CreatePollTransactions " + formatWithPlaceholders("signature", "creator", "owner", "poll", "description")); PreparedStatement createPollOptionPStmt = c .prepareStatement("INSERT INTO CreatePollTransactionOptions " + formatWithPlaceholders("signature", "option")); PreparedStatement voteOnPollPStmt = c @@ -140,7 +155,7 @@ public class migrate { PreparedStatement createAssetOrderPStmt = c.prepareStatement("INSERT INTO CreateAssetOrderTransactions " + formatWithPlaceholders("signature", "creator", "have_asset_id", "amount", "want_asset_id", "price")); PreparedStatement cancelAssetOrderPStmt = c - .prepareStatement("INSERT INTO CancelAssetOrderTransactions " + formatWithPlaceholders("signature", "creator", "asset_order")); + .prepareStatement("INSERT INTO CancelAssetOrderTransactions " + formatWithPlaceholders("signature", "creator", "asset_order_id")); PreparedStatement multiPaymentPStmt = c.prepareStatement("INSERT INTO MultiPaymentTransactions " + formatWithPlaceholders("signature", "sender")); PreparedStatement deployATPStmt = c.prepareStatement("INSERT INTO DeployATTransactions " + formatWithPlaceholders("signature", "creator", "AT_name", "description", "AT_type", "AT_tags", "creation_bytes", "amount")); @@ -153,7 +168,12 @@ public class migrate { PreparedStatement blockTxPStmt = c .prepareStatement("INSERT INTO BlockTransactions " + formatWithPlaceholders("block_signature", "sequence", "transaction_signature")); - int height = blockRepository.getBlockchainHeight() + 1; + int height; + try (final Repository repository = RepositoryManager.getRepository()) { + BlockRepository blockRepository = repository.getBlockRepository(); + height = blockRepository.getBlockchainHeight() + 1; + } + byte[] milestone_block = null; System.out.println("Starting migration from block height " + height); @@ -178,23 +198,23 @@ public class migrate { byte[] generatorPublicKey = addressToPublicKey((String) json.get("generator")); - blocksPStmt.setBinaryStream(1, new ByteArrayInputStream(blockSignature)); + blocksPStmt.setBytes(1, blockSignature); blocksPStmt.setInt(2, ((Long) json.get("version")).intValue()); - blocksPStmt.setBinaryStream(3, new ByteArrayInputStream(blockReference)); + blocksPStmt.setBytes(3, blockReference); blocksPStmt.setInt(4, transactions.size()); blocksPStmt.setBigDecimal(5, BigDecimal.valueOf(Double.valueOf((String) json.get("fee")).doubleValue())); - blocksPStmt.setBinaryStream(6, new ByteArrayInputStream(blockTransactionsSignature)); + blocksPStmt.setBytes(6, blockTransactionsSignature); blocksPStmt.setInt(7, height); blocksPStmt.setTimestamp(8, new Timestamp((Long) json.get("timestamp"))); blocksPStmt.setBigDecimal(9, BigDecimal.valueOf((Long) json.get("generatingBalance"))); - blocksPStmt.setBinaryStream(10, new ByteArrayInputStream(generatorPublicKey)); - blocksPStmt.setBinaryStream(11, new ByteArrayInputStream(blockGeneratorSignature)); + blocksPStmt.setBytes(10, generatorPublicKey); + blocksPStmt.setBytes(11, blockGeneratorSignature); String blockATs = (String) json.get("blockATs"); if (blockATs != null && blockATs.length() > 0) { HashCode atBytes = HashCode.fromString(blockATs); - blocksPStmt.setBinaryStream(12, new ByteArrayInputStream(atBytes.asBytes())); + blocksPStmt.setBytes(12, atBytes.asBytes()); blocksPStmt.setBigDecimal(13, BigDecimal.valueOf(((Long) json.get("atFees")).longValue(), 8)); } else { blocksPStmt.setNull(12, java.sql.Types.VARBINARY); @@ -211,14 +231,14 @@ public class migrate { JSONObject transaction = (JSONObject) transactions.get(txIndex); byte[] txSignature = Base58.decode((String) transaction.get("signature")); - txPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + txPStmt.setBytes(1, txSignature); String txReference58 = (String) transaction.get("reference"); byte[] txReference = txReference58.isEmpty() ? null : Base58.decode(txReference58); int type = ((Long) transaction.get("type")).intValue(); if (txReference != null) - txPStmt.setBinaryStream(2, new ByteArrayInputStream(txReference)); + txPStmt.setBytes(2, txReference); else if (height == 1 && type == 1) txPStmt.setNull(2, java.sql.Types.VARBINARY); // genesis transactions only else @@ -229,27 +249,27 @@ public class migrate { // Determine transaction "creator" from specific transaction info switch (type) { case 1: // genesis - txPStmt.setBinaryStream(4, new ByteArrayInputStream(GENESIS_PUBLICKEY)); // genesis transactions only + txPStmt.setBytes(4, GENESIS_PUBLICKEY); // genesis transactions only break; case 2: // payment case 12: // transfer asset case 15: // multi-payment - txPStmt.setBinaryStream(4, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("sender")))); + txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("sender"))); break; case 3: // register name - txPStmt.setBinaryStream(4, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("registrant")))); + txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("registrant"))); break; case 4: // update name case 5: // sell name case 6: // cancel sell name - txPStmt.setBinaryStream(4, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("owner")))); + txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("owner"))); break; case 7: // buy name - txPStmt.setBinaryStream(4, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("buyer")))); + txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("buyer"))); break; case 8: // create poll @@ -260,7 +280,7 @@ public class migrate { case 14: // cancel asset order case 16: // deploy CIYAM AT case 17: // message - txPStmt.setBinaryStream(4, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("creator"))); break; default: @@ -272,7 +292,7 @@ public class migrate { txPStmt.setBigDecimal(6, BigDecimal.valueOf(Double.valueOf((String) transaction.get("fee")).doubleValue())); if (milestone_block != null) - txPStmt.setBinaryStream(7, new ByteArrayInputStream(milestone_block)); + txPStmt.setBytes(7, milestone_block); else if (height == 1 && type == 1) txPStmt.setNull(7, java.sql.Types.VARBINARY); // genesis transactions only else @@ -331,7 +351,7 @@ public class migrate { } for (String recipient : recipients) { - recipientPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + recipientPStmt.setBytes(1, txSignature); recipientPStmt.setString(2, recipient); recipientPStmt.execute(); @@ -341,7 +361,7 @@ public class migrate { // Transaction-type-specific processing switch (type) { case 1: // genesis - genesisPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + genesisPStmt.setBytes(1, txSignature); genesisPStmt.setString(2, recipients.get(0)); genesisPStmt.setBigDecimal(3, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); @@ -350,8 +370,8 @@ public class migrate { break; case 2: // payment - paymentPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - paymentPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("sender")))); + paymentPStmt.setBytes(1, txSignature); + paymentPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender"))); paymentPStmt.setString(3, recipients.get(0)); paymentPStmt.setBigDecimal(4, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); @@ -360,8 +380,8 @@ public class migrate { break; case 3: // register name - registerNamePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - registerNamePStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("registrant")))); + registerNamePStmt.setBytes(1, txSignature); + registerNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("registrant"))); registerNamePStmt.setString(3, (String) transaction.get("name")); registerNamePStmt.setString(4, (String) transaction.get("owner")); registerNamePStmt.setString(5, (String) transaction.get("value")); @@ -371,8 +391,8 @@ public class migrate { break; case 4: // update name - updateNamePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - updateNamePStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("owner")))); + updateNamePStmt.setBytes(1, txSignature); + updateNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner"))); updateNamePStmt.setString(3, (String) transaction.get("name")); updateNamePStmt.setString(4, (String) transaction.get("newOwner")); updateNamePStmt.setString(5, (String) transaction.get("newValue")); @@ -382,8 +402,8 @@ public class migrate { break; case 5: // sell name - sellNamePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - sellNamePStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("owner")))); + sellNamePStmt.setBytes(1, txSignature); + sellNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner"))); sellNamePStmt.setString(3, (String) transaction.get("name")); sellNamePStmt.setBigDecimal(4, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); @@ -392,8 +412,8 @@ public class migrate { break; case 6: // cancel sell name - cancelSellNamePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - cancelSellNamePStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("owner")))); + cancelSellNamePStmt.setBytes(1, txSignature); + cancelSellNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner"))); cancelSellNamePStmt.setString(3, (String) transaction.get("name")); cancelSellNamePStmt.execute(); @@ -401,8 +421,8 @@ public class migrate { break; case 7: // buy name - buyNamePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - buyNamePStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("buyer")))); + buyNamePStmt.setBytes(1, txSignature); + buyNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("buyer"))); buyNamePStmt.setString(3, (String) transaction.get("name")); buyNamePStmt.setString(4, (String) transaction.get("seller")); buyNamePStmt.setBigDecimal(5, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); @@ -412,10 +432,12 @@ public class migrate { break; case 8: // create poll - createPollPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - createPollPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); - createPollPStmt.setString(3, (String) transaction.get("name")); - createPollPStmt.setString(4, (String) transaction.get("description")); + createPollPStmt.setBytes(1, txSignature); + createPollPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); + // In gen1, there are no polls where the owner is not the creator + createPollPStmt.setString(3, (String) transaction.get("creator")); // owner + createPollPStmt.setString(4, (String) transaction.get("name")); + createPollPStmt.setString(5, (String) transaction.get("description")); createPollPStmt.execute(); createPollPStmt.clearParameters(); @@ -423,7 +445,7 @@ public class migrate { // options JSONArray options = (JSONArray) transaction.get("options"); for (Object option : options) { - createPollOptionPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + createPollOptionPStmt.setBytes(1, txSignature); createPollOptionPStmt.setString(2, (String) option); createPollOptionPStmt.execute(); @@ -432,8 +454,8 @@ public class migrate { break; case 9: // vote on poll - voteOnPollPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - voteOnPollPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + voteOnPollPStmt.setBytes(1, txSignature); + voteOnPollPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); voteOnPollPStmt.setString(3, (String) transaction.get("poll")); voteOnPollPStmt.setInt(4, ((Long) transaction.get("option")).intValue()); @@ -442,8 +464,8 @@ public class migrate { break; case 10: // arbitrary transactions - arbitraryPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - arbitraryPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + arbitraryPStmt.setBytes(1, txSignature); + arbitraryPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); arbitraryPStmt.setInt(3, ((Long) transaction.get("service")).intValue()); arbitraryPStmt.setString(4, "TODO"); @@ -454,7 +476,7 @@ public class migrate { for (Object paymentObj : multiPayments) { JSONObject payment = (JSONObject) paymentObj; - sharedPaymentPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + sharedPaymentPStmt.setBytes(1, txSignature); sharedPaymentPStmt.setString(2, (String) payment.get("recipient")); sharedPaymentPStmt.setBigDecimal(3, BigDecimal.valueOf(Double.valueOf((String) payment.get("amount")).doubleValue())); sharedPaymentPStmt.setLong(4, ((Long) payment.get("asset")).longValue()); @@ -465,9 +487,10 @@ public class migrate { break; case 11: // issue asset - issueAssetPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - issueAssetPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); - issueAssetPStmt.setString(3, (String) transaction.get("owner")); + issueAssetPStmt.setBytes(1, txSignature); + issueAssetPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); + // In gen1, there are no polls where the owner is not the creator + issueAssetPStmt.setString(3, (String) transaction.get("creator")); // owner issueAssetPStmt.setString(4, (String) transaction.get("name")); issueAssetPStmt.setString(5, (String) transaction.get("description")); issueAssetPStmt.setBigDecimal(6, BigDecimal.valueOf(((Long) transaction.get("quantity")).longValue())); @@ -478,8 +501,8 @@ public class migrate { break; case 12: // transfer asset - transferAssetPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - transferAssetPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("sender")))); + transferAssetPStmt.setBytes(1, txSignature); + transferAssetPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender"))); transferAssetPStmt.setString(3, (String) transaction.get("recipient")); transferAssetPStmt.setLong(4, ((Long) transaction.get("asset")).longValue()); transferAssetPStmt.setBigDecimal(5, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); @@ -489,8 +512,8 @@ public class migrate { break; case 13: // create asset order - createAssetOrderPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - createAssetOrderPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + createAssetOrderPStmt.setBytes(1, txSignature); + createAssetOrderPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); JSONObject assetOrder = (JSONObject) transaction.get("order"); createAssetOrderPStmt.setLong(3, ((Long) assetOrder.get("have")).longValue()); @@ -503,17 +526,17 @@ public class migrate { break; case 14: // cancel asset order - cancelAssetOrderPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - cancelAssetOrderPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); - cancelAssetOrderPStmt.setString(3, (String) transaction.get("order")); + cancelAssetOrderPStmt.setBytes(1, txSignature); + cancelAssetOrderPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); + cancelAssetOrderPStmt.setBytes(3, Base58.decode((String) transaction.get("order"))); cancelAssetOrderPStmt.execute(); cancelAssetOrderPStmt.clearParameters(); break; case 15: // multi-payment - multiPaymentPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - multiPaymentPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("sender")))); + multiPaymentPStmt.setBytes(1, txSignature); + multiPaymentPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender"))); multiPaymentPStmt.execute(); multiPaymentPStmt.clearParameters(); @@ -521,7 +544,7 @@ public class migrate { for (Object paymentObj : multiPayments) { JSONObject payment = (JSONObject) paymentObj; - sharedPaymentPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + sharedPaymentPStmt.setBytes(1, txSignature); sharedPaymentPStmt.setString(2, (String) payment.get("recipient")); sharedPaymentPStmt.setBigDecimal(3, BigDecimal.valueOf(Double.valueOf((String) payment.get("amount")).doubleValue())); sharedPaymentPStmt.setLong(4, ((Long) payment.get("asset")).longValue()); @@ -533,15 +556,14 @@ public class migrate { case 16: // deploy AT HashCode creationBytes = HashCode.fromString((String) transaction.get("creationBytes")); - InputStream creationBytesStream = new ByteArrayInputStream(creationBytes.asBytes()); - deployATPStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); - deployATPStmt.setBinaryStream(2, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + deployATPStmt.setBytes(1, txSignature); + deployATPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator"))); deployATPStmt.setString(3, (String) transaction.get("name")); deployATPStmt.setString(4, (String) transaction.get("description")); deployATPStmt.setString(5, (String) transaction.get("atType")); deployATPStmt.setString(6, (String) transaction.get("tags")); - deployATPStmt.setBinaryStream(7, creationBytesStream); + deployATPStmt.setBytes(7, creationBytes.asBytes()); deployATPStmt.setBigDecimal(8, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue())); deployATPStmt.execute(); @@ -553,17 +575,17 @@ public class migrate { boolean isEncrypted = (Boolean) transaction.get("encrypted"); String messageData = (String) transaction.get("data"); - InputStream messageDataStream; + byte[] messageDataBytes; if (isText && !isEncrypted) { - messageDataStream = new ByteArrayInputStream(messageData.getBytes("UTF-8")); + messageDataBytes = messageData.getBytes("UTF-8"); } else { HashCode messageBytes = HashCode.fromString(messageData); - messageDataStream = new ByteArrayInputStream(messageBytes.asBytes()); + messageDataBytes = messageBytes.asBytes(); } - messagePStmt.setBinaryStream(1, new ByteArrayInputStream(txSignature)); + messagePStmt.setBytes(1, txSignature); messagePStmt.setInt(2, Transaction.getVersionByTimestamp(transactionTimestamp)); - messagePStmt.setBinaryStream(3, new ByteArrayInputStream(addressToPublicKey((String) transaction.get("creator")))); + messagePStmt.setBytes(3, addressToPublicKey((String) transaction.get("creator"))); messagePStmt.setString(4, (String) transaction.get("recipient")); messagePStmt.setBoolean(5, isText); messagePStmt.setBoolean(6, isEncrypted); @@ -574,7 +596,7 @@ public class migrate { else messagePStmt.setLong(8, 0L); // QORA simulated asset - messagePStmt.setBinaryStream(9, messageDataStream); + messagePStmt.setBytes(9, messageDataBytes); messagePStmt.execute(); messagePStmt.clearParameters(); @@ -584,14 +606,14 @@ public class migrate { // fail(); } - blockTxPStmt.setBinaryStream(1, new ByteArrayInputStream(blockSignature)); + blockTxPStmt.setBytes(1, blockSignature); blockTxPStmt.setInt(2, txIndex); - blockTxPStmt.setBinaryStream(3, new ByteArrayInputStream(txSignature)); + blockTxPStmt.setBytes(3, txSignature); blockTxPStmt.execute(); blockTxPStmt.clearParameters(); - repository.saveChanges(); + // repository.saveChanges(); } // new milestone block every 500 blocks? @@ -601,7 +623,16 @@ public class migrate { ++height; } - System.out.println("Migration finished with new blockchain height " + blockRepository.getBlockchainHeight()); + savePublicKeys(c); + + c.close(); + + try (final Repository repository = RepositoryManager.getRepository()) { + BlockRepository blockRepository = repository.getBlockRepository(); + System.out.println("Migration finished with new blockchain height " + blockRepository.getBlockchainHeight()); + } + + RepositoryManager.closeRepositoryFactory(); } } diff --git a/src/repository/hsqldb/HSQLDBAccountRepository.java b/src/repository/hsqldb/HSQLDBAccountRepository.java index 80c543b5..bb52a491 100644 --- a/src/repository/hsqldb/HSQLDBAccountRepository.java +++ b/src/repository/hsqldb/HSQLDBAccountRepository.java @@ -23,7 +23,7 @@ public class HSQLDBAccountRepository implements AccountRepository { if (resultSet == null) return null; - return new AccountData(address, this.repository.getResultSetBytes(resultSet.getBinaryStream(1))); + return new AccountData(address, resultSet.getBytes(1)); } catch (SQLException e) { throw new DataException("Unable to fetch account info from repository", e); } diff --git a/src/repository/hsqldb/HSQLDBAssetRepository.java b/src/repository/hsqldb/HSQLDBAssetRepository.java index a877eaf3..55751439 100644 --- a/src/repository/hsqldb/HSQLDBAssetRepository.java +++ b/src/repository/hsqldb/HSQLDBAssetRepository.java @@ -31,7 +31,7 @@ public class HSQLDBAssetRepository implements AssetRepository { String description = resultSet.getString(3); long quantity = resultSet.getLong(4); boolean isDivisible = resultSet.getBoolean(5); - byte[] reference = this.repository.getResultSetBytes(resultSet.getBinaryStream(6)); + byte[] reference = resultSet.getBytes(6); return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, reference); } catch (SQLException e) { @@ -89,7 +89,7 @@ public class HSQLDBAssetRepository implements AssetRepository { if (resultSet == null) return null; - byte[] creatorPublicKey = this.repository.getResultSetBytes(resultSet.getBinaryStream(1)); + byte[] creatorPublicKey = resultSet.getBytes(1); long haveAssetId = resultSet.getLong(2); long wantAssetId = resultSet.getLong(3); BigDecimal amount = resultSet.getBigDecimal(4); diff --git a/src/repository/hsqldb/HSQLDBBlockRepository.java b/src/repository/hsqldb/HSQLDBBlockRepository.java index 54257c99..24a1cdec 100644 --- a/src/repository/hsqldb/HSQLDBBlockRepository.java +++ b/src/repository/hsqldb/HSQLDBBlockRepository.java @@ -31,16 +31,16 @@ public class HSQLDBBlockRepository implements BlockRepository { try { int version = rs.getInt(1); - byte[] reference = this.repository.getResultSetBytes(rs.getBinaryStream(2)); + byte[] reference = rs.getBytes(2); int transactionCount = rs.getInt(3); BigDecimal totalFees = rs.getBigDecimal(4); - byte[] transactionsSignature = this.repository.getResultSetBytes(rs.getBinaryStream(5)); + byte[] transactionsSignature = rs.getBytes(5); int height = rs.getInt(6); long timestamp = rs.getTimestamp(7).getTime(); BigDecimal generatingBalance = rs.getBigDecimal(8); - byte[] generatorPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(9)); - byte[] generatorSignature = this.repository.getResultSetBytes(rs.getBinaryStream(10)); - byte[] atBytes = this.repository.getResultSetBytes(rs.getBinaryStream(11)); + byte[] generatorPublicKey = rs.getBytes(9); + byte[] generatorSignature = rs.getBytes(10); + byte[] atBytes = rs.getBytes(11); BigDecimal atFees = rs.getBigDecimal(12); return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, @@ -117,7 +117,7 @@ public class HSQLDBBlockRepository implements BlockRepository { // NB: do-while loop because .checkedExecute() implicitly calls ResultSet.next() for us do { - byte[] transactionSignature = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] transactionSignature = rs.getBytes(1); transactions.add(transactionRepo.fromSignature(transactionSignature)); } while (rs.next()); } catch (SQLException e) { diff --git a/src/repository/hsqldb/HSQLDBRepository.java b/src/repository/hsqldb/HSQLDBRepository.java index 46390f97..5f9be839 100644 --- a/src/repository/hsqldb/HSQLDBRepository.java +++ b/src/repository/hsqldb/HSQLDBRepository.java @@ -1,7 +1,5 @@ package repository.hsqldb; -import java.io.IOException; -import java.io.InputStream; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; @@ -101,30 +99,6 @@ public class HSQLDBRepository implements Repository { public void rebuild() throws DataException { } - /** - * Convert InputStream, from ResultSet.getBinaryStream(), into byte[]. - * - * @param inputStream - * @return byte[] - */ - public byte[] getResultSetBytes(InputStream inputStream) { - // inputStream could be null if database's column's value is null - if (inputStream == null) - return null; - - try { - int length = inputStream.available(); - byte[] result = new byte[length]; - - if (inputStream.read(result) == length) - return result; - } catch (IOException e) { - // Fall-through to return null - } - - return null; - } - /** * Execute SQL and return ResultSet with but added checking. *

diff --git a/src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java index da29ce57..47f5aa6f 100644 --- a/src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java @@ -22,7 +22,7 @@ public class HSQLDBCancelOrderTransactionRepository extends HSQLDBTransactionRep if (rs == null) return null; - byte[] assetOrderId = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] assetOrderId = rs.getBytes(1); return new CancelOrderTransactionData(creatorPublicKey, assetOrderId, fee, timestamp, reference, signature); } catch (SQLException e) { diff --git a/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java index a0ecee3f..faa843d9 100644 --- a/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java @@ -24,7 +24,7 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo if (rs == null) return null; - byte[] issuerPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] issuerPublicKey = rs.getBytes(1); String owner = rs.getString(2); String assetName = rs.getString(3); String description = rs.getString(4); diff --git a/src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java index f67c4301..cce2766a 100644 --- a/src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java @@ -24,13 +24,13 @@ public class HSQLDBMessageTransactionRepository extends HSQLDBTransactionReposit return null; int version = rs.getInt(1); - byte[] senderPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(2)); + byte[] senderPublicKey = rs.getBytes(2); String recipient = rs.getString(3); boolean isText = rs.getBoolean(4); boolean isEncrypted = rs.getBoolean(5); BigDecimal amount = rs.getBigDecimal(6); Long assetId = rs.getLong(7); - byte[] data = this.repository.getResultSetBytes(rs.getBinaryStream(8)); + byte[] data = rs.getBytes(8); return new MessageTransactionData(version, senderPublicKey, recipient, assetId, amount, fee, data, isText, isEncrypted, timestamp, reference, signature); diff --git a/src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java index 806f0990..e08e5ebd 100644 --- a/src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java @@ -24,7 +24,7 @@ public class HSQLDBMultiPaymentTransactionRepository extends HSQLDBTransactionRe if (rs == null) return null; - byte[] senderPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] senderPublicKey = rs.getBytes(1); List payments = this.getPaymentsFromSignature(signature); diff --git a/src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java index d6b787b8..e5222a21 100644 --- a/src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java @@ -22,7 +22,7 @@ public class HSQLDBPaymentTransactionRepository extends HSQLDBTransactionReposit if (rs == null) return null; - byte[] senderPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] senderPublicKey = rs.getBytes(1); String recipient = rs.getString(2); BigDecimal amount = rs.getBigDecimal(3); diff --git a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java index 39cb3aa6..616ad96f 100644 --- a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java @@ -52,8 +52,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository { return null; TransactionType type = TransactionType.valueOf(rs.getInt(1)); - byte[] reference = this.repository.getResultSetBytes(rs.getBinaryStream(2)); - byte[] creatorPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(3)); + byte[] reference = rs.getBytes(2); + byte[] creatorPublicKey = rs.getBytes(3); long timestamp = rs.getTimestamp(4).getTime(); BigDecimal fee = rs.getBigDecimal(5).setScale(8); @@ -70,8 +70,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository { return null; TransactionType type = TransactionType.valueOf(rs.getInt(1)); - byte[] signature = this.repository.getResultSetBytes(rs.getBinaryStream(2)); - byte[] creatorPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(3)); + byte[] signature = rs.getBytes(2); + byte[] creatorPublicKey = rs.getBytes(3); long timestamp = rs.getTimestamp(4).getTime(); BigDecimal fee = rs.getBigDecimal(5).setScale(8); @@ -185,7 +185,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { if (rs == null) return null; - byte[] blockSignature = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] blockSignature = rs.getBytes(1); return this.repository.getBlockRepository().fromSignature(blockSignature); } catch (SQLException | DataException e) { diff --git a/src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java index b35a4ad6..5272155d 100644 --- a/src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java @@ -23,7 +23,7 @@ public class HSQLDBTransferAssetTransactionRepository extends HSQLDBTransactionR if (rs == null) return null; - byte[] senderPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(1)); + byte[] senderPublicKey = rs.getBytes(1); String recipient = rs.getString(2); long assetId = rs.getLong(3); BigDecimal amount = rs.getBigDecimal(4);