Remove "generating balance", and all related aspects/code.

Block forging is now allowed by level 1+ accounts,
instead of accounts with "minting flag" set.
This commit is contained in:
catbref 2019-09-27 15:16:12 +01:00
parent 4c6656dd17
commit 305bb38446
13 changed files with 48 additions and 497 deletions

View File

@ -5,9 +5,7 @@ import java.util.List;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qora.asset.Asset;
import org.qora.block.Block; import org.qora.block.Block;
import org.qora.block.BlockChain;
import org.qora.data.account.AccountBalanceData; import org.qora.data.account.AccountBalanceData;
import org.qora.data.account.AccountData; import org.qora.data.account.AccountData;
import org.qora.data.block.BlockData; import org.qora.data.block.BlockData;
@ -53,44 +51,6 @@ public class Account {
return new AccountData(this.address); return new AccountData(this.address);
} }
// More information
/**
* Calculate current generating balance for this account.
* <p>
* This is the current confirmed balance minus amounts received in the last <code>BlockChain.BLOCK_RETARGET_INTERVAL</code> 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 // Balance manipulations - assetId is 0 for QORA
public BigDecimal getBalance(long assetId, int confirmations) throws DataException { public BigDecimal getBalance(long assetId, int confirmations) throws DataException {

View File

@ -13,8 +13,8 @@ public class Forging {
} }
public static boolean canForge(Account account) throws DataException { public static boolean canForge(Account account) throws DataException {
Integer flags = account.getFlags(); Integer level = account.getLevel();
return flags != null && (flags & getForgingMask()) != 0; return level != null && level > 0;
} }
} }

View File

@ -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 @GET
@Path("/balance/{address}") @Path("/balance/{address}")
@Operation( @Operation(
@ -228,7 +201,7 @@ public class AddressesResource {
} }
) )
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) @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)) if (!Crypto.isValidAddress(address))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_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(); throw new UnsupportedOperationException();
} }

View File

@ -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.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -28,7 +27,6 @@ import org.qora.api.ApiErrors;
import org.qora.api.ApiException; import org.qora.api.ApiException;
import org.qora.api.ApiExceptionFactory; import org.qora.api.ApiExceptionFactory;
import org.qora.api.model.BlockForgerSummary; import org.qora.api.model.BlockForgerSummary;
import org.qora.block.Block;
import org.qora.crypto.Crypto; import org.qora.crypto.Crypto;
import org.qora.data.account.AccountData; import org.qora.data.account.AccountData;
import org.qora.data.block.BlockData; 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 @GET
@Path("/height") @Path("/height")
@Operation( @Operation(

View File

@ -34,7 +34,6 @@ import org.qora.data.block.BlockTransactionData;
import org.qora.data.network.OnlineAccountData; import org.qora.data.network.OnlineAccountData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.repository.ATRepository; import org.qora.repository.ATRepository;
import org.qora.repository.BlockRepository;
import org.qora.repository.DataException; import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import org.qora.repository.TransactionRepository; import org.qora.repository.TransactionRepository;
@ -55,28 +54,6 @@ import com.google.common.primitives.Longs;
import io.druid.extendedset.intset.ConciseSet; 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 { public class Block {
// Validation results // Validation results
@ -93,7 +70,6 @@ public class Block {
TIMESTAMP_INCORRECT(24), TIMESTAMP_INCORRECT(24),
VERSION_INCORRECT(30), VERSION_INCORRECT(30),
FEATURE_NOT_YET_RELEASED(31), FEATURE_NOT_YET_RELEASED(31),
GENERATING_BALANCE_INCORRECT(40),
GENERATOR_NOT_ACCEPTED(41), GENERATOR_NOT_ACCEPTED(41),
GENESIS_TRANSACTIONS_INVALID(50), GENESIS_TRANSACTIONS_INVALID(50),
TRANSACTION_TIMESTAMP_INVALID(51), TRANSACTION_TIMESTAMP_INVALID(51),
@ -144,8 +120,6 @@ public class Block {
/** Locally-generated AT fees */ /** Locally-generated AT fees */
protected BigDecimal ourAtFees; // Generated locally protected BigDecimal ourAtFees; // Generated locally
/** Cached copy of next block's generating balance */
protected BigDecimal cachedNextGeneratingBalance;
/** Minimum Qora balance for use in calculations. */ /** Minimum Qora balance for use in calculations. */
public static final BigDecimal MIN_BALANCE = BigDecimal.valueOf(1L).setScale(8); 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. * Note that CIYAM ATs will be executed and AT-Transactions prepended to this block, along with AT state data and fees.
* *
* @param repository * @param repository
* @param version * @param parentBlockData
* @param reference
* @param timestamp
* @param generatingBalance
* @param generator * @param generator
* @throws DataException * @throws DataException
*/ */
@ -231,7 +202,6 @@ public class Block {
int version = parentBlock.getNextBlockVersion(); int version = parentBlock.getNextBlockVersion();
byte[] reference = parentBlockData.getSignature(); byte[] reference = parentBlockData.getSignature();
BigDecimal generatingBalance = parentBlock.calcNextBlockGeneratingBalance();
// Fetch our list of online accounts // Fetch our list of online accounts
List<OnlineAccountData> onlineAccounts = Controller.getInstance().getOnlineAccounts(); List<OnlineAccountData> onlineAccounts = Controller.getInstance().getOnlineAccounts();
@ -274,8 +244,7 @@ public class Block {
byte[] generatorSignature; byte[] generatorSignature;
try { try {
generatorSignature = generator generatorSignature = generator.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generator, encodedOnlineAccounts));
.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generatingBalance, generator, encodedOnlineAccounts));
} catch (TransformationException e) { } catch (TransformationException e) {
throw new DataException("Unable to calculate next block generator signature", e); throw new DataException("Unable to calculate next block generator signature", e);
} }
@ -293,7 +262,7 @@ public class Block {
BigDecimal totalFees = atFees; BigDecimal totalFees = atFees;
// This instance used for AT processing // 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, generator.getPublicKey(), generatorSignature, atCount, atFees,
encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
@ -306,7 +275,7 @@ public class Block {
totalFees = atFees; totalFees = atFees;
// Rebuild blockData using post-AT-execute data // 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, generator.getPublicKey(), generatorSignature, atCount, atFees,
encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
} }
@ -334,12 +303,10 @@ public class Block {
// Calculate new block timestamp // Calculate new block timestamp
int version = this.blockData.getVersion(); int version = this.blockData.getVersion();
byte[] reference = this.blockData.getReference(); byte[] reference = this.blockData.getReference();
BigDecimal generatingBalance = this.blockData.getGeneratingBalance();
byte[] generatorSignature; byte[] generatorSignature;
try { try {
generatorSignature = generator generatorSignature = generator.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generator, this.blockData.getEncodedOnlineAccounts()));
.sign(BlockTransformer.getBytesForGeneratorSignature(parentBlockData.getGeneratorSignature(), generatingBalance, generator, this.blockData.getEncodedOnlineAccounts()));
} catch (TransformationException e) { } catch (TransformationException e) {
throw new DataException("Unable to calculate next block generator signature", e); throw new DataException("Unable to calculate next block generator signature", e);
} }
@ -360,7 +327,7 @@ public class Block {
Long onlineAccountsTimestamp = this.blockData.getOnlineAccountsTimestamp(); Long onlineAccountsTimestamp = this.blockData.getOnlineAccountsTimestamp();
byte[] onlineAccountsSignatures = this.blockData.getOnlineAccountsSignatures(); 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); generator.getPublicKey(), generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
// Resign to update transactions signature // Resign to update transactions signature
@ -412,80 +379,6 @@ public class Block {
return 4; return 4;
} }
/**
* Return the next block's generating balance.
* <p>
* Every BLOCK_RETARGET_INTERVAL the generating balance is recalculated.
* <p>
* If this block starts a new interval then the new generating balance is calculated, cached and returned.<br>
* 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. * Return block's transactions.
* <p> * <p>
@ -953,10 +846,6 @@ public class Block {
if (this.blockData.getVersion() < 2 && this.blockData.getATCount() != 0) if (this.blockData.getVersion() < 2 && this.blockData.getATCount() != 0)
return ValidationResult.FEATURE_NOT_YET_RELEASED; 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 // Check generator is allowed to forge this block
if (!isGeneratorValidToForge(parentBlock)) if (!isGeneratorValidToForge(parentBlock))
return ValidationResult.GENERATOR_NOT_ACCEPTED; return ValidationResult.GENERATOR_NOT_ACCEPTED;

View File

@ -1,6 +1,7 @@
package org.qora.block; package org.qora.block;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
@ -160,8 +161,9 @@ public class BlockChain {
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
} catch (JAXBException e) { } catch (JAXBException e) {
LOGGER.error("Unable to process blockchain config file", e); String message = "Failed to setup unmarshaller to process blockchain config file";
throw new RuntimeException("Unable to process blockchain config file", e); LOGGER.error(message, e);
throw new RuntimeException(message, e);
} }
BlockChain blockchain = null; BlockChain blockchain = null;
@ -173,8 +175,9 @@ public class BlockChain {
File jsonFile = new File(path + filename); File jsonFile = new File(path + filename);
if (!jsonFile.exists()) { if (!jsonFile.exists()) {
LOGGER.error("Blockchain config file not found: " + path + filename); String message = "Blockchain config file not found: " + path + filename;
throw new RuntimeException("Blockchain config file not found: " + path + filename); LOGGER.error(message);
throw new RuntimeException(message, new FileNotFoundException(message));
} }
jsonSource = new StreamSource(jsonFile); jsonSource = new StreamSource(jsonFile);
@ -194,14 +197,16 @@ public class BlockChain {
if (linkedException instanceof XMLMarshalException) { if (linkedException instanceof XMLMarshalException) {
String message = ((XMLMarshalException) linkedException).getInternalException().getLocalizedMessage(); String message = ((XMLMarshalException) linkedException).getInternalException().getLocalizedMessage();
LOGGER.error(message); LOGGER.error(message);
throw new RuntimeException(message); throw new RuntimeException(message, e);
} }
LOGGER.error("Unable to process blockchain config file", e); String message = "Failed to parse blockchain config file";
throw new RuntimeException("Unable to process blockchain config file", e); LOGGER.error(message, e);
throw new RuntimeException(message, e);
} catch (JAXBException e) { } catch (JAXBException e) {
LOGGER.error("Unable to process blockchain config file", e); String message = "Unexpected JAXB issue while processing blockchain config file";
throw new RuntimeException("Unable to process blockchain config file", e); LOGGER.error(message, e);
throw new RuntimeException(message, e);
} }
// Validate config // Validate config

View File

@ -46,7 +46,6 @@ public class GenesisBlock extends Block {
public static class GenesisInfo { public static class GenesisInfo {
public int version = 1; public int version = 1;
public long timestamp; public long timestamp;
public BigDecimal generatingBalance;
public TransactionData[] transactions; public TransactionData[] transactions;
@ -123,21 +122,18 @@ public class GenesisBlock extends Block {
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
// Minor fix-up
info.generatingBalance.setScale(8);
byte[] reference = GENESIS_REFERENCE; byte[] reference = GENESIS_REFERENCE;
int transactionCount = transactionsData.size(); int transactionCount = transactionsData.size();
BigDecimal totalFees = BigDecimal.ZERO.setScale(8); BigDecimal totalFees = BigDecimal.ZERO.setScale(8);
byte[] generatorPublicKey = GenesisAccount.PUBLIC_KEY; 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[] generatorSignature = calcSignature(bytesForSignature);
byte[] transactionsSignature = generatorSignature; byte[] transactionsSignature = generatorSignature;
int height = 1; int height = 1;
int atCount = 0; int atCount = 0;
BigDecimal atFees = BigDecimal.ZERO.setScale(8); 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); generatorPublicKey, generatorSignature, atCount, atFees);
} }
@ -214,7 +210,7 @@ public class GenesisBlock extends Block {
return Bytes.concat(digest, digest); 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 { 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.
@ -233,8 +229,6 @@ public class GenesisBlock extends Block {
*/ */
bytes.write(Bytes.ensureCapacity(reference, 64, 0)); 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. // 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)); 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 */ /** Convenience method for calculating genesis block signatures from block data */
private static byte[] calcSignature(BlockData blockData) { private static byte[] calcSignature(BlockData blockData) {
byte[] bytes = getBytesForSignature(blockData.getVersion(), blockData.getReference(), blockData.getGeneratingBalance(), byte[] bytes = getBytesForSignature(blockData.getVersion(), blockData.getReference(), blockData.getGeneratorPublicKey());
blockData.getGeneratorPublicKey());
return calcSignature(bytes); return calcSignature(bytes);
} }

View File

@ -27,7 +27,6 @@ public class BlockData implements Serializable {
private byte[] transactionsSignature; private byte[] transactionsSignature;
private Integer height; private Integer height;
private long timestamp; private long timestamp;
private BigDecimal generatingBalance;
private byte[] generatorPublicKey; private byte[] generatorPublicKey;
private byte[] generatorSignature; private byte[] generatorSignature;
private int atCount; 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, 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) { byte[] encodedOnlineAccounts, int onlineAccountsCount, Long onlineAccountsTimestamp, byte[] onlineAccountsSignatures) {
this.version = version; this.version = version;
this.reference = reference; this.reference = reference;
@ -53,7 +52,6 @@ public class BlockData implements Serializable {
this.transactionsSignature = transactionsSignature; this.transactionsSignature = transactionsSignature;
this.height = height; this.height = height;
this.timestamp = timestamp; this.timestamp = timestamp;
this.generatingBalance = generatingBalance;
this.generatorPublicKey = generatorPublicKey; this.generatorPublicKey = generatorPublicKey;
this.generatorSignature = generatorSignature; this.generatorSignature = generatorSignature;
this.atCount = atCount; 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, 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) {
this(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, generatorPublicKey, generatorSignature, atCount, atFees, this(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatorPublicKey, generatorSignature, atCount, atFees,
null, 0, null, null); null, 0, null, null);
} }
@ -133,10 +131,6 @@ public class BlockData implements Serializable {
return this.timestamp; return this.timestamp;
} }
public BigDecimal getGeneratingBalance() {
return this.generatingBalance;
}
public byte[] getGeneratorPublicKey() { public byte[] getGeneratorPublicKey() {
return this.generatorPublicKey; return this.generatorPublicKey;
} }

View File

@ -22,7 +22,7 @@ import static org.qora.repository.hsqldb.HSQLDBRepository.getZonedTimestampMilli
public class HSQLDBBlockRepository implements BlockRepository { public class HSQLDBBlockRepository implements BlockRepository {
private static final String BLOCK_DB_COLUMNS = "version, reference, transaction_count, total_fees, " 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"; + "AT_count, AT_fees, online_accounts, online_accounts_count, online_accounts_timestamp, online_accounts_signatures";
protected HSQLDBRepository repository; protected HSQLDBRepository repository;
@ -43,17 +43,16 @@ public class HSQLDBBlockRepository implements BlockRepository {
byte[] transactionsSignature = resultSet.getBytes(5); byte[] transactionsSignature = resultSet.getBytes(5);
int height = resultSet.getInt(6); int height = resultSet.getInt(6);
long timestamp = getZonedTimestampMilli(resultSet, 7); long timestamp = getZonedTimestampMilli(resultSet, 7);
BigDecimal generatingBalance = resultSet.getBigDecimal(8); byte[] generatorPublicKey = resultSet.getBytes(8);
byte[] generatorPublicKey = resultSet.getBytes(9); byte[] generatorSignature = resultSet.getBytes(9);
byte[] generatorSignature = resultSet.getBytes(10); int atCount = resultSet.getInt(10);
int atCount = resultSet.getInt(11); BigDecimal atFees = resultSet.getBigDecimal(11);
BigDecimal atFees = resultSet.getBigDecimal(12); byte[] encodedOnlineAccounts = resultSet.getBytes(12);
byte[] encodedOnlineAccounts = resultSet.getBytes(13); int onlineAccountsCount = resultSet.getInt(13);
int onlineAccountsCount = resultSet.getInt(14); Long onlineAccountsTimestamp = getZonedTimestampMilli(resultSet, 14);
Long onlineAccountsTimestamp = getZonedTimestampMilli(resultSet, 15); byte[] onlineAccountsSignatures = resultSet.getBytes(15);
byte[] onlineAccountsSignatures = resultSet.getBytes(16);
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, generatorPublicKey, generatorSignature, atCount, atFees,
encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
} catch (SQLException e) { } 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()) saveHelper.bind("signature", blockData.getSignature()).bind("version", blockData.getVersion()).bind("reference", blockData.getReference())
.bind("transaction_count", blockData.getTransactionCount()).bind("total_fees", blockData.getTotalFees()) .bind("transaction_count", blockData.getTransactionCount()).bind("total_fees", blockData.getTotalFees())
.bind("transactions_signature", blockData.getTransactionsSignature()).bind("height", blockData.getHeight()) .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("generator", blockData.getGeneratorPublicKey()).bind("generator_signature", blockData.getGeneratorSignature())
.bind("AT_count", blockData.getATCount()).bind("AT_fees", blockData.getATFees()) .bind("AT_count", blockData.getATCount()).bind("AT_fees", blockData.getATFees())
.bind("online_accounts", blockData.getEncodedOnlineAccounts()).bind("online_accounts_count", blockData.getOnlineAccountsCount()) .bind("online_accounts", blockData.getEncodedOnlineAccounts()).bind("online_accounts_count", blockData.getOnlineAccountsCount())

View File

@ -125,7 +125,7 @@ public class HSQLDBDatabaseUpdates {
// Blocks // Blocks
stmt.execute("CREATE TABLE Blocks (signature BlockSignature, version TINYINT NOT NULL, reference BlockSignature, " 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, " + "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, " + "generator QoraPublicKey NOT NULL, generator_signature Signature NOT NULL, AT_count INTEGER NOT NULL, AT_fees QoraAmount NOT NULL, "
+ "PRIMARY KEY (signature))"); + "PRIMARY KEY (signature))");
// For finding blocks by height. // For finding blocks by height.

View File

@ -37,11 +37,10 @@ public class BlockTransformer extends Transformer {
private static final int GENERATOR_SIGNATURE_LENGTH = SIGNATURE_LENGTH; 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 BLOCK_REFERENCE_LENGTH = GENERATOR_SIGNATURE_LENGTH + TRANSACTIONS_SIGNATURE_LENGTH;
private static final int TIMESTAMP_LENGTH = LONG_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 GENERATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int TRANSACTION_COUNT_LENGTH = INT_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; + TRANSACTIONS_SIGNATURE_LENGTH + GENERATOR_SIGNATURE_LENGTH + TRANSACTION_COUNT_LENGTH;
public static final int BLOCK_SIGNATURE_LENGTH = GENERATOR_SIGNATURE_LENGTH + TRANSACTIONS_SIGNATURE_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]; byte[] reference = new byte[BLOCK_REFERENCE_LENGTH];
byteBuffer.get(reference); byteBuffer.get(reference);
BigDecimal generatingBalance = BigDecimal.valueOf(byteBuffer.getLong()).setScale(8);
byte[] generatorPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] generatorPublicKey = Serialization.deserializePublicKey(byteBuffer);
byte[] transactionsSignature = new byte[TRANSACTIONS_SIGNATURE_LENGTH]; byte[] transactionsSignature = new byte[TRANSACTIONS_SIGNATURE_LENGTH];
@ -244,7 +241,7 @@ public class BlockTransformer extends Transformer {
// We don't have a height! // We don't have a height!
Integer height = null; 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); generatorPublicKey, generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
return new Triple<BlockData, List<TransactionData>, List<ATStateData>>(blockData, transactions, atStates); return new Triple<BlockData, List<TransactionData>, List<ATStateData>>(blockData, transactions, atStates);
@ -289,8 +286,6 @@ public class BlockTransformer extends Transformer {
bytes.write(Ints.toByteArray(blockData.getVersion())); bytes.write(Ints.toByteArray(blockData.getVersion()));
bytes.write(Longs.toByteArray(blockData.getTimestamp())); bytes.write(Longs.toByteArray(blockData.getTimestamp()));
bytes.write(blockData.getReference()); 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.getGeneratorPublicKey());
bytes.write(blockData.getTransactionsSignature()); bytes.write(blockData.getTransactionsSignature());
bytes.write(blockData.getGeneratorSignature()); bytes.write(blockData.getGeneratorSignature());
@ -373,18 +368,16 @@ public class BlockTransformer extends Transformer {
byte[] generatorSignature = getGeneratorSignatureFromReference(blockData.getReference()); byte[] generatorSignature = getGeneratorSignatureFromReference(blockData.getReference());
PublicKeyAccount generator = new PublicKeyAccount(null, blockData.getGeneratorPublicKey()); 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 { throws TransformationException {
try { 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(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. // 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)); bytes.write(Bytes.ensureCapacity(generator.getPublicKey(), GENERATOR_LENGTH, 0));

View File

@ -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);
}
}
}

View File

@ -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());
}
}
}