mirror of https://github.com/qortal/qortal
Browse Source
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});pull/67/head
catbref
6 years ago
20 changed files with 698 additions and 181 deletions
@ -0,0 +1,21 @@
|
||||
import com.google.common.hash.HashCode; |
||||
|
||||
import qora.crypto.BrokenMD160; |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
public class brokenmd160 { |
||||
|
||||
public static void main(String args[]) { |
||||
if (args.length == 0) { |
||||
System.err.println("usage: broken-md160 <hex>\noutputs: hex"); |
||||
System.exit(1); |
||||
} |
||||
|
||||
byte[] raw = HashCode.fromString(args[0]).asBytes(); |
||||
BrokenMD160 brokenMD160 = new BrokenMD160(); |
||||
byte[] digest = brokenMD160.digest(raw); |
||||
|
||||
System.out.println(HashCode.fromBytes(digest).toString()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,150 @@
|
||||
package qora.block; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
|
||||
import org.json.simple.JSONObject; |
||||
|
||||
import database.DB; |
||||
import database.NoDataFoundException; |
||||
import qora.transaction.Transaction; |
||||
import qora.transaction.TransactionFactory; |
||||
|
||||
public class BlockTransaction { |
||||
|
||||
// Database properties shared with all transaction types
|
||||
protected byte[] blockSignature; |
||||
protected int sequence; |
||||
protected byte[] transactionSignature; |
||||
|
||||
// Constructors
|
||||
|
||||
protected BlockTransaction(byte[] blockSignature, int sequence, byte[] transactionSignature) { |
||||
this.blockSignature = blockSignature; |
||||
this.sequence = sequence; |
||||
this.transactionSignature = transactionSignature; |
||||
} |
||||
|
||||
// Getters/setters
|
||||
|
||||
public byte[] getBlockSignature() { |
||||
return this.blockSignature; |
||||
} |
||||
|
||||
public int getSequence() { |
||||
return this.sequence; |
||||
} |
||||
|
||||
public byte[] getTransactionSignature() { |
||||
return this.transactionSignature; |
||||
} |
||||
|
||||
// More information
|
||||
|
||||
// Load/Save
|
||||
|
||||
protected BlockTransaction(Connection connection, byte[] blockSignature, int sequence) throws SQLException { |
||||
// Can't use DB.executeUsingBytes() here as we need two placeholders
|
||||
PreparedStatement preparedStatement = connection |
||||
.prepareStatement("SELECT transaction_signature FROM BlockTransactions WHERE block_signature = ? and sequence = ?"); |
||||
preparedStatement.setBinaryStream(1, new ByteArrayInputStream(blockSignature)); |
||||
preparedStatement.setInt(2, sequence); |
||||
|
||||
ResultSet rs = DB.checkedExecute(preparedStatement); |
||||
if (rs == null) |
||||
throw new NoDataFoundException(); |
||||
|
||||
this.blockSignature = blockSignature; |
||||
this.sequence = sequence; |
||||
this.transactionSignature = DB.getResultSetBytes(rs.getBinaryStream(1), Transaction.SIGNATURE_LENGTH); |
||||
} |
||||
|
||||
protected BlockTransaction(Connection connection, byte[] transactionSignature) throws SQLException { |
||||
ResultSet rs = DB.executeUsingBytes(connection, "SELECT block_signature, sequence FROM BlockTransactions WHERE transaction_signature = ?", |
||||
transactionSignature); |
||||
if (rs == null) |
||||
throw new NoDataFoundException(); |
||||
|
||||
this.blockSignature = DB.getResultSetBytes(rs.getBinaryStream(1), Block.BLOCK_SIGNATURE_LENGTH); |
||||
this.sequence = rs.getInt(2); |
||||
this.transactionSignature = transactionSignature; |
||||
} |
||||
|
||||
/** |
||||
* Load BlockTransaction from DB using block signature and tx-in-block sequence. |
||||
* |
||||
* @param connection |
||||
* @param blockSignature |
||||
* @param sequence |
||||
* @return BlockTransaction, or null if not found |
||||
* @throws SQLException |
||||
*/ |
||||
public static BlockTransaction fromBlockSignature(Connection connection, byte[] blockSignature, int sequence) throws SQLException { |
||||
try { |
||||
return new BlockTransaction(connection, blockSignature, sequence); |
||||
} catch (NoDataFoundException e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Load BlockTransaction from DB using transaction signature. |
||||
* |
||||
* @param connection |
||||
* @param transactionSignature |
||||
* @return BlockTransaction, or null if not found |
||||
* @throws SQLException |
||||
*/ |
||||
public static BlockTransaction fromTransactionSignature(Connection connection, byte[] transactionSignature) throws SQLException { |
||||
try { |
||||
return new BlockTransaction(connection, transactionSignature); |
||||
} catch (NoDataFoundException e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
protected void save(Connection connection) throws SQLException { |
||||
String sql = DB.formatInsertWithPlaceholders("BlockTransactions", "block_signature", "sequence", "transaction_signature"); |
||||
PreparedStatement preparedStatement = connection.prepareStatement(sql); |
||||
DB.bindInsertPlaceholders(preparedStatement, this.blockSignature, this.sequence, this.transactionSignature); |
||||
preparedStatement.execute(); |
||||
} |
||||
|
||||
// Navigation
|
||||
|
||||
/** |
||||
* Load corresponding Block from DB. |
||||
* |
||||
* @param connection |
||||
* @return Block, or null if not found (which should never happen) |
||||
* @throws SQLException |
||||
*/ |
||||
public Block getBlock(Connection connection) throws SQLException { |
||||
return Block.fromSignature(connection, this.blockSignature); |
||||
} |
||||
|
||||
/** |
||||
* Load corresponding Transaction from DB. |
||||
* |
||||
* @param connection |
||||
* @return Transaction, or null if not found (which should never happen) |
||||
* @throws SQLException |
||||
*/ |
||||
public Transaction getTransaction(Connection connection) throws SQLException { |
||||
return TransactionFactory.fromSignature(connection, this.transactionSignature); |
||||
} |
||||
|
||||
// Converters
|
||||
|
||||
public JSONObject toJSON() { |
||||
// TODO
|
||||
return null; |
||||
} |
||||
|
||||
// Processing
|
||||
|
||||
} |
@ -0,0 +1,54 @@
|
||||
package test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
import qora.block.Block; |
||||
import qora.transaction.PaymentTransaction; |
||||
import utils.Base58; |
||||
|
||||
public class navigation { |
||||
|
||||
private static Connection connection; |
||||
|
||||
@Before |
||||
public void connect() throws SQLException { |
||||
connection = common.getConnection(); |
||||
} |
||||
|
||||
@After |
||||
public void disconnect() { |
||||
try { |
||||
connection.createStatement().execute("SHUTDOWN"); |
||||
} catch (SQLException e) { |
||||
fail(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testNavigateFromTransactionToBlock() throws SQLException { |
||||
String signature58 = "1211ZPwG3hk5evWzXCZi9hMDRpwumWmkENjwWkeTCik9xA5uoYnxzF7rwR5hmHH3kG2RXo7ToCAaRc7dvnynByJt"; |
||||
byte[] signature = Base58.decode(signature58); |
||||
|
||||
System.out.println("Navigating to Block from transaction " + signature58); |
||||
|
||||
PaymentTransaction paymentTransaction = PaymentTransaction.fromSignature(connection, signature); |
||||
|
||||
assertNotNull(paymentTransaction); |
||||
|
||||
Block block = paymentTransaction.getBlock(connection); |
||||
|
||||
assertNotNull(block); |
||||
|
||||
System.out.println("Block " + block.getHeight() + ", signature: " + Base58.encode(block.getSignature())); |
||||
|
||||
assertEquals(49778, block.getHeight()); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue