2018-05-16 11:46:44 +01:00
|
|
|
import static org.junit.Assert.*;
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.nio.charset.Charset;
|
|
|
|
import java.sql.Connection;
|
2018-06-19 16:49:42 +01:00
|
|
|
import java.sql.DriverManager;
|
2018-05-16 11:46:44 +01:00
|
|
|
import java.sql.PreparedStatement;
|
|
|
|
import java.sql.SQLException;
|
|
|
|
import java.sql.Timestamp;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
import java.util.HashMap;
|
2018-05-16 11:46:44 +01:00
|
|
|
import java.util.List;
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
import java.util.Map;
|
2018-06-19 16:49:42 +01:00
|
|
|
import java.util.Map.Entry;
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
import org.json.simple.JSONArray;
|
|
|
|
import org.json.simple.JSONObject;
|
|
|
|
import org.json.simple.JSONValue;
|
|
|
|
import org.json.simple.parser.ParseException;
|
|
|
|
|
|
|
|
import com.google.common.hash.HashCode;
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
import com.google.common.io.CharStreams;
|
2018-05-16 11:46:44 +01:00
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
import qora.transaction.Transaction;
|
|
|
|
import repository.BlockRepository;
|
|
|
|
import repository.DataException;
|
|
|
|
import repository.Repository;
|
|
|
|
import repository.RepositoryManager;
|
2018-05-16 11:46:44 +01:00
|
|
|
import utils.Base58;
|
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
public class migrate {
|
2018-05-16 11:46:44 +01:00
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
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";
|
|
|
|
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
private static final String GENESIS_ADDRESS = "QfGMeDQQUQePMpAmfLBJzgqyrM35RWxHGD";
|
|
|
|
private static final byte[] GENESIS_PUBLICKEY = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 };
|
|
|
|
|
|
|
|
private static Map<String, byte[]> publicKeyByAddress = new HashMap<String, byte[]>();
|
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
public static Object fetchBlockJSON(int height) throws IOException {
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
try (InputStream is = new URL("http://localhost:9085/blocks/byheight/" + height).openStream();
|
|
|
|
InputStreamReader isr = new InputStreamReader(is, Charset.forName("UTF-8"));
|
|
|
|
BufferedReader reader = new BufferedReader(isr)) {
|
|
|
|
return JSONValue.parseWithException(reader);
|
2018-05-16 11:46:44 +01:00
|
|
|
} catch (IOException e) {
|
|
|
|
return null;
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
} catch (ParseException e) {
|
2018-05-16 11:46:44 +01:00
|
|
|
return null;
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
public static byte[] addressToPublicKey(String address) throws IOException {
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
byte[] cachedPublicKey = publicKeyByAddress.get(address);
|
|
|
|
if (cachedPublicKey != null)
|
|
|
|
return cachedPublicKey;
|
|
|
|
|
|
|
|
InputStream is = new URL("http://localhost:9085/addresses/publickey/" + address).openStream();
|
|
|
|
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
try (InputStreamReader isr = new InputStreamReader(is, Charset.forName("UTF-8"))) {
|
|
|
|
String publicKey58 = CharStreams.toString(isr);
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
|
|
|
|
byte[] publicKey = Base58.decode(publicKey58);
|
|
|
|
publicKeyByAddress.put(address, publicKey);
|
|
|
|
return publicKey;
|
|
|
|
} finally {
|
|
|
|
is.close();
|
2018-05-16 11:46:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
public static void savePublicKeys(Connection connection) throws SQLException {
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
try (PreparedStatement pStmt = connection.prepareStatement("INSERT IGNORE INTO Test_public_keys VALUES (?, ?)")) {
|
|
|
|
for (Entry<String, byte[]> entry : publicKeyByAddress.entrySet()) {
|
|
|
|
pStmt.setString(1, entry.getKey());
|
|
|
|
pStmt.setBytes(2, entry.getValue());
|
|
|
|
pStmt.execute();
|
|
|
|
}
|
2018-06-19 16:49:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
public static String formatWithPlaceholders(String... columns) {
|
2018-05-16 11:46:44 +01:00
|
|
|
String[] placeholders = new String[columns.length];
|
|
|
|
Arrays.setAll(placeholders, (int i) -> "?");
|
|
|
|
|
|
|
|
StringBuilder output = new StringBuilder();
|
|
|
|
output.append("(");
|
|
|
|
output.append(String.join(", ", columns));
|
|
|
|
output.append(") VALUES (");
|
|
|
|
output.append(String.join(", ", placeholders));
|
|
|
|
output.append(")");
|
|
|
|
return output.toString();
|
|
|
|
}
|
|
|
|
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
@SuppressWarnings("resource")
|
2018-06-13 16:48:28 +01:00
|
|
|
public static void main(String args[]) throws SQLException, DataException, IOException {
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
// Genesis public key
|
|
|
|
publicKeyByAddress.put(GENESIS_ADDRESS, GENESIS_PUBLICKEY);
|
|
|
|
// Some other public keys for addresses that have never created a transaction
|
|
|
|
publicKeyByAddress.put("QcDLhirHkSbR4TLYeShLzHw61B8UGTFusk", Base58.decode("HP58uWRBae654ze6ysmdyGv3qaDrr9BEk6cHv4WuiF7d"));
|
|
|
|
|
2018-06-13 16:48:28 +01:00
|
|
|
// TODO convert to repository
|
2018-06-19 16:49:42 +01:00
|
|
|
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)");
|
2018-06-13 16:48:28 +01:00
|
|
|
|
|
|
|
test.Common.setRepository();
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
PreparedStatement blocksPStmt = c
|
|
|
|
.prepareStatement("INSERT INTO Blocks " + formatWithPlaceholders("signature", "version", "reference", "transaction_count", "total_fees",
|
2018-05-25 11:48:47 +01:00
|
|
|
"transactions_signature", "height", "generation", "generating_balance", "generator", "generator_signature", "AT_data", "AT_fees"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
PreparedStatement txPStmt = c.prepareStatement(
|
|
|
|
"INSERT INTO Transactions " + formatWithPlaceholders("signature", "reference", "type", "creator", "creation", "fee", "milestone_block"));
|
|
|
|
|
|
|
|
PreparedStatement recipientPStmt = c.prepareStatement("INSERT INTO TransactionRecipients " + formatWithPlaceholders("signature", "recipient"));
|
|
|
|
|
|
|
|
PreparedStatement genesisPStmt = c.prepareStatement("INSERT INTO GenesisTransactions " + formatWithPlaceholders("signature", "recipient", "amount"));
|
|
|
|
PreparedStatement paymentPStmt = c
|
|
|
|
.prepareStatement("INSERT INTO PaymentTransactions " + formatWithPlaceholders("signature", "sender", "recipient", "amount"));
|
|
|
|
PreparedStatement registerNamePStmt = c
|
|
|
|
.prepareStatement("INSERT INTO RegisterNameTransactions " + formatWithPlaceholders("signature", "registrant", "name", "owner", "data"));
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
PreparedStatement updateNamePStmt = c.prepareStatement(
|
|
|
|
"INSERT INTO UpdateNameTransactions " + formatWithPlaceholders("signature", "owner", "name", "new_owner", "new_data", "name_reference"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement sellNamePStmt = c
|
|
|
|
.prepareStatement("INSERT INTO SellNameTransactions " + formatWithPlaceholders("signature", "owner", "name", "amount"));
|
|
|
|
PreparedStatement cancelSellNamePStmt = c
|
|
|
|
.prepareStatement("INSERT INTO CancelSellNameTransactions " + formatWithPlaceholders("signature", "owner", "name"));
|
HSQLDB issue, resource leak prevention, v1 differences
HSQLDB v2.4.0 had some issue with non-padded, case-insensitive string comparisons.
This is fixed in svn r5836-ish of HSQLDB but yet to be pushed out to new HSQLDB release.
So this commit includes hsqldb-r5836.jar and modified pom.xml/.classpath for now.
No need for duplicate, hidden creatorPublicKey in CancelOrderTransactionData,
CreateOrderTransactionData and CreatePollTransactionData.
Various changes to use more try-with-resources, especially with JDBC objects like
Connection, Statement, PreparedStatement, ResultSet.
Added loads of missing @Override annotations.
Fixed bug in Asset exchange order matching where the matching logic loop
would incorrectly adjust temporary amount fulfilled
by the "want" asset amount (in matchedAmount)
instead of the "have" asset amount (in tradePrice).
Disabled check for duplicate asset name in IssueAssetTransactions for old v1 transactions.
In HSQLDB repository we now use ResultSet.getTimestamp(index, UTC-calendar) to make sure we
only store/fetch UTC timestamps. The UTC-calendar is made using static final TimeZone called
HSQLDBRepository.UTC.
To keep asset IDs in line with v1, Assets.asset_id values are generated on-the-fly in HSQLDB
using a "before insert" trigger on Assets table. Corresponding code
calling HSQLDBRepository.callIdentity() replaced with SELECT statement instead.
Moved most of the HSQLDB connection properties from the connection URL to explicit code in
HSQLDBRepositoryFactory.
Fixed incorrect 'amount' lengths in PaymentTransformer, as used by MultiPayment and Arbitrary
transaction types.
Added support for mangled arbitrary transaction bytes when generating/verifying a v1 transaction signature.
In v1 Arbitrary transactions, bytes-for-signing are lost prior to final payment (but only if there are any payments).
Added corresponding code for multi-payment transactions in the same vein.
2018-08-07 15:44:41 +01:00
|
|
|
PreparedStatement buyNamePStmt = c.prepareStatement(
|
|
|
|
"INSERT INTO BuyNameTransactions " + formatWithPlaceholders("signature", "buyer", "name", "seller", "amount", "name_reference"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement createPollPStmt = c
|
2018-07-05 16:24:05 +01:00
|
|
|
.prepareStatement("INSERT INTO CreatePollTransactions " + formatWithPlaceholders("signature", "creator", "owner", "poll_name", "description"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement createPollOptionPStmt = c
|
2018-07-05 16:24:05 +01:00
|
|
|
.prepareStatement("INSERT INTO CreatePollTransactionOptions " + formatWithPlaceholders("signature", "option_name"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement voteOnPollPStmt = c
|
2018-07-05 16:24:05 +01:00
|
|
|
.prepareStatement("INSERT INTO VoteOnPollTransactions " + formatWithPlaceholders("signature", "voter", "poll_name", "option_index"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement arbitraryPStmt = c
|
|
|
|
.prepareStatement("INSERT INTO ArbitraryTransactions " + formatWithPlaceholders("signature", "creator", "service", "data_hash"));
|
|
|
|
PreparedStatement issueAssetPStmt = c.prepareStatement("INSERT INTO IssueAssetTransactions "
|
2018-06-06 09:52:42 +01:00
|
|
|
+ formatWithPlaceholders("signature", "issuer", "owner", "asset_name", "description", "quantity", "is_divisible"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement transferAssetPStmt = c
|
2018-05-27 14:59:30 +01:00
|
|
|
.prepareStatement("INSERT INTO TransferAssetTransactions " + formatWithPlaceholders("signature", "sender", "recipient", "asset_id", "amount"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement createAssetOrderPStmt = c.prepareStatement("INSERT INTO CreateAssetOrderTransactions "
|
2018-05-27 14:59:30 +01:00
|
|
|
+ formatWithPlaceholders("signature", "creator", "have_asset_id", "amount", "want_asset_id", "price"));
|
2018-05-16 11:46:44 +01:00
|
|
|
PreparedStatement cancelAssetOrderPStmt = c
|
2018-06-19 16:49:42 +01:00
|
|
|
.prepareStatement("INSERT INTO CancelAssetOrderTransactions " + formatWithPlaceholders("signature", "creator", "asset_order_id"));
|
2018-05-16 11:46:44 +01:00
|
|
|
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"));
|
|
|
|
PreparedStatement messagePStmt = c.prepareStatement("INSERT INTO MessageTransactions "
|
2018-06-04 11:45:40 +01:00
|
|
|
+ formatWithPlaceholders("signature", "version", "sender", "recipient", "is_text", "is_encrypted", "amount", "asset_id", "data"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
PreparedStatement sharedPaymentPStmt = c
|
2018-05-27 14:59:30 +01:00
|
|
|
.prepareStatement("INSERT INTO SharedTransactionPayments " + formatWithPlaceholders("signature", "recipient", "amount", "asset_id"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
PreparedStatement blockTxPStmt = c
|
|
|
|
.prepareStatement("INSERT INTO BlockTransactions " + formatWithPlaceholders("block_signature", "sequence", "transaction_signature"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
int height;
|
|
|
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
|
|
|
BlockRepository blockRepository = repository.getBlockRepository();
|
|
|
|
height = blockRepository.getBlockchainHeight() + 1;
|
|
|
|
}
|
|
|
|
|
2018-05-16 11:46:44 +01:00
|
|
|
byte[] milestone_block = null;
|
2018-05-24 11:26:59 +01:00
|
|
|
System.out.println("Starting migration from block height " + height);
|
|
|
|
|
2018-05-16 11:46:44 +01:00
|
|
|
while (true) {
|
|
|
|
JSONObject json = (JSONObject) fetchBlockJSON(height);
|
|
|
|
if (json == null)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (height % 1000 == 0)
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
System.out.println("Height: " + height + ", public key map size: " + publicKeyByAddress.size());
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
JSONArray transactions = (JSONArray) json.get("transactions");
|
|
|
|
|
|
|
|
// Blocks:
|
2018-05-25 11:48:47 +01:00
|
|
|
// signature, version, reference, transaction_count, total_fees, transactions_signature, height, generation, generating_balance, generator,
|
|
|
|
// generator_signature
|
2018-05-16 11:46:44 +01:00
|
|
|
// varchar, tinyint, varchar, int, decimal, varchar, int, timestamp, decimal, varchar, varchar
|
|
|
|
byte[] blockSignature = Base58.decode((String) json.get("signature"));
|
|
|
|
byte[] blockReference = Base58.decode((String) json.get("reference"));
|
|
|
|
byte[] blockTransactionsSignature = Base58.decode((String) json.get("transactionsSignature"));
|
|
|
|
byte[] blockGeneratorSignature = Base58.decode((String) json.get("generatorSignature"));
|
|
|
|
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
byte[] generatorPublicKey = addressToPublicKey((String) json.get("generator"));
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
blocksPStmt.setBytes(1, blockSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
blocksPStmt.setInt(2, ((Long) json.get("version")).intValue());
|
2018-06-19 16:49:42 +01:00
|
|
|
blocksPStmt.setBytes(3, blockReference);
|
2018-05-16 11:46:44 +01:00
|
|
|
blocksPStmt.setInt(4, transactions.size());
|
|
|
|
blocksPStmt.setBigDecimal(5, BigDecimal.valueOf(Double.valueOf((String) json.get("fee")).doubleValue()));
|
2018-06-19 16:49:42 +01:00
|
|
|
blocksPStmt.setBytes(6, blockTransactionsSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
blocksPStmt.setInt(7, height);
|
|
|
|
blocksPStmt.setTimestamp(8, new Timestamp((Long) json.get("timestamp")));
|
|
|
|
blocksPStmt.setBigDecimal(9, BigDecimal.valueOf((Long) json.get("generatingBalance")));
|
2018-06-19 16:49:42 +01:00
|
|
|
blocksPStmt.setBytes(10, generatorPublicKey);
|
|
|
|
blocksPStmt.setBytes(11, blockGeneratorSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
String blockATs = (String) json.get("blockATs");
|
|
|
|
if (blockATs != null && blockATs.length() > 0) {
|
|
|
|
HashCode atBytes = HashCode.fromString(blockATs);
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
blocksPStmt.setBytes(12, atBytes.asBytes());
|
2018-05-16 11:46:44 +01:00
|
|
|
blocksPStmt.setBigDecimal(13, BigDecimal.valueOf(((Long) json.get("atFees")).longValue(), 8));
|
|
|
|
} else {
|
|
|
|
blocksPStmt.setNull(12, java.sql.Types.VARBINARY);
|
|
|
|
blocksPStmt.setNull(13, java.sql.Types.DECIMAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
blocksPStmt.execute();
|
|
|
|
blocksPStmt.clearParameters();
|
|
|
|
|
|
|
|
// Transactions:
|
|
|
|
// signature, reference, type, creator, creation, fee, milestone_block
|
|
|
|
// varchar, varchar, int, varchar, timestamp, decimal, varchar
|
|
|
|
for (int txIndex = 0; txIndex < transactions.size(); ++txIndex) {
|
|
|
|
JSONObject transaction = (JSONObject) transactions.get(txIndex);
|
|
|
|
|
|
|
|
byte[] txSignature = Base58.decode((String) transaction.get("signature"));
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
String txReference58 = (String) transaction.get("reference");
|
|
|
|
byte[] txReference = txReference58.isEmpty() ? null : Base58.decode(txReference58);
|
|
|
|
int type = ((Long) transaction.get("type")).intValue();
|
|
|
|
|
|
|
|
if (txReference != null)
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(2, txReference);
|
2018-05-16 11:46:44 +01:00
|
|
|
else if (height == 1 && type == 1)
|
2018-05-24 11:26:59 +01:00
|
|
|
txPStmt.setNull(2, java.sql.Types.VARBINARY); // genesis transactions only
|
2018-05-16 11:46:44 +01:00
|
|
|
else
|
|
|
|
fail();
|
|
|
|
|
|
|
|
txPStmt.setInt(3, type);
|
|
|
|
|
More work on Blocks, refactor to using public key in DB, etc.
Added brokenmd160.java as command-line support for producing broken MD160 digests.
Transactions, and sub-classes, now use/store public key instead of Qora address.
(Qora address can be derived from public key and they take up about the same space in DB).
Loads more JavaDoc for lovely mouseover help in Eclipse IDE.
Crypto.verify() and Crypto.sign() moved into PublicKeyAccount and PrivateKeyAccount
as appropriate.
Fleshed out Block, added BlockTransactions support.
Added TODO comments as Eclipse helpfully lists these for later implementation.
Made loading-from-DB-constructors protected/private and also throw NoDataFoundException
if unable to load from DB. Public methods can call respective constructors, catch the above
exception and return null if they like. Load-from-DB-constructors are to allow sub-classes
to load some data from sub-tables and super-class to load from another table.
(See PaymentTransaction/Transaction for example). Using public methods allows similar argument
lists but with different names,
e.g. DBObject.fromSignature(Connection, byte[]) and DBObject.fromReference(Connection, byte[])
Saving into DB maybe still a bit untidy. Looking for a way to close-couple column names with
place-holder bind Objects.
Less of:
connection.prepareStatement("INSERT INTO table (column) VALUES (?)")
DB.bindInsertPlaceholders(PreparedStatement, Object...);
More like:
DB.insertUpdate(String tableName, SomeMagicCloseCoupledPairs...)
called like:
DB.insertUpdate("Cats", {"name", "Tiddles"}, {"age", 3});
2018-05-17 17:39:55 +01:00
|
|
|
// Determine transaction "creator" from specific transaction info
|
2018-05-16 11:46:44 +01:00
|
|
|
switch (type) {
|
|
|
|
case 1: // genesis
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, GENESIS_PUBLICKEY); // genesis transactions only
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: // payment
|
|
|
|
case 12: // transfer asset
|
|
|
|
case 15: // multi-payment
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("sender")));
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: // register name
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("registrant")));
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4: // update name
|
|
|
|
case 5: // sell name
|
|
|
|
case 6: // cancel sell name
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("owner")));
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 7: // buy name
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("buyer")));
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 8: // create poll
|
|
|
|
case 9: // vote on poll
|
|
|
|
case 10: // arbitrary transaction
|
|
|
|
case 11: // issue asset
|
|
|
|
case 13: // create asset order
|
|
|
|
case 14: // cancel asset order
|
|
|
|
case 16: // deploy CIYAM AT
|
|
|
|
case 17: // message
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(4, addressToPublicKey((String) transaction.get("creator")));
|
2018-05-16 11:46:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
|
2018-06-04 11:45:40 +01:00
|
|
|
long transactionTimestamp = ((Long) transaction.get("timestamp")).longValue();
|
|
|
|
txPStmt.setTimestamp(5, new Timestamp(transactionTimestamp));
|
2018-05-16 11:46:44 +01:00
|
|
|
txPStmt.setBigDecimal(6, BigDecimal.valueOf(Double.valueOf((String) transaction.get("fee")).doubleValue()));
|
|
|
|
|
|
|
|
if (milestone_block != null)
|
2018-06-19 16:49:42 +01:00
|
|
|
txPStmt.setBytes(7, milestone_block);
|
2018-05-16 11:46:44 +01:00
|
|
|
else if (height == 1 && type == 1)
|
2018-05-24 11:26:59 +01:00
|
|
|
txPStmt.setNull(7, java.sql.Types.VARBINARY); // genesis transactions only
|
2018-05-16 11:46:44 +01:00
|
|
|
else
|
|
|
|
fail();
|
|
|
|
|
|
|
|
txPStmt.execute();
|
|
|
|
txPStmt.clearParameters();
|
|
|
|
|
|
|
|
JSONArray multiPayments = null;
|
|
|
|
if (type == 15)
|
|
|
|
multiPayments = (JSONArray) transaction.get("payments");
|
|
|
|
|
|
|
|
List<String> recipients = new ArrayList<String>();
|
|
|
|
switch (type) {
|
|
|
|
case 1: // genesis
|
|
|
|
case 2: // payment
|
|
|
|
case 12: // transfer asset
|
|
|
|
case 17: // message
|
|
|
|
recipients.add((String) transaction.get("recipient"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: // register name
|
|
|
|
case 4: // update name
|
|
|
|
// parse Name data for "owner"
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5: // sell name
|
|
|
|
case 6: // cancel sell name
|
|
|
|
case 8: // create poll
|
|
|
|
case 9: // vote on poll
|
|
|
|
case 10: // arbitrary transaction
|
|
|
|
case 13: // create asset order
|
|
|
|
case 14: // cancel asset order
|
|
|
|
case 16: // deploy CIYAM AT
|
|
|
|
// no recipients
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7: // buy name
|
|
|
|
recipients.add((String) transaction.get("seller"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 11: // issue asset
|
|
|
|
recipients.add((String) transaction.get("creator"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 15: // multi-payment
|
|
|
|
assertNotNull(multiPayments);
|
|
|
|
for (Object payment : multiPayments) {
|
|
|
|
String recipient = (String) ((JSONObject) payment).get("recipient");
|
|
|
|
recipients.add(recipient);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (String recipient : recipients) {
|
2018-06-19 16:49:42 +01:00
|
|
|
recipientPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
recipientPStmt.setString(2, recipient);
|
|
|
|
|
|
|
|
recipientPStmt.execute();
|
|
|
|
recipientPStmt.clearParameters();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction-type-specific processing
|
|
|
|
switch (type) {
|
|
|
|
case 1: // genesis
|
2018-06-19 16:49:42 +01:00
|
|
|
genesisPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
genesisPStmt.setString(2, recipients.get(0));
|
|
|
|
genesisPStmt.setBigDecimal(3, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue()));
|
|
|
|
|
|
|
|
genesisPStmt.execute();
|
|
|
|
genesisPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: // payment
|
2018-06-19 16:49:42 +01:00
|
|
|
paymentPStmt.setBytes(1, txSignature);
|
|
|
|
paymentPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender")));
|
2018-05-16 11:46:44 +01:00
|
|
|
paymentPStmt.setString(3, recipients.get(0));
|
|
|
|
paymentPStmt.setBigDecimal(4, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue()));
|
|
|
|
|
|
|
|
paymentPStmt.execute();
|
|
|
|
paymentPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: // register name
|
2018-06-19 16:49:42 +01:00
|
|
|
registerNamePStmt.setBytes(1, txSignature);
|
|
|
|
registerNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("registrant")));
|
2018-05-16 11:46:44 +01:00
|
|
|
registerNamePStmt.setString(3, (String) transaction.get("name"));
|
|
|
|
registerNamePStmt.setString(4, (String) transaction.get("owner"));
|
|
|
|
registerNamePStmt.setString(5, (String) transaction.get("value"));
|
|
|
|
|
|
|
|
registerNamePStmt.execute();
|
|
|
|
registerNamePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4: // update name
|
2018-06-19 16:49:42 +01:00
|
|
|
updateNamePStmt.setBytes(1, txSignature);
|
|
|
|
updateNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner")));
|
2018-05-16 11:46:44 +01:00
|
|
|
updateNamePStmt.setString(3, (String) transaction.get("name"));
|
|
|
|
updateNamePStmt.setString(4, (String) transaction.get("newOwner"));
|
|
|
|
updateNamePStmt.setString(5, (String) transaction.get("newValue"));
|
2018-07-05 16:24:05 +01:00
|
|
|
updateNamePStmt.setBytes(6, txSignature); // dummy value for name_reference
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
updateNamePStmt.execute();
|
|
|
|
updateNamePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5: // sell name
|
2018-06-19 16:49:42 +01:00
|
|
|
sellNamePStmt.setBytes(1, txSignature);
|
|
|
|
sellNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner")));
|
2018-05-16 11:46:44 +01:00
|
|
|
sellNamePStmt.setString(3, (String) transaction.get("name"));
|
|
|
|
sellNamePStmt.setBigDecimal(4, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue()));
|
|
|
|
|
|
|
|
sellNamePStmt.execute();
|
|
|
|
sellNamePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6: // cancel sell name
|
2018-06-19 16:49:42 +01:00
|
|
|
cancelSellNamePStmt.setBytes(1, txSignature);
|
|
|
|
cancelSellNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("owner")));
|
2018-05-16 11:46:44 +01:00
|
|
|
cancelSellNamePStmt.setString(3, (String) transaction.get("name"));
|
|
|
|
|
|
|
|
cancelSellNamePStmt.execute();
|
|
|
|
cancelSellNamePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7: // buy name
|
2018-06-19 16:49:42 +01:00
|
|
|
buyNamePStmt.setBytes(1, txSignature);
|
|
|
|
buyNamePStmt.setBytes(2, addressToPublicKey((String) transaction.get("buyer")));
|
2018-05-16 11:46:44 +01:00
|
|
|
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()));
|
2018-07-05 16:24:05 +01:00
|
|
|
buyNamePStmt.setBytes(6, txSignature); // dummy value for name_reference
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
buyNamePStmt.execute();
|
|
|
|
buyNamePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8: // create poll
|
2018-06-19 16:49:42 +01:00
|
|
|
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"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
createPollPStmt.execute();
|
|
|
|
createPollPStmt.clearParameters();
|
|
|
|
|
|
|
|
// options
|
|
|
|
JSONArray options = (JSONArray) transaction.get("options");
|
|
|
|
for (Object option : options) {
|
2018-06-19 16:49:42 +01:00
|
|
|
createPollOptionPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
createPollOptionPStmt.setString(2, (String) option);
|
|
|
|
|
|
|
|
createPollOptionPStmt.execute();
|
|
|
|
createPollOptionPStmt.clearParameters();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 9: // vote on poll
|
2018-06-19 16:49:42 +01:00
|
|
|
voteOnPollPStmt.setBytes(1, txSignature);
|
|
|
|
voteOnPollPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator")));
|
2018-05-16 11:46:44 +01:00
|
|
|
voteOnPollPStmt.setString(3, (String) transaction.get("poll"));
|
|
|
|
voteOnPollPStmt.setInt(4, ((Long) transaction.get("option")).intValue());
|
|
|
|
|
|
|
|
voteOnPollPStmt.execute();
|
|
|
|
voteOnPollPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 10: // arbitrary transactions
|
2018-06-19 16:49:42 +01:00
|
|
|
arbitraryPStmt.setBytes(1, txSignature);
|
|
|
|
arbitraryPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator")));
|
2018-05-16 11:46:44 +01:00
|
|
|
arbitraryPStmt.setInt(3, ((Long) transaction.get("service")).intValue());
|
|
|
|
arbitraryPStmt.setString(4, "TODO");
|
|
|
|
|
|
|
|
arbitraryPStmt.execute();
|
|
|
|
arbitraryPStmt.clearParameters();
|
|
|
|
|
|
|
|
if (multiPayments != null)
|
|
|
|
for (Object paymentObj : multiPayments) {
|
|
|
|
JSONObject payment = (JSONObject) paymentObj;
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
sharedPaymentPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
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());
|
|
|
|
|
|
|
|
sharedPaymentPStmt.execute();
|
|
|
|
sharedPaymentPStmt.clearParameters();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 11: // issue asset
|
2018-06-19 16:49:42 +01:00
|
|
|
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
|
2018-06-06 09:52:42 +01:00
|
|
|
issueAssetPStmt.setString(4, (String) transaction.get("name"));
|
|
|
|
issueAssetPStmt.setString(5, (String) transaction.get("description"));
|
|
|
|
issueAssetPStmt.setBigDecimal(6, BigDecimal.valueOf(((Long) transaction.get("quantity")).longValue()));
|
|
|
|
issueAssetPStmt.setBoolean(7, (Boolean) transaction.get("divisible"));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
issueAssetPStmt.execute();
|
|
|
|
issueAssetPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12: // transfer asset
|
2018-06-19 16:49:42 +01:00
|
|
|
transferAssetPStmt.setBytes(1, txSignature);
|
|
|
|
transferAssetPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender")));
|
2018-05-16 11:46:44 +01:00
|
|
|
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()));
|
|
|
|
|
|
|
|
transferAssetPStmt.execute();
|
|
|
|
transferAssetPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 13: // create asset order
|
2018-06-19 16:49:42 +01:00
|
|
|
createAssetOrderPStmt.setBytes(1, txSignature);
|
|
|
|
createAssetOrderPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator")));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
JSONObject assetOrder = (JSONObject) transaction.get("order");
|
|
|
|
createAssetOrderPStmt.setLong(3, ((Long) assetOrder.get("have")).longValue());
|
|
|
|
createAssetOrderPStmt.setBigDecimal(4, BigDecimal.valueOf(Double.valueOf((String) assetOrder.get("amount")).doubleValue()));
|
|
|
|
createAssetOrderPStmt.setLong(5, ((Long) assetOrder.get("want")).longValue());
|
|
|
|
createAssetOrderPStmt.setBigDecimal(6, BigDecimal.valueOf(Double.valueOf((String) assetOrder.get("price")).doubleValue()));
|
|
|
|
|
|
|
|
createAssetOrderPStmt.execute();
|
|
|
|
createAssetOrderPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14: // cancel asset order
|
2018-06-19 16:49:42 +01:00
|
|
|
cancelAssetOrderPStmt.setBytes(1, txSignature);
|
|
|
|
cancelAssetOrderPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator")));
|
|
|
|
cancelAssetOrderPStmt.setBytes(3, Base58.decode((String) transaction.get("order")));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
cancelAssetOrderPStmt.execute();
|
|
|
|
cancelAssetOrderPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 15: // multi-payment
|
2018-06-19 16:49:42 +01:00
|
|
|
multiPaymentPStmt.setBytes(1, txSignature);
|
|
|
|
multiPaymentPStmt.setBytes(2, addressToPublicKey((String) transaction.get("sender")));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
multiPaymentPStmt.execute();
|
|
|
|
multiPaymentPStmt.clearParameters();
|
|
|
|
|
|
|
|
for (Object paymentObj : multiPayments) {
|
|
|
|
JSONObject payment = (JSONObject) paymentObj;
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
sharedPaymentPStmt.setBytes(1, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
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());
|
|
|
|
|
|
|
|
sharedPaymentPStmt.execute();
|
|
|
|
sharedPaymentPStmt.clearParameters();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 16: // deploy AT
|
|
|
|
HashCode creationBytes = HashCode.fromString((String) transaction.get("creationBytes"));
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
deployATPStmt.setBytes(1, txSignature);
|
|
|
|
deployATPStmt.setBytes(2, addressToPublicKey((String) transaction.get("creator")));
|
2018-05-16 11:46:44 +01:00
|
|
|
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"));
|
2018-06-19 16:49:42 +01:00
|
|
|
deployATPStmt.setBytes(7, creationBytes.asBytes());
|
2018-05-16 11:46:44 +01:00
|
|
|
deployATPStmt.setBigDecimal(8, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue()));
|
|
|
|
|
|
|
|
deployATPStmt.execute();
|
|
|
|
deployATPStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 17: // message
|
|
|
|
boolean isText = (Boolean) transaction.get("isText");
|
|
|
|
boolean isEncrypted = (Boolean) transaction.get("encrypted");
|
|
|
|
String messageData = (String) transaction.get("data");
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
byte[] messageDataBytes;
|
2018-05-16 11:46:44 +01:00
|
|
|
if (isText && !isEncrypted) {
|
2018-06-19 16:49:42 +01:00
|
|
|
messageDataBytes = messageData.getBytes("UTF-8");
|
2018-05-16 11:46:44 +01:00
|
|
|
} else {
|
|
|
|
HashCode messageBytes = HashCode.fromString(messageData);
|
2018-06-19 16:49:42 +01:00
|
|
|
messageDataBytes = messageBytes.asBytes();
|
2018-05-16 11:46:44 +01:00
|
|
|
}
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
messagePStmt.setBytes(1, txSignature);
|
2018-06-13 16:48:28 +01:00
|
|
|
messagePStmt.setInt(2, Transaction.getVersionByTimestamp(transactionTimestamp));
|
2018-06-19 16:49:42 +01:00
|
|
|
messagePStmt.setBytes(3, addressToPublicKey((String) transaction.get("creator")));
|
2018-06-04 11:45:40 +01:00
|
|
|
messagePStmt.setString(4, (String) transaction.get("recipient"));
|
|
|
|
messagePStmt.setBoolean(5, isText);
|
|
|
|
messagePStmt.setBoolean(6, isEncrypted);
|
|
|
|
messagePStmt.setBigDecimal(7, BigDecimal.valueOf(Double.valueOf((String) transaction.get("amount")).doubleValue()));
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
if (transaction.containsKey("asset"))
|
2018-06-04 11:45:40 +01:00
|
|
|
messagePStmt.setLong(8, ((Long) transaction.get("asset")).longValue());
|
2018-05-16 11:46:44 +01:00
|
|
|
else
|
2018-06-04 11:45:40 +01:00
|
|
|
messagePStmt.setLong(8, 0L); // QORA simulated asset
|
2018-05-16 11:46:44 +01:00
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
messagePStmt.setBytes(9, messageDataBytes);
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
messagePStmt.execute();
|
|
|
|
messagePStmt.clearParameters();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// fail();
|
|
|
|
}
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
blockTxPStmt.setBytes(1, blockSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
blockTxPStmt.setInt(2, txIndex);
|
2018-06-19 16:49:42 +01:00
|
|
|
blockTxPStmt.setBytes(3, txSignature);
|
2018-05-16 11:46:44 +01:00
|
|
|
|
|
|
|
blockTxPStmt.execute();
|
|
|
|
blockTxPStmt.clearParameters();
|
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
// repository.saveChanges();
|
2018-05-16 11:46:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// new milestone block every 500 blocks?
|
|
|
|
if (milestone_block == null || (height % 500) == 0)
|
|
|
|
milestone_block = blockSignature;
|
|
|
|
|
|
|
|
++height;
|
|
|
|
}
|
2018-05-24 11:26:59 +01:00
|
|
|
|
2018-06-19 16:49:42 +01:00
|
|
|
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();
|
2018-05-16 11:46:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|