diff --git a/src/main/java/org/qora/account/Account.java b/src/main/java/org/qora/account/Account.java index ed60774c..f4775fd9 100644 --- a/src/main/java/org/qora/account/Account.java +++ b/src/main/java/org/qora/account/Account.java @@ -5,9 +5,7 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.qora.asset.Asset; import org.qora.block.Block; -import org.qora.block.BlockChain; import org.qora.data.account.AccountBalanceData; import org.qora.data.account.AccountData; import org.qora.data.block.BlockData; @@ -53,44 +51,6 @@ public class Account { return new AccountData(this.address); } - // More information - - /** - * Calculate current generating balance for this account. - *

- * This is the current confirmed balance minus amounts received in the last BlockChain.BLOCK_RETARGET_INTERVAL blocks. - * - * @throws DataException - */ - public BigDecimal getGeneratingBalance() throws DataException { - BigDecimal balance = this.getConfirmedBalance(Asset.QORA); - - BlockRepository blockRepository = this.repository.getBlockRepository(); - BlockData blockData = blockRepository.getLastBlock(); - - for (int i = 1; i < BlockChain.getInstance().getBlockDifficultyInterval() && blockData != null && blockData.getHeight() > 1; ++i) { - Block block = new Block(this.repository, blockData); - - // CIYAM AT transactions should be fetched from repository so no special handling needed here - for (Transaction transaction : block.getTransactions()) { - if (transaction.isInvolved(this)) { - final BigDecimal amount = transaction.getAmount(this); - - // Subtract positive amounts only - if (amount.compareTo(BigDecimal.ZERO) > 0) - balance = balance.subtract(amount); - } - } - - blockData = block.getParent(); - } - - // Do not go below 0 - balance = balance.max(BigDecimal.ZERO); - - return balance; - } - // Balance manipulations - assetId is 0 for QORA public BigDecimal getBalance(long assetId, int confirmations) throws DataException { diff --git a/src/main/java/org/qora/account/Forging.java b/src/main/java/org/qora/account/Forging.java index 51f06c5f..4c44bdc5 100644 --- a/src/main/java/org/qora/account/Forging.java +++ b/src/main/java/org/qora/account/Forging.java @@ -13,8 +13,8 @@ public class Forging { } public static boolean canForge(Account account) throws DataException { - Integer flags = account.getFlags(); - return flags != null && (flags & getForgingMask()) != 0; + Integer level = account.getLevel(); + return level != null && level > 0; } } diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java index 70111508..92eb4f0b 100644 --- a/src/main/java/org/qora/api/resource/AddressesResource.java +++ b/src/main/java/org/qora/api/resource/AddressesResource.java @@ -189,33 +189,6 @@ public class AddressesResource { } } - @GET - @Path("/generatingbalance/{address}") - @Operation( - summary = "Return the generating balance of the given address", - description = "Returns the effective balance of the given address, used in Proof-of-Stake calculationgs when generating a new block.", - responses = { - @ApiResponse( - description = "the generating balance", - content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number")) - ) - } - ) - @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) - public BigDecimal getGeneratingBalanceOfAddress(@PathParam("address") String address) { - if (!Crypto.isValidAddress(address)) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); - - try (final Repository repository = RepositoryManager.getRepository()) { - Account account = new Account(repository, address); - return account.getGeneratingBalance(); - } catch (ApiException e) { - throw e; - } catch (DataException e) { - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); - } - } - @GET @Path("/balance/{address}") @Operation( @@ -228,7 +201,7 @@ public class AddressesResource { } ) @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) - public BigDecimal getGeneratingBalance(@PathParam("address") String address) { + public BigDecimal getConfirmedBalance(@PathParam("address") String address) { if (!Crypto.isValidAddress(address)) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); @@ -253,7 +226,7 @@ public class AddressesResource { ) } ) - public String getGeneratingBalance(@PathParam("address") String address, @PathParam("confirmations") int confirmations) { + public String getConfirmedBalance(@PathParam("address") String address, @PathParam("confirmations") int confirmations) { throw new UnsupportedOperationException(); } diff --git a/src/main/java/org/qora/api/resource/BlocksResource.java b/src/main/java/org/qora/api/resource/BlocksResource.java index 1193ecae..32ffe2c0 100644 --- a/src/main/java/org/qora/api/resource/BlocksResource.java +++ b/src/main/java/org/qora/api/resource/BlocksResource.java @@ -9,7 +9,6 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -28,7 +27,6 @@ import org.qora.api.ApiErrors; import org.qora.api.ApiException; import org.qora.api.ApiExceptionFactory; import org.qora.api.model.BlockForgerSummary; -import org.qora.block.Block; import org.qora.crypto.Crypto; import org.qora.data.account.AccountData; import org.qora.data.block.BlockData; @@ -243,83 +241,6 @@ public class BlocksResource { } } - @GET - @Path("/generatingbalance") - @Operation( - summary = "Generating balance of next block", - description = "Calculates the generating balance of the block that will follow the last block", - responses = { - @ApiResponse( - description = "the generating balance", - content = @Content( - mediaType = MediaType.TEXT_PLAIN, - schema = @Schema( - implementation = BigDecimal.class - ) - ) - ) - } - ) - @ApiErrors({ - ApiError.REPOSITORY_ISSUE - }) - public BigDecimal getGeneratingBalance() { - try (final Repository repository = RepositoryManager.getRepository()) { - BlockData blockData = repository.getBlockRepository().getLastBlock(); - Block block = new Block(repository, blockData); - return block.calcNextBlockGeneratingBalance(); - } catch (ApiException e) { - throw e; - } catch (DataException e) { - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); - } - } - - @GET - @Path("/generatingbalance/{signature}") - @Operation( - summary = "Generating balance of block after specific block", - description = "Calculates the generating balance of the block that will follow the block that matches the signature", - responses = { - @ApiResponse( - description = "the block", - content = @Content( - mediaType = MediaType.TEXT_PLAIN, - schema = @Schema( - implementation = BigDecimal.class - ) - ) - ) - } - ) - @ApiErrors({ - ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE - }) - public BigDecimal getGeneratingBalance(@PathParam("signature") String signature58) { - // Decode signature - byte[] signature; - try { - signature = Base58.decode(signature58); - } catch (NumberFormatException e) { - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e); - } - - try (final Repository repository = RepositoryManager.getRepository()) { - BlockData blockData = repository.getBlockRepository().fromSignature(signature); - - // Check block exists - if (blockData == null) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS); - - Block block = new Block(repository, blockData); - return block.calcNextBlockGeneratingBalance(); - } catch (ApiException e) { - throw e; - } catch (DataException e) { - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); - } - } - @GET @Path("/height") @Operation( diff --git a/src/main/java/org/qora/block/Block.java b/src/main/java/org/qora/block/Block.java index bbe0d582..ffbc8d12 100644 --- a/src/main/java/org/qora/block/Block.java +++ b/src/main/java/org/qora/block/Block.java @@ -34,7 +34,6 @@ import org.qora.data.block.BlockTransactionData; import org.qora.data.network.OnlineAccountData; import org.qora.data.transaction.TransactionData; import org.qora.repository.ATRepository; -import org.qora.repository.BlockRepository; import org.qora.repository.DataException; import org.qora.repository.Repository; import org.qora.repository.TransactionRepository; @@ -55,28 +54,6 @@ import com.google.common.primitives.Longs; import io.druid.extendedset.intset.ConciseSet; -/* - * Typical use-case scenarios: - * - * 1. Loading a Block from the database using height, signature, reference, etc. - * 2. Generating a new block, adding unconfirmed transactions - * 3. Receiving a block from another node - * - * Transaction count, transactions signature and total fees need to be maintained by Block. - * In scenario (1) these can be found in database. - * In scenarios (2) and (3) Transactions are added to the Block via addTransaction() method. - * Also in scenarios (2) and (3), Block is responsible for saving Transactions to DB. - * - * When is height set? - * In scenario (1) this can be found in database. - * In scenarios (2) and (3) this will need to be set after successful processing, - * but before Block is saved into database. - * - * GeneratorSignature's data is: reference + generatingBalance + generator's public key - * TransactionSignature's data is: generatorSignature + transaction signatures - * Block signature is: generatorSignature + transactionsSignature - */ - public class Block { // Validation results @@ -93,7 +70,6 @@ public class Block { TIMESTAMP_INCORRECT(24), VERSION_INCORRECT(30), FEATURE_NOT_YET_RELEASED(31), - GENERATING_BALANCE_INCORRECT(40), GENERATOR_NOT_ACCEPTED(41), GENESIS_TRANSACTIONS_INVALID(50), TRANSACTION_TIMESTAMP_INVALID(51), @@ -144,8 +120,6 @@ public class Block { /** Locally-generated AT fees */ protected BigDecimal ourAtFees; // Generated locally - /** Cached copy of next block's generating balance */ - protected BigDecimal cachedNextGeneratingBalance; /** Minimum Qora balance for use in calculations. */ public static final BigDecimal MIN_BALANCE = BigDecimal.valueOf(1L).setScale(8); @@ -216,10 +190,7 @@ public class Block { * Note that CIYAM ATs will be executed and AT-Transactions prepended to this block, along with AT state data and fees. * * @param repository - * @param version - * @param reference - * @param timestamp - * @param generatingBalance + * @param parentBlockData * @param generator * @throws DataException */ @@ -231,7 +202,6 @@ public class Block { int version = parentBlock.getNextBlockVersion(); byte[] reference = parentBlockData.getSignature(); - BigDecimal generatingBalance = parentBlock.calcNextBlockGeneratingBalance(); // Fetch our list of online accounts List onlineAccounts = Controller.getInstance().getOnlineAccounts(); @@ -274,8 +244,7 @@ public class Block { byte[] generatorSignature; try { - generatorSignature = generator - .sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generatingBalance, generator, encodedOnlineAccounts)); + generatorSignature = generator.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generator, encodedOnlineAccounts)); } catch (TransformationException e) { throw new DataException("Unable to calculate next block generator signature", e); } @@ -293,7 +262,7 @@ public class Block { BigDecimal totalFees = atFees; // This instance used for AT processing - this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, + this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generator.getPublicKey(), generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); @@ -306,7 +275,7 @@ public class Block { totalFees = atFees; // Rebuild blockData using post-AT-execute data - this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, + this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generator.getPublicKey(), generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); } @@ -334,12 +303,10 @@ public class Block { // Calculate new block timestamp int version = this.blockData.getVersion(); byte[] reference = this.blockData.getReference(); - BigDecimal generatingBalance = this.blockData.getGeneratingBalance(); byte[] generatorSignature; try { - generatorSignature = generator - .sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generatingBalance, generator, this.blockData.getEncodedOnlineAccounts())); + generatorSignature = generator.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generator, this.blockData.getEncodedOnlineAccounts())); } catch (TransformationException e) { throw new DataException("Unable to calculate next block generator signature", e); } @@ -360,7 +327,7 @@ public class Block { Long onlineAccountsTimestamp = this.blockData.getOnlineAccountsTimestamp(); byte[] onlineAccountsSignatures = this.blockData.getOnlineAccountsSignatures(); - newBlock.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, + newBlock.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generator.getPublicKey(), generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); // Resign to update transactions signature @@ -412,80 +379,6 @@ public class Block { return 4; } - /** - * Return the next block's generating balance. - *

- * Every BLOCK_RETARGET_INTERVAL the generating balance is recalculated. - *

- * If this block starts a new interval then the new generating balance is calculated, cached and returned.
- * Within this interval, the generating balance stays the same so the current block's generating balance will be returned. - * - * @return next block's generating balance - * @throws DataException - */ - public BigDecimal calcNextBlockGeneratingBalance() throws DataException { - if (this.blockData.getHeight() == null) - throw new IllegalStateException("Can't calculate next block's generating balance as this block's height is unset"); - - final int blockDifficultyInterval = BlockChain.getInstance().getBlockDifficultyInterval(); - - // This block not at the start of an interval? - if (this.blockData.getHeight() % blockDifficultyInterval != 0) - return this.blockData.getGeneratingBalance(); - - // Return cached calculation if we have one - if (this.cachedNextGeneratingBalance != null) - return this.cachedNextGeneratingBalance; - - // Perform calculation - - // Navigate back to first block in previous interval: - // XXX: why can't we simply load using block height? - BlockRepository blockRepo = this.repository.getBlockRepository(); - BlockData firstBlock = this.blockData; - - try { - for (int i = 1; firstBlock != null && i < blockDifficultyInterval; ++i) - firstBlock = blockRepo.fromSignature(firstBlock.getReference()); - } catch (DataException e) { - firstBlock = null; - } - - // Couldn't navigate back far enough? - if (firstBlock == null) - throw new IllegalStateException("Failed to calculate next block's generating balance due to lack of historic blocks"); - - // Calculate the actual time period (in ms) over previous interval's blocks. - long previousGeneratingTime = this.blockData.getTimestamp() - firstBlock.getTimestamp(); - - // Calculate expected forging time (in ms) for a whole interval based on this block's generating balance. - long expectedGeneratingTime = Block.calcForgingDelay(this.blockData.getGeneratingBalance(), this.blockData.getHeight()) * blockDifficultyInterval; - - // Finally, scale generating balance such that faster than expected previous intervals produce larger generating balances. - // NOTE: we have to use doubles and longs here to keep compatibility with Qora v1 results - double multiplier = (double) expectedGeneratingTime / (double) previousGeneratingTime; - long nextGeneratingBalance = (long) (this.blockData.getGeneratingBalance().doubleValue() * multiplier); - - this.cachedNextGeneratingBalance = Block.minMaxBalance(BigDecimal.valueOf(nextGeneratingBalance).setScale(8)); - - return this.cachedNextGeneratingBalance; - } - - /** - * Return expected forging delay, in seconds, since previous block based on passed generating balance. - */ - public static long calcForgingDelay(BigDecimal generatingBalance, int previousBlockHeight) { - generatingBalance = Block.minMaxBalance(generatingBalance); - - double percentageOfTotal = generatingBalance.divide(BlockChain.getInstance().getMaxBalance()).doubleValue(); - - BlockTimingByHeight blockTiming = BlockChain.getInstance().getBlockTimingByHeight(previousBlockHeight + 1); - - long actualBlockTime = (long) (blockTiming.target + (blockTiming.deviation * (1 - (2 * percentageOfTotal)))); - - return actualBlockTime; - } - /** * Return block's transactions. *

@@ -953,10 +846,6 @@ public class Block { if (this.blockData.getVersion() < 2 && this.blockData.getATCount() != 0) return ValidationResult.FEATURE_NOT_YET_RELEASED; - // Check generating balance - if (this.blockData.getGeneratingBalance().compareTo(parentBlock.calcNextBlockGeneratingBalance()) != 0) - return ValidationResult.GENERATING_BALANCE_INCORRECT; - // Check generator is allowed to forge this block if (!isGeneratorValidToForge(parentBlock)) return ValidationResult.GENERATOR_NOT_ACCEPTED; diff --git a/src/main/java/org/qora/block/BlockChain.java b/src/main/java/org/qora/block/BlockChain.java index 6a8b4d21..e010ee44 100644 --- a/src/main/java/org/qora/block/BlockChain.java +++ b/src/main/java/org/qora/block/BlockChain.java @@ -1,6 +1,7 @@ package org.qora.block; import java.io.File; +import java.io.FileNotFoundException; import java.io.InputStream; import java.math.BigDecimal; import java.math.MathContext; @@ -160,8 +161,9 @@ public class BlockChain { unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); } catch (JAXBException e) { - LOGGER.error("Unable to process blockchain config file", e); - throw new RuntimeException("Unable to process blockchain config file", e); + String message = "Failed to setup unmarshaller to process blockchain config file"; + LOGGER.error(message, e); + throw new RuntimeException(message, e); } BlockChain blockchain = null; @@ -173,8 +175,9 @@ public class BlockChain { File jsonFile = new File(path + filename); if (!jsonFile.exists()) { - LOGGER.error("Blockchain config file not found: " + path + filename); - throw new RuntimeException("Blockchain config file not found: " + path + filename); + String message = "Blockchain config file not found: " + path + filename; + LOGGER.error(message); + throw new RuntimeException(message, new FileNotFoundException(message)); } jsonSource = new StreamSource(jsonFile); @@ -194,14 +197,16 @@ public class BlockChain { if (linkedException instanceof XMLMarshalException) { String message = ((XMLMarshalException) linkedException).getInternalException().getLocalizedMessage(); LOGGER.error(message); - throw new RuntimeException(message); + throw new RuntimeException(message, e); } - LOGGER.error("Unable to process blockchain config file", e); - throw new RuntimeException("Unable to process blockchain config file", e); + String message = "Failed to parse blockchain config file"; + LOGGER.error(message, e); + throw new RuntimeException(message, e); } catch (JAXBException e) { - LOGGER.error("Unable to process blockchain config file", e); - throw new RuntimeException("Unable to process blockchain config file", e); + String message = "Unexpected JAXB issue while processing blockchain config file"; + LOGGER.error(message, e); + throw new RuntimeException(message, e); } // Validate config diff --git a/src/main/java/org/qora/block/GenesisBlock.java b/src/main/java/org/qora/block/GenesisBlock.java index c11e849c..7a9c723a 100644 --- a/src/main/java/org/qora/block/GenesisBlock.java +++ b/src/main/java/org/qora/block/GenesisBlock.java @@ -46,7 +46,6 @@ public class GenesisBlock extends Block { public static class GenesisInfo { public int version = 1; public long timestamp; - public BigDecimal generatingBalance; public TransactionData[] transactions; @@ -123,21 +122,18 @@ public class GenesisBlock extends Block { }).collect(Collectors.toList()); } - // Minor fix-up - info.generatingBalance.setScale(8); - byte[] reference = GENESIS_REFERENCE; int transactionCount = transactionsData.size(); BigDecimal totalFees = BigDecimal.ZERO.setScale(8); byte[] generatorPublicKey = GenesisAccount.PUBLIC_KEY; - byte[] bytesForSignature = getBytesForSignature(info.version, reference, info.generatingBalance, generatorPublicKey); + byte[] bytesForSignature = getBytesForSignature(info.version, reference, generatorPublicKey); byte[] generatorSignature = calcSignature(bytesForSignature); byte[] transactionsSignature = generatorSignature; int height = 1; int atCount = 0; BigDecimal atFees = BigDecimal.ZERO.setScale(8); - blockData = new BlockData(info.version, reference, transactionCount, totalFees, transactionsSignature, height, info.timestamp, info.generatingBalance, + blockData = new BlockData(info.version, reference, transactionCount, totalFees, transactionsSignature, height, info.timestamp, generatorPublicKey, generatorSignature, atCount, atFees); } @@ -214,7 +210,7 @@ public class GenesisBlock extends Block { return Bytes.concat(digest, digest); } - private static byte[] getBytesForSignature(int version, byte[] reference, BigDecimal generatingBalance, byte[] generatorPublicKey) { + private static byte[] getBytesForSignature(int version, byte[] reference, byte[] generatorPublicKey) { try { // 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. @@ -233,8 +229,6 @@ public class GenesisBlock extends Block { */ bytes.write(Bytes.ensureCapacity(reference, 64, 0)); - bytes.write(Longs.toByteArray(generatingBalance.longValue())); - // NOTE: Genesis account's public key is only 8 bytes, not the usual 32, so we have to pad. bytes.write(Bytes.ensureCapacity(generatorPublicKey, 32, 0)); @@ -246,8 +240,7 @@ public class GenesisBlock extends Block { /** Convenience method for calculating genesis block signatures from block data */ private static byte[] calcSignature(BlockData blockData) { - byte[] bytes = getBytesForSignature(blockData.getVersion(), blockData.getReference(), blockData.getGeneratingBalance(), - blockData.getGeneratorPublicKey()); + byte[] bytes = getBytesForSignature(blockData.getVersion(), blockData.getReference(), blockData.getGeneratorPublicKey()); return calcSignature(bytes); } diff --git a/src/main/java/org/qora/data/block/BlockData.java b/src/main/java/org/qora/data/block/BlockData.java index 455a0d32..9fd10429 100644 --- a/src/main/java/org/qora/data/block/BlockData.java +++ b/src/main/java/org/qora/data/block/BlockData.java @@ -27,7 +27,6 @@ public class BlockData implements Serializable { private byte[] transactionsSignature; private Integer height; private long timestamp; - private BigDecimal generatingBalance; private byte[] generatorPublicKey; private byte[] generatorSignature; private int atCount; @@ -44,7 +43,7 @@ public class BlockData implements Serializable { } public BlockData(int version, byte[] reference, int transactionCount, BigDecimal totalFees, byte[] transactionsSignature, Integer height, long timestamp, - BigDecimal generatingBalance, byte[] generatorPublicKey, byte[] generatorSignature, int atCount, BigDecimal atFees, + byte[] generatorPublicKey, byte[] generatorSignature, int atCount, BigDecimal atFees, byte[] encodedOnlineAccounts, int onlineAccountsCount, Long onlineAccountsTimestamp, byte[] onlineAccountsSignatures) { this.version = version; this.reference = reference; @@ -53,7 +52,6 @@ public class BlockData implements Serializable { this.transactionsSignature = transactionsSignature; this.height = height; this.timestamp = timestamp; - this.generatingBalance = generatingBalance; this.generatorPublicKey = generatorPublicKey; this.generatorSignature = generatorSignature; this.atCount = atCount; @@ -70,8 +68,8 @@ public class BlockData implements Serializable { } public BlockData(int version, byte[] reference, int transactionCount, BigDecimal totalFees, byte[] transactionsSignature, Integer height, long timestamp, - BigDecimal generatingBalance, byte[] generatorPublicKey, byte[] generatorSignature, int atCount, BigDecimal atFees) { - this(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, generatorPublicKey, generatorSignature, atCount, atFees, + byte[] generatorPublicKey, byte[] generatorSignature, int atCount, BigDecimal atFees) { + this(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatorPublicKey, generatorSignature, atCount, atFees, null, 0, null, null); } @@ -133,10 +131,6 @@ public class BlockData implements Serializable { return this.timestamp; } - public BigDecimal getGeneratingBalance() { - return this.generatingBalance; - } - public byte[] getGeneratorPublicKey() { return this.generatorPublicKey; } diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java index c8acd507..d2ed8563 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java @@ -22,7 +22,7 @@ import static org.qora.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli public class HSQLDBBlockRepository implements BlockRepository { private static final String BLOCK_DB_COLUMNS = "version, reference, transaction_count, total_fees, " - + "transactions_signature, height, generation, generating_balance, generator, generator_signature, " + + "transactions_signature, height, generation, generator, generator_signature, " + "AT_count, AT_fees, online_accounts, online_accounts_count, online_accounts_timestamp, online_accounts_signatures"; protected HSQLDBRepository repository; @@ -43,17 +43,16 @@ public class HSQLDBBlockRepository implements BlockRepository { byte[] transactionsSignature = resultSet.getBytes(5); int height = resultSet.getInt(6); long timestamp = getZonedTimestampMilli(resultSet, 7); - BigDecimal generatingBalance = resultSet.getBigDecimal(8); - byte[] generatorPublicKey = resultSet.getBytes(9); - byte[] generatorSignature = resultSet.getBytes(10); - int atCount = resultSet.getInt(11); - BigDecimal atFees = resultSet.getBigDecimal(12); - byte[] encodedOnlineAccounts = resultSet.getBytes(13); - int onlineAccountsCount = resultSet.getInt(14); - Long onlineAccountsTimestamp = getZonedTimestampMilli(resultSet, 15); - byte[] onlineAccountsSignatures = resultSet.getBytes(16); + byte[] generatorPublicKey = resultSet.getBytes(8); + byte[] generatorSignature = resultSet.getBytes(9); + int atCount = resultSet.getInt(10); + BigDecimal atFees = resultSet.getBigDecimal(11); + byte[] encodedOnlineAccounts = resultSet.getBytes(12); + int onlineAccountsCount = resultSet.getInt(13); + Long onlineAccountsTimestamp = getZonedTimestampMilli(resultSet, 14); + byte[] onlineAccountsSignatures = resultSet.getBytes(15); - return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, + return new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatorPublicKey, generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); } catch (SQLException e) { @@ -341,7 +340,7 @@ public class HSQLDBBlockRepository implements BlockRepository { saveHelper.bind("signature", blockData.getSignature()).bind("version", blockData.getVersion()).bind("reference", blockData.getReference()) .bind("transaction_count", blockData.getTransactionCount()).bind("total_fees", blockData.getTotalFees()) .bind("transactions_signature", blockData.getTransactionsSignature()).bind("height", blockData.getHeight()) - .bind("generation", toOffsetDateTime(blockData.getTimestamp())).bind("generating_balance", blockData.getGeneratingBalance()) + .bind("generation", toOffsetDateTime(blockData.getTimestamp())) .bind("generator", blockData.getGeneratorPublicKey()).bind("generator_signature", blockData.getGeneratorSignature()) .bind("AT_count", blockData.getATCount()).bind("AT_fees", blockData.getATFees()) .bind("online_accounts", blockData.getEncodedOnlineAccounts()).bind("online_accounts_count", blockData.getOnlineAccountsCount()) diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java index a1a091b1..698b241a 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java @@ -125,7 +125,7 @@ public class HSQLDBDatabaseUpdates { // Blocks stmt.execute("CREATE TABLE Blocks (signature BlockSignature, version TINYINT NOT NULL, reference BlockSignature, " + "transaction_count INTEGER NOT NULL, total_fees QoraAmount NOT NULL, transactions_signature Signature NOT NULL, " - + "height INTEGER NOT NULL, generation TIMESTAMP WITH TIME ZONE NOT NULL, generating_balance QoraAmount NOT NULL, " + + "height INTEGER NOT NULL, generation TIMESTAMP WITH TIME ZONE NOT NULL, " + "generator QoraPublicKey NOT NULL, generator_signature Signature NOT NULL, AT_count INTEGER NOT NULL, AT_fees QoraAmount NOT NULL, " + "PRIMARY KEY (signature))"); // For finding blocks by height. diff --git a/src/main/java/org/qora/transform/block/BlockTransformer.java b/src/main/java/org/qora/transform/block/BlockTransformer.java index b7bf5078..a569cba2 100644 --- a/src/main/java/org/qora/transform/block/BlockTransformer.java +++ b/src/main/java/org/qora/transform/block/BlockTransformer.java @@ -37,11 +37,10 @@ public class BlockTransformer extends Transformer { private static final int GENERATOR_SIGNATURE_LENGTH = SIGNATURE_LENGTH; private static final int BLOCK_REFERENCE_LENGTH = GENERATOR_SIGNATURE_LENGTH + TRANSACTIONS_SIGNATURE_LENGTH; private static final int TIMESTAMP_LENGTH = LONG_LENGTH; - private static final int GENERATING_BALANCE_LENGTH = LONG_LENGTH; private static final int GENERATOR_LENGTH = PUBLIC_KEY_LENGTH; private static final int TRANSACTION_COUNT_LENGTH = INT_LENGTH; - private static final int BASE_LENGTH = VERSION_LENGTH + TIMESTAMP_LENGTH + BLOCK_REFERENCE_LENGTH + GENERATING_BALANCE_LENGTH + GENERATOR_LENGTH + private static final int BASE_LENGTH = VERSION_LENGTH + TIMESTAMP_LENGTH + BLOCK_REFERENCE_LENGTH + GENERATOR_LENGTH + TRANSACTIONS_SIGNATURE_LENGTH + GENERATOR_SIGNATURE_LENGTH + TRANSACTION_COUNT_LENGTH; public static final int BLOCK_SIGNATURE_LENGTH = GENERATOR_SIGNATURE_LENGTH + TRANSACTIONS_SIGNATURE_LENGTH; @@ -98,8 +97,6 @@ public class BlockTransformer extends Transformer { byte[] reference = new byte[BLOCK_REFERENCE_LENGTH]; byteBuffer.get(reference); - BigDecimal generatingBalance = BigDecimal.valueOf(byteBuffer.getLong()).setScale(8); - byte[] generatorPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] transactionsSignature = new byte[TRANSACTIONS_SIGNATURE_LENGTH]; @@ -244,7 +241,7 @@ public class BlockTransformer extends Transformer { // We don't have a height! Integer height = null; - BlockData blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, + BlockData blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatorPublicKey, generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); return new Triple, List>(blockData, transactions, atStates); @@ -289,8 +286,6 @@ public class BlockTransformer extends Transformer { bytes.write(Ints.toByteArray(blockData.getVersion())); bytes.write(Longs.toByteArray(blockData.getTimestamp())); bytes.write(blockData.getReference()); - // NOTE: generatingBalance serialized as long value, not as BigDecimal, for historic compatibility - bytes.write(Longs.toByteArray(blockData.getGeneratingBalance().longValue())); bytes.write(blockData.getGeneratorPublicKey()); bytes.write(blockData.getTransactionsSignature()); bytes.write(blockData.getGeneratorSignature()); @@ -373,18 +368,16 @@ public class BlockTransformer extends Transformer { byte[] generatorSignature = getGeneratorSignatureFromReference(blockData.getReference()); PublicKeyAccount generator = new PublicKeyAccount(null, blockData.getGeneratorPublicKey()); - return getBytesForGeneratorSignature(generatorSignature, blockData.getGeneratingBalance(), generator, blockData.getEncodedOnlineAccounts()); + return getBytesForGeneratorSignature(generatorSignature, generator, blockData.getEncodedOnlineAccounts()); } - public static byte[] getBytesForGeneratorSignature(byte[] generatorSignature, BigDecimal generatingBalance, PublicKeyAccount generator, byte[] encodedOnlineAccounts) + public static byte[] getBytesForGeneratorSignature(byte[] generatorSignature, PublicKeyAccount generator, byte[] encodedOnlineAccounts) throws TransformationException { try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(GENERATOR_SIGNATURE_LENGTH + GENERATING_BALANCE_LENGTH + GENERATOR_LENGTH + encodedOnlineAccounts.length); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(GENERATOR_SIGNATURE_LENGTH + GENERATOR_LENGTH + encodedOnlineAccounts.length); bytes.write(generatorSignature); - bytes.write(Longs.toByteArray(generatingBalance.longValue())); - // We're padding here just in case the generator is the genesis account whose public key is only 8 bytes long. bytes.write(Bytes.ensureCapacity(generator.getPublicKey(), GENERATOR_LENGTH, 0)); diff --git a/src/test/java/org/qora/test/ATTests.java b/src/test/java/org/qora/test/ATTests.java deleted file mode 100644 index 3e5e8592..00000000 --- a/src/test/java/org/qora/test/ATTests.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.qora.test; - -import org.junit.Test; -import org.qora.asset.Asset; -import org.qora.data.at.ATStateData; -import org.qora.data.block.BlockData; -import org.qora.data.block.BlockTransactionData; -import org.qora.data.transaction.BaseTransactionData; -import org.qora.data.transaction.DeployAtTransactionData; -import org.qora.group.Group; -import org.qora.repository.DataException; -import org.qora.repository.Repository; -import org.qora.repository.RepositoryManager; -import org.qora.test.common.Common; -import org.qora.transaction.DeployAtTransaction; -import org.qora.transform.TransformationException; -import org.qora.utils.Base58; - -import static org.junit.Assert.*; - -import java.math.BigDecimal; -import java.util.Arrays; - -import com.google.common.hash.HashCode; - -public class ATTests extends Common { - - @Test - public void testATAccount() throws TransformationException, DataException { - // 2dZ4megUyNoYYY7qWmuSd4xw1yUKgPPF97yBbeddh8aKuC8PLpz7Xvf3r6Zjv1zwGrR8fEAHuaztCPD4KQp76KdL at height 125598 - // AT address: AaaUn82XV4YcUtsQ3rHa5ZgqyiK35rVfE3 - - String expectedAddress = "AaaUn82XV4YcUtsQ3rHa5ZgqyiK35rVfE3"; - - byte[] creatorPublicKey = HashCode.fromString("c74d71ecec6b37890f26573186e634986cc90a507af01749f92aa2c7c95ad05f").asBytes(); - String name = "QORABURST @ 1.00"; - String description = "Initiators BURST address: BURST-LKGW-Z2JK-EZ99-E7CUE"; - String ATType = "acct"; - String tags = "acct,atomic cross chain tx,initiate,initiator"; - byte[] creationBytes = HashCode - .fromString("010000000100010000000000" + "0094357700" + "000000bf" - + "3501030900000006040000000900000029302009000000040000000f1ab4000000330403090000003525010a000000260a000000320903350703090000003526010a0000001b0a000000cd322801331601000000003317010100000033180102000000331901030000003505020a0000001b0a000000a1320b033205041e050000001833000509000000320a033203041ab400000033160105000000331701060000003318010700000033190108000000320304320b033203041ab7" - + "00000048" - + "5e211280259d2f3130248482c2dfc53be2fd5f9bedc9bc21425f951e8097a21900000000c80000003ac8716ad810191acf270d22e9f47f27806256c10d6ba6144900000000000000") - .asBytes(); - BigDecimal amount = BigDecimal.valueOf(500.0).setScale(8); - BigDecimal fee = BigDecimal.valueOf(20.0).setScale(8); - long timestamp = 1439997077932L; - byte[] reference = Base58.decode("2D3jX1pEgu6irsQ7QzJb85QP1D9M45dNyP5M9a3WFHndU5ZywF4F5pnUurcbzMnGMcTwpAY6H7DuLw8cUBU66ao1"); - byte[] signature = Base58.decode("2dZ4megUyNoYYY7qWmuSd4xw1yUKgPPF97yBbeddh8aKuC8PLpz7Xvf3r6Zjv1zwGrR8fEAHuaztCPD4KQp76KdL"); - - BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, creatorPublicKey, fee, signature); - DeployAtTransactionData transactionData = new DeployAtTransactionData(baseTransactionData, name, description, ATType, tags, creationBytes, amount, Asset.QORA); - - try (final Repository repository = RepositoryManager.getRepository()) { - repository.getTransactionRepository().save(transactionData); - - DeployAtTransaction transaction = new DeployAtTransaction(repository, transactionData); - - // Fake entry for this transaction at block height 125598 if it doesn't already exist - if (transaction.getHeight() == 0) { - byte[] blockSignature = Base58.decode( - "2amu634LnAbxeLfDtWdTLiCWtKu1XM2XLK9o6fDM7yGNNoh5Tq2KxSLdx8AS486zUU1wYNGCm8mcGxjMiww979MxdPVB2PQzaKrW2aFn9hpdSNN6Nk7EmeYKwsZdx9tkpHfBt5thSrUUrhzXJju9KYCAP6p3Ty4zccFkaxCP15j332U"); - byte[] generatorSignature = Arrays.copyOfRange(blockSignature, 0, 64); - byte[] transactionsSignature = Arrays.copyOfRange(blockSignature, 64, 128); - - // Check block exists too - if (repository.getBlockRepository().fromSignature(blockSignature) == null) { - int version = 2; - byte[] blockReference = blockSignature; - int transactionCount = 0; - BigDecimal totalFees = BigDecimal.valueOf(70.0).setScale(8); - int height = 125598; - long blockTimestamp = 1439997158336L; - BigDecimal generatingBalance = BigDecimal.valueOf(1440368826L).setScale(8); - byte[] generatorPublicKey = Base58.decode("X4s833bbtghh7gejmaBMbWqD44HrUobw93ANUuaNhFc"); - int atCount = 1; - BigDecimal atFees = BigDecimal.valueOf(50.0).setScale(8); - - BlockData blockData = new BlockData(version, blockReference, transactionCount, totalFees, transactionsSignature, height, blockTimestamp, - generatingBalance, generatorPublicKey, generatorSignature, atCount, atFees); - - repository.getBlockRepository().save(blockData); - - byte[] atBytes = HashCode.fromString("17950a6c62d17ff0caa545651c054a105f1c464daca443df846cc6a3d58f764b78c09cff50f0fd9ec2").asBytes(); - - String atAddress = Base58.encode(Arrays.copyOfRange(atBytes, 0, 25)); - byte[] stateHash = Arrays.copyOfRange(atBytes, 25, atBytes.length); - - ATStateData atStateData = new ATStateData(atAddress, height, timestamp, new byte[0], stateHash, atFees); - - repository.getATRepository().save(atStateData); - } - - int sequence = 0; - - BlockTransactionData blockTransactionData = new BlockTransactionData(blockSignature, sequence, signature); - repository.getBlockRepository().save(blockTransactionData); - } - - String actualAddress = transaction.getATAccount().getAddress(); - - repository.discardChanges(); - - assertEquals(expectedAddress, actualAddress); - } - } - -} diff --git a/src/test/java/org/qora/test/SignatureTests.java b/src/test/java/org/qora/test/SignatureTests.java deleted file mode 100644 index 28553ce9..00000000 --- a/src/test/java/org/qora/test/SignatureTests.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.qora.test; - -import org.junit.Test; -import org.qora.account.PrivateKeyAccount; -import org.qora.block.Block; -import org.qora.block.GenesisBlock; -import org.qora.data.block.BlockData; -import org.qora.repository.DataException; -import org.qora.repository.Repository; -import org.qora.repository.RepositoryManager; -import org.qora.test.common.Common; -import org.qora.utils.Base58; - -import static org.junit.Assert.*; - -import java.math.BigDecimal; - -public class SignatureTests extends Common { - - @Test - public void testGenesisBlockSignature() throws DataException { - String expected58 = "6pHMBFif7jXFG654joT8GPaymau1fMtaxacRyqSrnAwQMQDvqRuLpHpfFyqX4gWVvj4pF1mwQhFgqWAvjVvPJUjmBZQvL751dM9cEcQBTaUcxtNLuWZCVUAtbnWN9f7FsLppHhkPbxwpoodL3UJYRGt3EZrG17mhv1RJbmq8j6rr7Mk"; - - try (final Repository repository = RepositoryManager.getRepository()) { - GenesisBlock block = GenesisBlock.getInstance(repository); - BlockData blockData = block.getBlockData(); - - System.out - .println("Generator: " + block.getGenerator().getAddress() + ", generator signature: " + Base58.encode(blockData.getGeneratorSignature())); - - assertEquals(expected58, Base58.encode(block.getSignature())); - } - } - - @Test - public void testBlockSignature() throws DataException { - try (final Repository repository = RepositoryManager.getRepository()) { - PrivateKeyAccount generator = new PrivateKeyAccount(repository, - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); - - int version = 3; - - byte[] reference = Base58.decode( - "BSfgEr6r1rXGGJCv8criR5NcBWfpHdJnm9x5unPwxvojEKCESv1wH1zJm7yvCeC48wshymYtARbHdUojbqWCCWW7h2UTc8g5oEx59C9M41dM7H48My8gVkcEZdxR1of3VgpE5UcowFp3kFC12hVcD9hUttJ2i2nZWMwprbFtUGyVv1U"); - - int transactionCount = 0; - BigDecimal totalFees = BigDecimal.ZERO.setScale(8); - byte[] transactionsSignature = null; - int height = 0; - long timestamp = System.currentTimeMillis() - 5000; - BigDecimal generatingBalance = BigDecimal.valueOf(10_000_000L).setScale(8); - byte[] generatorPublicKey = generator.getPublicKey(); - byte[] generatorSignature = null; - int atCount = 0; - BigDecimal atFees = BigDecimal.valueOf(10_000_000L).setScale(8); - - BlockData blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, - generatorPublicKey, generatorSignature, atCount, atFees); - - Block block = new Block(repository, blockData, generator); - block.sign(); - - assertTrue(block.isSignatureValid()); - } - } - -}