More repository work

Moved more repository-like methods from qora.* classes to repository.

Removed qora.block.BlockTransaction as it's pretty much internal to the HSQLDB repository.

Fixing qora.account.*

Fixing genesis-related classes: block, account, transaction...
This commit is contained in:
catbref 2018-06-12 14:54:06 +01:00
parent 37d9bcbb53
commit 698c4b6cc9
15 changed files with 169 additions and 173 deletions

View File

@ -14,7 +14,8 @@ public class GenesisTransactionData extends TransactionData {
// Constructors // Constructors
public GenesisTransactionData(String recipient, BigDecimal amount, long timestamp, byte[] signature) { public GenesisTransactionData(String recipient, BigDecimal amount, long timestamp, byte[] signature) {
super(TransactionType.GENESIS, BigDecimal.ZERO, new GenesisAccount().getPublicKey(), timestamp, signature); // Zero fee
super(TransactionType.GENESIS, BigDecimal.ZERO, GenesisAccount.PUBLIC_KEY, timestamp, signature);
this.recipient = recipient; this.recipient = recipient;
this.amount = amount; this.amount = amount;

View File

@ -19,9 +19,7 @@ public class Account {
public Account(Repository repository, String address) throws DataException { public Account(Repository repository, String address) throws DataException {
this.repository = repository; this.repository = repository;
this.accountData = this.repository.getAccountRepository().getAccount(address); this.accountData = new AccountData(address);
if (this.accountData == null)
this.accountData = new AccountData(address);
} }
public String getAddress() { public String getAddress() {

View File

@ -1,9 +1,14 @@
package qora.account; package qora.account;
import repository.DataException;
import repository.Repository;
public final class GenesisAccount extends PublicKeyAccount { public final class GenesisAccount extends PublicKeyAccount {
public GenesisAccount() { public static final byte[] PUBLIC_KEY = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 };
super(new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 });
public GenesisAccount(Repository repository) throws DataException {
super(repository, PUBLIC_KEY);
} }
} }

View File

@ -1,7 +1,9 @@
package qora.account; package qora.account;
import data.account.AccountData;
import qora.crypto.Crypto; import qora.crypto.Crypto;
import qora.crypto.Ed25519; import qora.crypto.Ed25519;
import repository.Repository;
import utils.Pair; import utils.Pair;
public class PrivateKeyAccount extends PublicKeyAccount { public class PrivateKeyAccount extends PublicKeyAccount {
@ -15,11 +17,12 @@ public class PrivateKeyAccount extends PublicKeyAccount {
* @param seed * @param seed
* byte[32] used to create private/public key pair * byte[32] used to create private/public key pair
*/ */
public PrivateKeyAccount(byte[] seed) { public PrivateKeyAccount(Repository repository, byte[] seed) {
this.repository = repository;
this.seed = seed; this.seed = seed;
this.keyPair = Ed25519.createKeyPair(seed); this.keyPair = Ed25519.createKeyPair(seed);
this.publicKey = keyPair.getB(); this.publicKey = keyPair.getB();
this.address = Crypto.toAddress(this.publicKey); this.accountData = new AccountData(Crypto.toAddress(this.publicKey));
} }
public byte[] getSeed() { public byte[] getSeed() {

View File

@ -2,13 +2,15 @@ package qora.account;
import qora.crypto.Crypto; import qora.crypto.Crypto;
import qora.crypto.Ed25519; import qora.crypto.Ed25519;
import repository.DataException;
import repository.Repository;
public class PublicKeyAccount extends Account { public class PublicKeyAccount extends Account {
protected byte[] publicKey; protected byte[] publicKey;
public PublicKeyAccount(byte[] publicKey) { public PublicKeyAccount(Repository repository, byte[] publicKey) throws DataException {
super(Crypto.toAddress(publicKey)); super(repository, Crypto.toAddress(publicKey));
this.publicKey = publicKey; this.publicKey = publicKey;
} }
@ -28,4 +30,8 @@ public class PublicKeyAccount extends Account {
} }
} }
public static String getAddress(byte[] publicKey) {
return Crypto.toAddress(publicKey);
}
} }

View File

@ -49,9 +49,9 @@ import utils.NTP;
public class Block { public class Block {
// Properties // Properties
private Repository repository; protected Repository repository;
private BlockData blockData; protected BlockData blockData;
private PublicKeyAccount generator; protected PublicKeyAccount generator;
// Other properties // Other properties
protected List<Transaction> transactions; protected List<Transaction> transactions;
@ -76,10 +76,10 @@ public class Block {
// Constructors // Constructors
public Block(Repository repository, BlockData blockData) { public Block(Repository repository, BlockData blockData) throws DataException {
this.repository = repository; this.repository = repository;
this.blockData = blockData; this.blockData = blockData;
this.generator = new PublicKeyAccount(blockData.getGeneratorPublicKey()); this.generator = new PublicKeyAccount(repository, blockData.getGeneratorPublicKey());
} }
// Getters/setters // Getters/setters
@ -88,6 +88,10 @@ public class Block {
return this.blockData; return this.blockData;
} }
public PublicKeyAccount getGenerator() {
return this.generator;
}
// More information // More information
/** /**
@ -294,7 +298,6 @@ public class Block {
} }
} }
public boolean isSignatureValid() { public boolean isSignatureValid() {
try { try {
// Check generator's signature first // Check generator's signature first
@ -410,7 +413,7 @@ public class Block {
return true; return true;
} }
public void process() throws DataException, SQLException { public void process() throws DataException {
// Process transactions (we'll link them to this block after saving the block itself) // Process transactions (we'll link them to this block after saving the block itself)
List<Transaction> transactions = this.getTransactions(); List<Transaction> transactions = this.getTransactions();
for (Transaction transaction : transactions) for (Transaction transaction : transactions)
@ -422,7 +425,7 @@ public class Block {
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(blockFee)); this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(blockFee));
// Link block into blockchain by fetching signature of highest block and setting that as our reference // Link block into blockchain by fetching signature of highest block and setting that as our reference
int blockchainHeight = BlockChain.getHeight(); int blockchainHeight = this.repository.getBlockRepository().getBlockchainHeight();
BlockData latestBlockData = this.repository.getBlockRepository().fromHeight(blockchainHeight); BlockData latestBlockData = this.repository.getBlockRepository().fromHeight(blockchainHeight);
if (latestBlockData != null) if (latestBlockData != null)
this.blockData.setReference(latestBlockData.getSignature()); this.blockData.setReference(latestBlockData.getSignature());
@ -435,7 +438,8 @@ public class Block {
Transaction transaction = transactions.get(sequence); Transaction transaction = transactions.get(sequence);
// Link transaction to this block // Link transaction to this block
BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence, transaction.getTransactionData().getSignature()); BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence,
transaction.getTransactionData().getSignature());
this.repository.getBlockRepository().save(blockTransactionData); this.repository.getBlockRepository().save(blockTransactionData);
} }
} }

View File

@ -1,11 +1,14 @@
package qora.block; package qora.block;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import database.DB; import data.block.BlockData;
import qora.assets.Asset; import qora.assets.Asset;
import repository.BlockRepository;
import repository.DataException;
import repository.Repository;
import repository.RepositoryManager;
/** /**
* Class representing the blockchain as a whole. * Class representing the blockchain as a whole.
@ -35,69 +38,43 @@ public class BlockChain {
* *
* @throws SQLException * @throws SQLException
*/ */
public static void validate() throws SQLException { public static void validate() throws DataException {
// Check first block is Genesis Block // Check first block is Genesis Block
if (!isGenesisBlockValid()) if (!isGenesisBlockValid())
rebuildBlockchain(); rebuildBlockchain();
} }
private static boolean isGenesisBlockValid() throws SQLException { private static boolean isGenesisBlockValid() throws DataException {
int blockchainHeight = getHeight(); BlockRepository blockRepository = RepositoryManager.getRepository().getBlockRepository();
int blockchainHeight = blockRepository.getBlockchainHeight();
if (blockchainHeight < 1) if (blockchainHeight < 1)
return false; return false;
Block block = Block.fromHeight(1); BlockData blockData = blockRepository.fromHeight(1);
if (block == null) if (blockData == null)
return false; return false;
return GenesisBlock.isGenesisBlock(block); return GenesisBlock.isGenesisBlock(blockData);
} }
private static void rebuildBlockchain() throws SQLException { private static void rebuildBlockchain() throws DataException {
// (Re)build database // (Re)build repository
DB.rebuild(); Repository repository = RepositoryManager.getRepository();
repository.rebuild();
// Add Genesis Block // Add Genesis Block
GenesisBlock genesisBlock = GenesisBlock.getInstance(); GenesisBlock genesisBlock = new GenesisBlock(repository);
genesisBlock.process(); genesisBlock.process();
// Add QORA asset. // Add QORA asset.
// NOTE: Asset's transaction reference is Genesis Block's generator signature which doesn't exist as a transaction! // NOTE: Asset's transaction reference is Genesis Block's generator signature which doesn't exist as a transaction!
// TODO construct Asset(repository, AssetData) then .save()?
Asset qoraAsset = new Asset(Asset.QORA, genesisBlock.getGenerator().getAddress(), "Qora", "This is the simulated Qora asset.", 10_000_000_000L, true, Asset qoraAsset = new Asset(Asset.QORA, genesisBlock.getGenerator().getAddress(), "Qora", "This is the simulated Qora asset.", 10_000_000_000L, true,
genesisBlock.getGeneratorSignature()); genesisBlock.getBlockData().getGeneratorSignature());
qoraAsset.save(); qoraAsset.save();
}
/** repository.saveChanges();
* Return block height from DB using signature.
*
* @param signature
* @return height, or 0 if block not found.
* @throws SQLException
*/
public static int getBlockHeightFromSignature(byte[] signature) throws SQLException {
ResultSet rs = DB.checkedExecute("SELECT height FROM Blocks WHERE signature = ?", signature);
if (rs == null)
return 0;
return rs.getInt(1);
}
/**
* Return highest block height from DB.
*
* @return height, or 0 if there are no blocks in DB (not very likely).
*/
public static int getHeight() {
try {
ResultSet rs = DB.checkedExecute("SELECT MAX(height) FROM Blocks");
if (rs == null)
return 0;
return rs.getInt(1);
} catch (SQLException e) {
return 0;
}
} }
/** /**

View File

@ -1,5 +0,0 @@
package qora.block;
public class BlockTransaction {
}

View File

@ -3,37 +3,34 @@ package qora.block;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import data.block.BlockData;
import data.transaction.GenesisTransactionData;
import data.transaction.TransactionData;
import qora.account.GenesisAccount; import qora.account.GenesisAccount;
import qora.crypto.Crypto; import qora.crypto.Crypto;
import qora.transaction.GenesisTransaction; import qora.transaction.Transaction;
import qora.transaction.TransactionHandler; import repository.DataException;
import repository.Repository;
public class GenesisBlock extends Block { public class GenesisBlock extends Block {
private static GenesisBlock instance;
private static final int GENESIS_BLOCK_VERSION = 1; private static final int GENESIS_BLOCK_VERSION = 1;
private static final byte[] GENESIS_REFERENCE = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }; // NOTE: Neither 64 nor 128 bytes! private static final byte[] GENESIS_REFERENCE = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }; // NOTE: Neither 64 nor 128 bytes!
private static final BigDecimal GENESIS_GENERATING_BALANCE = BigDecimal.valueOf(10_000_000L).setScale(8); private static final BigDecimal GENESIS_GENERATING_BALANCE = BigDecimal.valueOf(10_000_000L).setScale(8);
private static final GenesisAccount GENESIS_GENERATOR = new GenesisAccount(); private static final byte[] GENESIS_GENERATOR_PUBLIC_KEY = GenesisAccount.PUBLIC_KEY; // NOTE: 8 bytes not 32 bytes!
private static final long GENESIS_TIMESTAMP = 1400247274336L; // QORA RELEASE: Fri May 16 13:34:34.336 2014 UTC private static final long GENESIS_TIMESTAMP = 1400247274336L; // QORA RELEASE: Fri May 16 13:34:34.336 2014 UTC
private static final byte[] GENESIS_GENERATOR_SIGNATURE = calcSignature(); private static final byte[] GENESIS_GENERATOR_SIGNATURE = calcSignature();
private static final byte[] GENESIS_TRANSACTIONS_SIGNATURE = calcSignature(); private static final byte[] GENESIS_TRANSACTIONS_SIGNATURE = calcSignature();
// Constructors // Constructors
protected GenesisBlock() { public GenesisBlock(Repository repository) throws DataException {
super(GENESIS_BLOCK_VERSION, GENESIS_REFERENCE, GENESIS_TIMESTAMP, GENESIS_GENERATING_BALANCE, GENESIS_GENERATOR, GENESIS_GENERATOR_SIGNATURE, super(repository, new BlockData(GENESIS_BLOCK_VERSION, GENESIS_REFERENCE, 0, BigDecimal.ZERO.setScale(8), GENESIS_TRANSACTIONS_SIGNATURE, 1,
GENESIS_TRANSACTIONS_SIGNATURE, null, null, new ArrayList<TransactionHandler>()); GENESIS_TIMESTAMP, GENESIS_GENERATING_BALANCE, GENESIS_GENERATOR_PUBLIC_KEY, GENESIS_GENERATOR_SIGNATURE, null, null));
this.height = 1;
// Genesis transactions // Genesis transactions
addGenesisTransaction("QUD9y7NZqTtNwvSAUfewd7zKUGoVivVnTW", "7032468.191"); addGenesisTransaction("QUD9y7NZqTtNwvSAUfewd7zKUGoVivVnTW", "7032468.191");
@ -172,74 +169,35 @@ public class GenesisBlock extends Block {
addGenesisTransaction("QT79PhvBwE6vFzfZ4oh5wdKVsEazZuVJFy", "6360421.343"); addGenesisTransaction("QT79PhvBwE6vFzfZ4oh5wdKVsEazZuVJFy", "6360421.343");
} }
/**
* Return cached GenesisBlock to save constructing one from scratch.
*
* @return GenesisBlock
*/
public static GenesisBlock getInstance() {
if (instance == null)
instance = new GenesisBlock();
return instance;
}
// Getters/setters
// More information // More information
public static boolean isGenesisBlock(Block block) { public static boolean isGenesisBlock(BlockData blockData) {
if (block.height != 1) if (blockData.getHeight() != 1)
return false; return false;
// Validate block signature // Validate block signature
if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, block.generatorSignature)) if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, blockData.getGeneratorSignature()))
return false; return false;
// Validate transactions signature // Validate transactions signature
if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, block.transactionsSignature)) if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, blockData.getTransactionsSignature()))
return false; return false;
return true; return true;
} }
// Load/Save
protected GenesisBlock(byte[] signature) throws SQLException {
super(signature);
}
protected GenesisBlock(ResultSet rs) throws SQLException {
super(rs);
}
// Navigation
/**
* Refuse to load parent of GenesisBlock from DB!
* <p>
* As the genesis block is the first block, this always returns null.
*
* @return null
* @throws SQLException
*/
@Override
public Block getParent() throws SQLException {
return null;
}
// Converters
// Processing // Processing
@Override @Override
public boolean addTransaction(TransactionHandler transaction) { public boolean addTransaction(TransactionData transactionData) {
// The genesis block has a fixed set of transactions so always refuse. // The genesis block has a fixed set of transactions so always refuse.
return false; return false;
} }
private void addGenesisTransaction(String recipient, String amount) { private void addGenesisTransaction(String recipient, String amount) {
this.transactions.add(new GenesisTransaction(recipient, new BigDecimal(amount).setScale(8), this.timestamp)); this.transactions
.add(Transaction.fromData(new GenesisTransactionData(recipient, new BigDecimal(amount).setScale(8), this.getBlockData().getTimestamp())));
this.blockData.setTransactionCount(this.blockData.getTransactionCount() + 1);
} }
/** /**
@ -288,7 +246,7 @@ public class GenesisBlock extends Block {
try { try {
// Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32. // Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32.
// See below for explanation of some of the values used to calculated expected size. // See below for explanation of some of the values used to calculated expected size.
ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 64 + GENERATING_BALANCE_LENGTH + GENERATOR_LENGTH); ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 64 + 8 + 32);
/* /*
* NOTE: Historic code had genesis block using Longs.toByteArray() compared to standard block's Ints.toByteArray. The subsequent * NOTE: Historic code had genesis block using Longs.toByteArray() compared to standard block's Ints.toByteArray. The subsequent
@ -306,7 +264,7 @@ public class GenesisBlock extends Block {
bytes.write(Longs.toByteArray(GENESIS_GENERATING_BALANCE.longValue())); bytes.write(Longs.toByteArray(GENESIS_GENERATING_BALANCE.longValue()));
// NOTE: Genesis account's public key is only 8 bytes, not the usual 32, so we have to pad. // NOTE: Genesis account's public key is only 8 bytes, not the usual 32, so we have to pad.
bytes.write(Bytes.ensureCapacity(GENESIS_GENERATOR.getPublicKey(), 32, 0)); bytes.write(Bytes.ensureCapacity(GENESIS_GENERATOR_PUBLIC_KEY, 32, 0));
return bytes.toByteArray(); return bytes.toByteArray();
} catch (IOException e) { } catch (IOException e) {
@ -317,25 +275,25 @@ public class GenesisBlock extends Block {
@Override @Override
public boolean isSignatureValid() { public boolean isSignatureValid() {
// Validate block signature // Validate block signature
if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, this.generatorSignature)) if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, this.getBlockData().getGeneratorSignature()))
return false; return false;
// Validate transactions signature // Validate transactions signature
if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, this.transactionsSignature)) if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, this.getBlockData().getTransactionsSignature()))
return false; return false;
return true; return true;
} }
@Override @Override
public boolean isValid() throws SQLException { public boolean isValid() throws DataException {
// Check there is no other block in DB // Check there is no other block in DB
if (BlockChain.getHeight() != 0) if (this.repository.getBlockRepository().getBlockchainHeight() != 0)
return false; return false;
// Validate transactions // Validate transactions
for (TransactionHandler transaction : this.getTransactions()) for (Transaction transaction : this.getTransactions())
if (transaction.isValid() != TransactionHandler.ValidationResult.OK) if (transaction.isValid() != Transaction.ValidationResult.OK)
return false; return false;
return true; return true;

View File

@ -12,6 +12,7 @@ import data.transaction.TransactionData;
import qora.account.PrivateKeyAccount; import qora.account.PrivateKeyAccount;
import qora.block.Block; import qora.block.Block;
import qora.block.BlockChain; import qora.block.BlockChain;
import repository.Repository;
import repository.RepositoryManager; import repository.RepositoryManager;
import settings.Settings; import settings.Settings;
import transform.TransformationException; import transform.TransformationException;
@ -63,6 +64,7 @@ public abstract class Transaction {
protected static final BigDecimal maxBytePerFee = BigDecimal.valueOf(Settings.getInstance().getMaxBytePerFee()); protected static final BigDecimal maxBytePerFee = BigDecimal.valueOf(Settings.getInstance().getMaxBytePerFee());
protected static final BigDecimal minFeePerByte = BigDecimal.ONE.divide(maxBytePerFee, MathContext.DECIMAL32); protected static final BigDecimal minFeePerByte = BigDecimal.ONE.divide(maxBytePerFee, MathContext.DECIMAL32);
// Properties
protected TransactionData transactionData; protected TransactionData transactionData;
// Constructors // Constructors
@ -108,7 +110,8 @@ public abstract class Transaction {
public BigDecimal calcRecommendedFee() { public BigDecimal calcRecommendedFee() {
try { try {
BigDecimal recommendedFee = BigDecimal.valueOf(TransactionTransformer.getDataLength(this.transactionData)).divide(maxBytePerFee, MathContext.DECIMAL32).setScale(8); BigDecimal recommendedFee = BigDecimal.valueOf(TransactionTransformer.getDataLength(this.transactionData))
.divide(maxBytePerFee, MathContext.DECIMAL32).setScale(8);
// security margin // security margin
recommendedFee = recommendedFee.add(new BigDecimal("0.0000001")); recommendedFee = recommendedFee.add(new BigDecimal("0.0000001"));
@ -139,7 +142,7 @@ public abstract class Transaction {
* @return height, or 0 if not in blockchain (i.e. unconfirmed) * @return height, or 0 if not in blockchain (i.e. unconfirmed)
*/ */
public int getHeight() { public int getHeight() {
return RepositoryManager.getTransactionRepository().getHeight(this.transactionData); return RepositoryManager.getRepository().getTransactionRepository().getHeight(this.transactionData);
} }
/** /**
@ -148,7 +151,7 @@ public abstract class Transaction {
* @return confirmation count, or 0 if not in blockchain (i.e. unconfirmed) * @return confirmation count, or 0 if not in blockchain (i.e. unconfirmed)
*/ */
public int getConfirmations() { public int getConfirmations() {
int ourHeight = this.getHeight(); int ourHeight = getHeight();
if (ourHeight == 0) if (ourHeight == 0)
return 0; return 0;

View File

@ -14,6 +14,22 @@ public interface BlockRepository {
public BlockData fromHeight(int height) throws DataException; public BlockData fromHeight(int height) throws DataException;
/**
* Return height of block in blockchain using block's signature.
*
* @param signature
* @return height, or 0 if not found in blockchain.
* @throws DataException
*/
public int getHeightFromSignature(byte[] signature) throws DataException;
/**
* Return highest block height from DB.
*
* @return height, or 0 if there are no blocks in DB (not very likely).
*/
public int getBlockchainHeight() throws DataException;
public List<TransactionData> getTransactionsFromSignature(byte[] signature) throws DataException; public List<TransactionData> getTransactionsFromSignature(byte[] signature) throws DataException;
public void save(BlockData blockData) throws DataException; public void save(BlockData blockData) throws DataException;

View File

@ -14,4 +14,6 @@ public interface Repository {
public void close() throws DataException; public void close() throws DataException;
public void rebuild() throws DataException;
} }

View File

@ -25,6 +25,31 @@ public class HSQLDBBlockRepository implements BlockRepository {
this.repository = repository; this.repository = repository;
} }
private BlockData getBlockFromResultSet(ResultSet rs) throws DataException {
if (rs == null)
return null;
try {
int version = rs.getInt(1);
byte[] reference = this.repository.getResultSetBytes(rs.getBinaryStream(2));
int transactionCount = rs.getInt(3);
BigDecimal totalFees = rs.getBigDecimal(4);
byte[] transactionsSignature = this.repository.getResultSetBytes(rs.getBinaryStream(5));
int height = rs.getInt(6);
long timestamp = rs.getTimestamp(7).getTime();
BigDecimal generatingBalance = rs.getBigDecimal(8);
byte[] generatorPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(9));
byte[] generatorSignature = this.repository.getResultSetBytes(rs.getBinaryStream(10));
byte[] atBytes = this.repository.getResultSetBytes(rs.getBinaryStream(11));
BigDecimal atFees = rs.getBigDecimal(12);
return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance,
generatorPublicKey, generatorSignature, atBytes, atFees);
} catch (SQLException e) {
throw new DataException("Error extracting data from result set", e);
}
}
public BlockData fromSignature(byte[] signature) throws DataException { public BlockData fromSignature(byte[] signature) throws DataException {
try { try {
ResultSet rs = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ?", signature); ResultSet rs = this.repository.checkedExecute("SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks WHERE signature = ?", signature);
@ -52,28 +77,27 @@ public class HSQLDBBlockRepository implements BlockRepository {
} }
} }
private BlockData getBlockFromResultSet(ResultSet rs) throws DataException { public int getHeightFromSignature(byte[] signature) throws DataException {
if (rs == null)
return null;
try { try {
int version = rs.getInt(1); ResultSet rs = this.repository.checkedExecute("SELECT height FROM Blocks WHERE signature = ?", signature);
byte[] reference = this.repository.getResultSetBytes(rs.getBinaryStream(2)); if (rs == null)
int transactionCount = rs.getInt(3); return 0;
BigDecimal totalFees = rs.getBigDecimal(4);
byte[] transactionsSignature = this.repository.getResultSetBytes(rs.getBinaryStream(5));
int height = rs.getInt(6);
long timestamp = rs.getTimestamp(7).getTime();
BigDecimal generatingBalance = rs.getBigDecimal(8);
byte[] generatorPublicKey = this.repository.getResultSetBytes(rs.getBinaryStream(9));
byte[] generatorSignature = this.repository.getResultSetBytes(rs.getBinaryStream(10));
byte[] atBytes = this.repository.getResultSetBytes(rs.getBinaryStream(11));
BigDecimal atFees = rs.getBigDecimal(12);
return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, return rs.getInt(1);
generatorPublicKey, generatorSignature, atBytes, atFees);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Error extracting data from result set", e); throw new DataException("Error obtaining block height from repository", e);
}
}
public int getBlockchainHeight() throws DataException {
try {
ResultSet rs = this.repository.checkedExecute("SELECT MAX(height) FROM Blocks");
if (rs == null)
return 0;
return rs.getInt(1);
} catch (SQLException e) {
throw new DataException("Error obtaining blockchain height from repository", e);
} }
} }

View File

@ -69,6 +69,10 @@ public class HSQLDBRepository implements Repository {
} }
} }
@Override
public void rebuild() throws DataException {
}
/** /**
* Convert InputStream, from ResultSet.getBinaryStream(), into byte[]. * Convert InputStream, from ResultSet.getBinaryStream(), into byte[].
* *

View File

@ -210,7 +210,7 @@ public class BlockTransformer extends Transformer {
json.put("version", blockData.getVersion()); json.put("version", blockData.getVersion());
json.put("timestamp", blockData.getTimestamp()); json.put("timestamp", blockData.getTimestamp());
json.put("generatingBalance", blockData.getGeneratingBalance()); json.put("generatingBalance", blockData.getGeneratingBalance());
json.put("generator", new PublicKeyAccount(blockData.getGeneratorPublicKey()).getAddress()); json.put("generator", PublicKeyAccount.getAddress(blockData.getGeneratorPublicKey()));
json.put("generatorPublicKey", Base58.encode(blockData.getGeneratorPublicKey())); json.put("generatorPublicKey", Base58.encode(blockData.getGeneratorPublicKey()));
json.put("fee", blockData.getTotalFees().toPlainString()); json.put("fee", blockData.getTotalFees().toPlainString());
json.put("transactionsSignature", Base58.encode(blockData.getTransactionsSignature())); json.put("transactionsSignature", Base58.encode(blockData.getTransactionsSignature()));