forked from Qortal/qortal
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:
parent
4c6656dd17
commit
305bb38446
@ -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.
|
||||
* <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
|
||||
|
||||
public BigDecimal getBalance(long assetId, int confirmations) throws DataException {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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<OnlineAccountData> 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.
|
||||
* <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.
|
||||
* <p>
|
||||
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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.
|
||||
|
@ -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<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(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));
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user