forked from Qortal/qortal
commit
6c33cfed74
86
src/data/block/Block.java
Normal file
86
src/data/block/Block.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package data.block;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import qora.account.PublicKeyAccount;
|
||||||
|
|
||||||
|
public class Block implements BlockData {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
18
src/data/block/BlockData.java
Normal file
18
src/data/block/BlockData.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package data.block;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public interface BlockData {
|
||||||
|
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();
|
||||||
|
}
|
@ -11,6 +11,8 @@ import static java.util.stream.Collectors.toMap;
|
|||||||
public abstract class Transaction {
|
public abstract class Transaction {
|
||||||
|
|
||||||
// Transaction types
|
// Transaction types
|
||||||
|
// TODO Transaction types are semantic and should go into the business logic layer.
|
||||||
|
// No need to know the meaning of the integer value in data layer
|
||||||
public enum TransactionType {
|
public enum TransactionType {
|
||||||
GENESIS(1), PAYMENT(2), REGISTER_NAME(3), UPDATE_NAME(4), SELL_NAME(5), CANCEL_SELL_NAME(6), BUY_NAME(7), CREATE_POLL(8), VOTE_ON_POLL(9), ARBITRARY(
|
GENESIS(1), PAYMENT(2), REGISTER_NAME(3), UPDATE_NAME(4), SELL_NAME(5), CANCEL_SELL_NAME(6), BUY_NAME(7), CREATE_POLL(8), VOTE_ON_POLL(9), ARBITRARY(
|
||||||
10), ISSUE_ASSET(11), TRANSFER_ASSET(12), CREATE_ASSET_ORDER(13), CANCEL_ASSET_ORDER(14), MULTIPAYMENT(15), DEPLOY_AT(16), MESSAGE(17);
|
10), ISSUE_ASSET(11), TRANSFER_ASSET(12), CREATE_ASSET_ORDER(13), CANCEL_ASSET_ORDER(14), MULTIPAYMENT(15), DEPLOY_AT(16), MESSAGE(17);
|
||||||
@ -30,6 +32,7 @@ public abstract class Transaction {
|
|||||||
|
|
||||||
// Properties shared with all transaction types
|
// Properties shared with all transaction types
|
||||||
protected TransactionType type;
|
protected TransactionType type;
|
||||||
|
// TODO PublicKeyAccount is a separate data entity, so here should only be a key to reference it
|
||||||
protected PublicKeyAccount creator;
|
protected PublicKeyAccount creator;
|
||||||
protected long timestamp;
|
protected long timestamp;
|
||||||
protected byte[] reference;
|
protected byte[] reference;
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
package qora.block;
|
package qora.block;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import data.block.BlockData;
|
||||||
import database.DB;
|
import database.DB;
|
||||||
import database.NoDataFoundException;
|
import database.NoDataFoundException;
|
||||||
|
import qora.account.PublicKeyAccount;
|
||||||
|
import qora.transaction.Transaction;
|
||||||
|
import qora.transaction.TransactionFactory;
|
||||||
|
import repository.BlockRepository;
|
||||||
|
import repository.hsqldb.HSQLDBBlockRepository;
|
||||||
|
|
||||||
public class BlockFactory {
|
public class BlockFactory {
|
||||||
|
|
||||||
|
// XXX repository should be pushed here from the root entry, no need to know the repository type
|
||||||
|
private static BlockRepository repository = new HSQLDBBlockRepository();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load Block from DB using block signature.
|
* Load Block from DB using block signature.
|
||||||
*
|
*
|
||||||
@ -35,16 +47,23 @@ public class BlockFactory {
|
|||||||
* @return ? extends Block, or null if not found
|
* @return ? extends Block, or null if not found
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public static Block fromHeight(int height) throws SQLException {
|
public static Block fromHeight(int height) {
|
||||||
if (height == 1)
|
if (height == 1)
|
||||||
return GenesisBlock.getInstance();
|
return GenesisBlock.getInstance();
|
||||||
|
|
||||||
PreparedStatement preparedStatement = DB.getConnection().prepareStatement("SELECT signature FROM Blocks WHERE height = ?");
|
|
||||||
preparedStatement.setInt(1, height);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new Block(DB.checkedExecute(preparedStatement));
|
BlockData data = repository.fromHeight(height);
|
||||||
} catch (NoDataFoundException e) {
|
|
||||||
|
// TODO fill this list from TransactionFactory
|
||||||
|
List<Transaction> transactions = new ArrayList<Transaction>();
|
||||||
|
|
||||||
|
// 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;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
src/repository/BlockRepository.java
Normal file
8
src/repository/BlockRepository.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package repository;
|
||||||
|
|
||||||
|
import data.block.BlockData;
|
||||||
|
|
||||||
|
public interface BlockRepository {
|
||||||
|
BlockData fromSignature(byte[] signature) throws DataException;
|
||||||
|
BlockData fromHeight(int height) throws DataException;
|
||||||
|
}
|
22
src/repository/DataException.java
Normal file
22
src/repository/DataException.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package repository;
|
||||||
|
|
||||||
|
public class DataException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3963965667288257605L;
|
||||||
|
|
||||||
|
public DataException() {}
|
||||||
|
|
||||||
|
public DataException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,9 +3,13 @@ package repository;
|
|||||||
public abstract class Repository {
|
public abstract class Repository {
|
||||||
|
|
||||||
protected TransactionRepository transactionRepository;
|
protected TransactionRepository transactionRepository;
|
||||||
|
protected BlockRepository blockRepository;
|
||||||
|
|
||||||
public TransactionRepository getTransactionRepository() {
|
public TransactionRepository getTransactionRepository() {
|
||||||
return this.transactionRepository;
|
return this.transactionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockRepository getBlockRepository() {
|
||||||
|
return this.blockRepository;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,8 @@ public abstract class RepositoryManager {
|
|||||||
return repository.transactionRepository;
|
return repository.transactionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BlockRepository getBlockRepository() {
|
||||||
|
return repository.blockRepository;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
64
src/repository/hsqldb/HSQLDBBlockRepository.java
Normal file
64
src/repository/hsqldb/HSQLDBBlockRepository.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package repository.hsqldb;
|
||||||
|
|
||||||
|
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.BlockData;
|
||||||
|
import database.DB;
|
||||||
|
import qora.account.PublicKeyAccount;
|
||||||
|
import repository.BlockRepository;
|
||||||
|
import repository.DataException;
|
||||||
|
|
||||||
|
public class HSQLDBBlockRepository implements BlockRepository
|
||||||
|
{
|
||||||
|
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 BlockData fromSignature(byte[] signature) throws DataException
|
||||||
|
{
|
||||||
|
ResultSet rs;
|
||||||
|
try {
|
||||||
|
rs = DB.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ?", signature);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Error loading data from DB", e);
|
||||||
|
}
|
||||||
|
return getBlockFromResultSet(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockData fromHeight(int height) throws DataException
|
||||||
|
{
|
||||||
|
ResultSet rs;
|
||||||
|
try {
|
||||||
|
rs = DB.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE height = ?", height);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Error loading data from DB", e);
|
||||||
|
}
|
||||||
|
return getBlockFromResultSet(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockData getBlockFromResultSet(ResultSet rs) throws DataException {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ import data.transaction.GenesisTransaction;
|
|||||||
import data.transaction.Transaction;
|
import data.transaction.Transaction;
|
||||||
import database.DB;
|
import database.DB;
|
||||||
|
|
||||||
public class HSQLDBGenesisTransaction extends HSQLDBTransaction {
|
public class HSQLDBGenesisTransactionRepository extends HSQLDBTransactionRepository {
|
||||||
|
|
||||||
Transaction fromBase(byte[] signature, byte[] reference, PublicKeyAccount creator, long timestamp, BigDecimal fee) {
|
Transaction fromBase(byte[] signature, byte[] reference, PublicKeyAccount creator, long timestamp, BigDecimal fee) {
|
||||||
try {
|
try {
|
@ -5,7 +5,7 @@ import repository.Repository;
|
|||||||
public class HSQLDBRepository extends Repository {
|
public class HSQLDBRepository extends Repository {
|
||||||
|
|
||||||
public HSQLDBRepository() {
|
public HSQLDBRepository() {
|
||||||
this.transactionRepository = new HSQLDBTransaction();
|
this.transactionRepository = new HSQLDBTransactionRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ import database.DB;
|
|||||||
import qora.block.Block;
|
import qora.block.Block;
|
||||||
import repository.TransactionRepository;
|
import repository.TransactionRepository;
|
||||||
|
|
||||||
public class HSQLDBTransaction implements TransactionRepository {
|
public class HSQLDBTransactionRepository implements TransactionRepository {
|
||||||
|
|
||||||
private HSQLDBGenesisTransaction genesisTransactionRepository;
|
private HSQLDBGenesisTransactionRepository genesisTransactionRepository;
|
||||||
|
|
||||||
public HSQLDBTransaction() {
|
public HSQLDBTransactionRepository() {
|
||||||
genesisTransactionRepository = new HSQLDBGenesisTransaction();
|
genesisTransactionRepository = new HSQLDBGenesisTransactionRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transaction fromSignature(byte[] signature) {
|
public Transaction fromSignature(byte[] signature) {
|
Loading…
x
Reference in New Issue
Block a user