use of neo.model.core.Block in project neo-java by coranos.
the class BlockDbH2Impl method getBlock.
/**
* return the block at the given height, with transactions attached.
*
* @param blockHeight
* the block height to use.
* @param withTransactions
* if true, add transactions. If false, only return the block header.
* @return the block at the given height.
*/
private Block getBlock(final long blockHeight, final boolean withTransactions) {
synchronized (this) {
if (closed) {
return null;
}
}
final JdbcTemplate t = new JdbcTemplate(ds);
final byte[] indexBa = BlockUtil.getBlockHeightBa(blockHeight);
final String sql = getSql("getBlockWithIndex");
final List<byte[]> data = t.queryForList(sql, byte[].class, indexBa);
if (data.isEmpty()) {
return null;
}
final Block block = new Block(ByteBuffer.wrap(data.get(0)));
if (withTransactions) {
getTransactionsForBlock(block);
}
return block;
}
use of neo.model.core.Block in project neo-java by coranos.
the class BlockDbH2Impl method validate.
@Override
public void validate() {
LOG.info("STARTED validate");
final Block block0 = getBlock(0, false);
if (!block0.hash.equals(GenesisBlockUtil.GENESIS_HASH)) {
throw new RuntimeException("height 0 block hash \"" + block0.hash.toHexString() + "\" does not match genesis block hash \"" + GenesisBlockUtil.GENESIS_HASH.toHexString() + "\".");
}
long lastInfoMs = System.currentTimeMillis();
long validBlockHeight = 1;
final long maxBlockCount = getBlockCount();
while (validBlockHeight < maxBlockCount) {
LOG.debug("INTERIM DEBUG validate {} of {} STARTED ", validBlockHeight, maxBlockCount);
final Block block = getBlock(validBlockHeight, false);
if (block == null) {
LOG.error("INTERIM validate {} of {} FAILURE, block not found in blockchain.", validBlockHeight, maxBlockCount);
} else if (!containsBlockWithHash(block.prevHash)) {
LOG.error("INTERIM validate {} of {} FAILURE, prevHash {} not found in blockchain.", validBlockHeight, maxBlockCount, block.prevHash.toHexString());
deleteBlockAtHeight(validBlockHeight);
} else if (block.getIndexAsLong() != validBlockHeight) {
LOG.error("INTERIM validate {} of {} FAILURE, indexAsLong {} does not match blockchain.", validBlockHeight, maxBlockCount, block.getIndexAsLong());
deleteBlockAtHeight(validBlockHeight);
} else {
if (System.currentTimeMillis() > (lastInfoMs + 1000)) {
LOG.info("INTERIM INFO validate {} of {} SUCCESS ", validBlockHeight, maxBlockCount);
lastInfoMs = System.currentTimeMillis();
} else {
LOG.debug("INTERIM DEBUG validate {} of {} SUCCESS ", validBlockHeight, maxBlockCount);
}
}
validBlockHeight++;
}
LOG.info("SUCCESS validate");
}
use of neo.model.core.Block in project neo-java by coranos.
the class BlockDbMapDbImpl method getBlock.
/**
* return the block at the given height, with transactions attached.
*
* @param blockHeight
* the block height to use.
* @param withTransactions
* if true, add transactions. If false, only return the block header.
* @return the block at the given height.
*/
private Block getBlock(final long blockHeight, final boolean withTransactions) {
synchronized (this) {
if (closed) {
return null;
}
}
final BTreeMap<Long, byte[]> map = getBlockHeaderByIndexMap();
if (!map.containsKey(blockHeight)) {
return null;
}
final Block block = new Block(ByteBuffer.wrap(map.get(blockHeight)));
if (withTransactions) {
getTransactionsForBlock(block);
}
return block;
}
use of neo.model.core.Block in project neo-java by coranos.
the class BlockDbMapDbImpl method validate.
@Override
public void validate() {
LOG.info("STARTED validate");
try {
final Block block0 = getBlock(0, false);
if (!block0.hash.equals(GenesisBlockUtil.GENESIS_HASH)) {
throw new RuntimeException("height 0 block hash \"" + block0.hash.toHexString() + "\" does not match genesis block hash \"" + GenesisBlockUtil.GENESIS_HASH.toHexString() + "\".");
}
long lastInfoMs = System.currentTimeMillis();
long blockHeight = 0;
long lastGoodBlockIndex = -1;
final long maxBlockCount = getBlockCount();
boolean blockHeightNoLongerValid = false;
final String maxBlockCountStr;
if (LOG.isDebugEnabled() || LOG.isErrorEnabled()) {
maxBlockCountStr = NumberFormat.getIntegerInstance().format(maxBlockCount);
} else {
maxBlockCountStr = null;
}
LOG.info("INTERIM validate, clear account list STARTED");
final BTreeMap<byte[], byte[]> assetAndValueByAccountMap = getAssetAndValueByAccountMap();
assetAndValueByAccountMap.clear();
LOG.info("INTERIM validate, clear account list SUCCESS");
LOG.info("INTERIM validate, clear transaction output state STARTED");
getTransactionByAccountAndIndexMap().clear();
getTransactionByAccountMaxIndexMap().clear();
LOG.info("INTERIM validate, clear transaction output state SUCCESS");
while (blockHeight < maxBlockCount) {
final String blockHeightStr;
if (LOG.isDebugEnabled() || LOG.isErrorEnabled()) {
blockHeightStr = NumberFormat.getIntegerInstance().format(blockHeight);
} else {
blockHeightStr = null;
}
LOG.debug("INTERIM DEBUG validate {} of {} STARTED ", blockHeightStr, maxBlockCountStr);
final Block block = getBlock(blockHeight, true);
if (block == null) {
LOG.error("INTERIM validate {} of {} FAILURE, block not found in blockchain.", blockHeightStr, maxBlockCountStr);
blockHeightNoLongerValid = true;
} else if ((blockHeight != 0) && (!containsBlockWithHash(block.prevHash))) {
LOG.error("INTERIM validate {} of {} FAILURE, prevHash {} not found in blockchain.", blockHeightStr, maxBlockCountStr, block.prevHash.toHexString());
deleteBlockAtHeight(blockHeight);
blockHeightNoLongerValid = true;
} else if (block.getIndexAsLong() != blockHeight) {
LOG.error("INTERIM validate {} of {} FAILURE, indexAsLong {} does not match blockchain.", blockHeightStr, maxBlockCountStr, block.getIndexAsLong());
deleteBlockAtHeight(blockHeight);
blockHeightNoLongerValid = true;
} else if (blockHeightNoLongerValid) {
LOG.error("INTERIM validate {} of {} FAILURE, block height tainted.", blockHeightStr, maxBlockCountStr, block.getIndexAsLong());
deleteBlockAtHeight(blockHeight);
} else {
if (System.currentTimeMillis() > (lastInfoMs + 30000)) {
final String numberOfAccountsStr = NumberFormat.getIntegerInstance().format(assetAndValueByAccountMap.size());
LOG.info("INTERIM INFO validate {} of {} SUCCESS, number of accounts:{}; date:{}", blockHeightStr, maxBlockCountStr, numberOfAccountsStr, block.getTimestamp());
lastInfoMs = System.currentTimeMillis();
} else {
LOG.debug("INTERIM DEBUG validate {} of {} SUCCESS.", blockHeightStr, maxBlockCountStr);
}
final long blockIndex = block.getIndexAsLong();
int transactionIndex = 0;
final Map<ByteBuffer, byte[]> txKeyByTxHashMap = new TreeMap<>();
for (final Transaction transaction : block.getTransactionList()) {
final byte[] transactionKeyBa = getTransactionKey(blockIndex, transactionIndex);
txKeyByTxHashMap.put(ByteBuffer.wrap(transaction.getHash().toByteArray()), transactionKeyBa);
transactionIndex++;
}
putWithByteBufferKey(TRANSACTION_KEY_BY_HASH, txKeyByTxHashMap);
try {
updateAssetAndValueByAccountMap(block, false);
} catch (final Exception e) {
throw new RuntimeException("validate: error updating assets for block [" + block.getIndexAsLong() + "]" + block.hash, e);
}
lastGoodBlockIndex = block.getIndexAsLong();
}
final boolean forceSynch = (lastGoodBlockIndex % BLOCK_FORCE_SYNCH_INTERVAL) == 0;
if (forceSynch) {
LOG.info("INTERIM validate, partial commit STARTED index {}", lastGoodBlockIndex);
commitValidation(lastGoodBlockIndex);
LOG.info("INTERIM validate, partial commit SUCCESS index {}", lastGoodBlockIndex);
}
blockHeight++;
}
LOG.info("INTERIM validate, commit STARTED index {}", lastGoodBlockIndex);
commitValidation(lastGoodBlockIndex);
LOG.info("INTERIM validate, commit SUCCESS index {}", lastGoodBlockIndex);
LOG.info("SUCCESS validate");
} catch (final Exception e) {
LOG.error("FAILURE validate", e);
db.rollback();
throw new RuntimeException(e);
}
}
use of neo.model.core.Block in project neo-java by coranos.
the class BlockDbH2Impl method getBlock.
/**
* returns the block with the given hash.
*
* @param hash
* the hash to use.
* @param withTransactions
* if true, add transactions. If false, only return the block header.
* @return the block with the given hash.
*/
private Block getBlock(final UInt256 hash, final boolean withTransactions) {
synchronized (this) {
if (closed) {
return null;
}
}
final JdbcTemplate t = new JdbcTemplate(ds);
final String sql = getSql("getBlockWithHash");
final List<byte[]> data = t.queryForList(sql, byte[].class, hash.toByteArray());
if (data.isEmpty()) {
return null;
}
final Block block = new Block(ByteBuffer.wrap(data.get(0)));
if (withTransactions) {
getTransactionsForBlock(block);
}
return block;
}
Aggregations