diff --git a/src/data/block/Block.java b/src/data/block/Block.java new file mode 100644 index 00000000..20f9944c --- /dev/null +++ b/src/data/block/Block.java @@ -0,0 +1,86 @@ +package data.block; + +import java.math.BigDecimal; + +import qora.account.PublicKeyAccount; + +public class Block implements IBlockData { + private int version; + private byte[] reference; + private int transactionCount; + private BigDecimal totalFees; + private byte[] transactionsSignature; + private int height; + private long timestamp; + private BigDecimal generatingBalance; + private byte[] generatorPublicKey; + private byte[] generatorSignature; + private byte[] atBytes; + private BigDecimal atFees; + + public Block(int version, byte[] reference, int transactionCount, BigDecimal totalFees, byte[] transactionsSignature, + int height, long timestamp, BigDecimal generatingBalance, byte[] generatorPublicKey, byte[] generatorSignature, + byte[] atBytes, BigDecimal atFees) + { + this.version = version; + this.reference = reference; + this.transactionCount = transactionCount; + this.totalFees = totalFees; + this.transactionsSignature = transactionsSignature; + this.height = height; + this.timestamp = timestamp; + this.generatingBalance = generatingBalance; + this.generatorPublicKey = generatorPublicKey; + this.generatorSignature = generatorSignature; + this.atBytes = atBytes; + this.atFees = atFees; + } + + public int getVersion() { + return version; + } + + public byte[] getReference() { + return reference; + } + + public int getTransactionCount() { + return transactionCount; + } + + public BigDecimal getTotalFees() { + return totalFees; + } + + public byte[] getTransactionsSignature() { + return transactionsSignature; + } + + public int getHeight() { + return height; + } + + public long getTimestamp() { + return timestamp; + } + + public BigDecimal getGeneratingBalance() { + return generatingBalance; + } + + public byte[] getGeneratorPublicKey() { + return generatorPublicKey; + } + + public byte[] getGeneratorSignature() { + return generatorSignature; + } + + public byte[] getAtBytes() { + return atBytes; + } + + public BigDecimal getAtFees() { + return atFees; + } +} diff --git a/src/data/block/IBlockData.java b/src/data/block/IBlockData.java new file mode 100644 index 00000000..e1b7979f --- /dev/null +++ b/src/data/block/IBlockData.java @@ -0,0 +1,18 @@ +package data.block; + +import java.math.BigDecimal; + +public interface IBlockData { + public int getVersion(); + public byte[] getReference(); + public int getTransactionCount(); + public BigDecimal getTotalFees(); + public byte[] getTransactionsSignature(); + public int getHeight(); + public long getTimestamp(); + public BigDecimal getGeneratingBalance(); + public byte[] getGeneratorPublicKey(); + public byte[] getGeneratorSignature(); + public byte[] getAtBytes(); + public BigDecimal getAtFees(); +} diff --git a/src/data/repository/HSQLDBRepository.java b/src/data/repository/HSQLDBRepository.java new file mode 100644 index 00000000..f4caf3bd --- /dev/null +++ b/src/data/repository/HSQLDBRepository.java @@ -0,0 +1,52 @@ +package data.repository; + +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; + +import data.block.Block; +import data.block.IBlockData; +import database.DB; +import qora.account.PublicKeyAccount; + +public class HSQLDBRepository implements IRepository +{ + protected static final int TRANSACTIONS_SIGNATURE_LENGTH = 64; + protected static final int GENERATOR_SIGNATURE_LENGTH = 64; + protected static final int REFERENCE_LENGTH = GENERATOR_SIGNATURE_LENGTH + TRANSACTIONS_SIGNATURE_LENGTH; + + private static final String BLOCK_DB_COLUMNS = "version, reference, transaction_count, total_fees, " + + "transactions_signature, height, generation, generating_balance, generator, generator_signature, AT_data, AT_fees"; + + public IBlockData getBlockBySignature(byte[] signature) throws SQLException + { + ResultSet rs = DB.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ?", signature); + return getBlockFromResultSet(rs); + } + + public IBlockData getBlockByHeight(int height) throws SQLException + { + ResultSet rs = DB.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE height = ?", height); + return getBlockFromResultSet(rs); + } + + private IBlockData getBlockFromResultSet(ResultSet rs) throws SQLException { + int version = rs.getInt(1); + byte[] reference = DB.getResultSetBytes(rs.getBinaryStream(2), REFERENCE_LENGTH); + int transactionCount = rs.getInt(3); + BigDecimal totalFees = rs.getBigDecimal(4); + byte[] transactionsSignature = DB.getResultSetBytes(rs.getBinaryStream(5), TRANSACTIONS_SIGNATURE_LENGTH); + int height = rs.getInt(6); + long timestamp = rs.getTimestamp(7).getTime(); + BigDecimal generatingBalance = rs.getBigDecimal(8); + byte[] generatorPublicKey = DB.getResultSetBytes(rs.getBinaryStream(9)); + byte[] generatorSignature = DB.getResultSetBytes(rs.getBinaryStream(10), GENERATOR_SIGNATURE_LENGTH); + byte[] atBytes = DB.getResultSetBytes(rs.getBinaryStream(11)); + BigDecimal atFees = rs.getBigDecimal(12); + + return new Block(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, + generatingBalance,generatorPublicKey, generatorSignature, atBytes, atFees); + } +} diff --git a/src/data/repository/IRepository.java b/src/data/repository/IRepository.java new file mode 100644 index 00000000..eb4a3c8c --- /dev/null +++ b/src/data/repository/IRepository.java @@ -0,0 +1,9 @@ +package data.repository; + +import data.block.IBlockData; + +public interface IRepository { + // XXX use NoDataFoundException? + IBlockData getBlockBySignature(byte[] signature) throws Exception; + IBlockData getBlockByHeight(int height) throws Exception; +} diff --git a/src/qora/block/BlockFactory.java b/src/qora/block/BlockFactory.java index 96e5d172..ac6a3c63 100644 --- a/src/qora/block/BlockFactory.java +++ b/src/qora/block/BlockFactory.java @@ -1,13 +1,25 @@ package qora.block; +import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import data.block.IBlockData; +import data.repository.HSQLDBRepository; +import data.repository.IRepository; import database.DB; import database.NoDataFoundException; +import qora.account.PublicKeyAccount; +import qora.transaction.Transaction; +import qora.transaction.TransactionFactory; public class BlockFactory { + // XXX repository should be pushed here from the root entry, no need to know the repository type + private static IRepository repository = new HSQLDBRepository(); + /** * Load Block from DB using block signature. * @@ -35,16 +47,23 @@ public class BlockFactory { * @return ? extends Block, or null if not found * @throws SQLException */ - public static Block fromHeight(int height) throws SQLException { + public static Block fromHeight(int height) { if (height == 1) return GenesisBlock.getInstance(); - PreparedStatement preparedStatement = DB.getConnection().prepareStatement("SELECT signature FROM Blocks WHERE height = ?"); - preparedStatement.setInt(1, height); - try { - return new Block(DB.checkedExecute(preparedStatement)); - } catch (NoDataFoundException e) { + IBlockData data = repository.getBlockByHeight(height); + + // TODO fill this list from TransactionFactory + List transactions = new ArrayList(); + + // TODO fetch account for data.getGeneratorPublicKey() + PublicKeyAccount generator = null; + + return new Block(data.getVersion(), data.getReference(), data.getTimestamp(), data.getGeneratingBalance(), + generator,data.getGeneratorSignature(),data.getTransactionsSignature(), + data.getAtBytes(), data.getAtFees(), transactions); + } catch (Exception e) { // XXX move NoDataFoundException to repository domain and use it here? return null; } }