use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionRepositoryImpl method queryTransaction.
/**
* @return {@code true} when the operation was successfult and {@code false} otherwise
*/
public boolean queryTransaction(byte[] txHash, Logger log) {
try {
Map<ByteArrayWrapper, AionTxInfo> txInfoList = transactionStore.getTxInfo(txHash);
if (txInfoList == null || txInfoList.isEmpty()) {
log.error("Can not find the transaction with given hash.");
return false;
}
for (Map.Entry<ByteArrayWrapper, AionTxInfo> entry : txInfoList.entrySet()) {
Block block = blockStore.getBlockByHash(entry.getKey().toBytes());
if (block == null) {
log.error("Cannot find the block data for the block hash from the transaction info. The database might be corrupted. Please consider reimporting the database by running ./aion.sh -n <network> --redo-import");
return false;
}
AionTransaction tx = block.getTransactionsList().get(entry.getValue().getIndex());
if (tx == null) {
log.error("Cannot find the transaction data for the given hash. The database might be corrupted. Please consider reimporting the database by running ./aion.sh -n <network> --redo-import");
return false;
}
log.info(tx.toString());
log.info(entry.getValue().toString());
}
return true;
} catch (Exception e) {
log.error("Error encountered while attempting to retrieve the transaction data.", e);
return false;
}
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionRepositoryImpl method dumpTestData.
public void dumpTestData(long blockNumber, String[] otherParameters, String basePath, Logger log) {
try {
String file = blockStore.dumpPastBlocksForConsensusTest(blockNumber, basePath);
if (file == null) {
log.error("Illegal arguments. Cannot print block information.");
} else {
log.info("Block information stored in " + file);
}
} catch (IOException e) {
log.error("Exception encountered while writing data to file.", e);
}
int paramIndex = 1;
// print state for parent block
Block parent = blockStore.getChainBlockByNumber(blockNumber - 1);
if (parent == null) {
log.error("Illegal arguments. Parent block is null.");
} else {
if (otherParameters.length > paramIndex && otherParameters[paramIndex].equals("skip-state")) {
log.info("Parent state information is not retrieved.");
paramIndex++;
} else {
try {
syncToRoot(parent.getStateRoot());
File file = new File(basePath, System.currentTimeMillis() + "-state-for-parent-block-" + parent.getNumber() + ".out");
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.append(Hex.toHexString(dumpImportableState(parent.getStateRoot(), Integer.MAX_VALUE, DatabaseType.STATE)));
writer.newLine();
writer.close();
log.info("Parent state information stored in " + file.getName());
} catch (IOException e) {
log.error("Exception encountered while writing data to file.", e);
}
}
// print details and storage for the given contracts
if (otherParameters.length > paramIndex) {
try {
syncToRoot(parent.getStateRoot());
File file = new File(basePath, System.currentTimeMillis() + "-state-contracts.out");
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
// iterate through contracts
for (int i = paramIndex; i < otherParameters.length; i++) {
writer.append("Contract: " + AddressUtils.wrapAddress(otherParameters[i]));
writer.newLine();
StoredContractDetails details = getContractDetails(AddressUtils.wrapAddress(otherParameters[i]));
if (details != null) {
writer.append("Details: " + Hex.toHexString(details.getEncoded()));
writer.newLine();
writer.append("Storage: " + Hex.toHexString(dumpImportableStorage(details.getStorageHash(), Integer.MAX_VALUE, AddressUtils.wrapAddress(otherParameters[i]))));
writer.newLine();
}
writer.newLine();
}
writer.close();
log.info("Contract details and storage information stored in " + file.getName());
} catch (IOException e) {
log.error("Exception encountered while writing data to file.", e);
}
}
}
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockStore method pruneAndCorrect.
public void pruneAndCorrect(Logger log) {
lock.lock();
try {
Block block = getBestBlockWithInfo();
if (block == null) {
log.error("Can't find the best block. PruneAndCorrect failed!");
log.error("Please reboot your node to trigger automatic database recovery by the kernel.");
throw new IllegalStateException("Missing the best block from the database.");
}
long initialLevel = block.getNumber();
long level = initialLevel;
long start = System.nanoTime();
final long TEN_SEC = 10_000_000_000L;
// top down pruning of nodes on side chains
while (level > 0) {
if (System.nanoTime() - start > TEN_SEC) {
log.info("Progress report: pruning side chains on level " + level + ".");
start = System.nanoTime();
}
pruneSideChains(block, log);
block = blocks.get(block.getParentHash());
if (block == null) {
log.error("Block #" + (level - 1) + " missing from the database. " + "Cannot proceed with block pruning and total difficulty updates.");
log.error(" Please shutdown the kernel and rollback the database by executing:\t./aion.sh -n <network> -r {}", level - 1);
throw new IllegalStateException("Missing block from the database.");
}
level = block.getNumber();
}
// prune genesis
pruneSideChains(block, log);
// bottom up repair of information
// initial TD set to genesis TD
level = 1;
while (level <= initialLevel) {
BigInteger totalDifficulty = correctTotalDifficulty(level, block.getTotalDifficulty(), log);
if (totalDifficulty == null) {
log.error("CorrectTotalDifficulty failed! level:{}", level);
throw new IllegalStateException("The Index database might corrupt!");
}
log.info("Updated difficulties on level " + level + " to " + " total difficulty: " + totalDifficulty + ".");
level++;
}
} finally {
lock.unlock();
}
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockStore method dumpPastBlocksForConsensusTest.
String dumpPastBlocksForConsensusTest(long firstBlock, String reportsFolder) throws IOException {
lock.lock();
try {
if (firstBlock < 0) {
return null;
}
// the 1st block will be imported by the test
// its total difficulty, state root and receipt hash can be used for validation
// the 2nd block will be used to setup the blockchain world state before import
// the 3rd block is also part of the setup as it is required for header validation
long lastBlock = firstBlock - 3;
File file = new File(reportsFolder, System.currentTimeMillis() + "-blocks-for-consensus-test.out");
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
while (firstBlock > lastBlock && firstBlock >= 0) {
List<BlockInfo> levelBlocks = getBlockInfoForLevel(firstBlock);
for (BlockInfo bi : levelBlocks) {
if (bi.isMainChain()) {
writer.append("\nBlock hash from index database: " + Hex.toHexString(bi.getHash()) + "\nTotal Difficulty: " + bi.getTotalDifficulty() + "\nBlock on main chain: " + String.valueOf(bi.isMainChain()).toUpperCase());
writer.newLine();
Block blk = blocks.get(bi.getHash());
if (blk != null) {
writer.append("\nFull block data:\n");
writer.append(blk.toString());
writer.newLine();
} else {
writer.append("Retrieved block data is null.");
}
}
}
writer.newLine();
firstBlock--;
}
writer.close();
return file.getName();
} finally {
lock.unlock();
}
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionBlockStore method revert.
/**
* Reverts the blockchain to the given height.
*
* @param targetLevel the height of the blockchain that we must revert to
*/
public void revert(long targetLevel, Logger log) {
lock.lock();
try {
log.info("Block store revert STARTED.");
Block bestBlock = getBestBlock();
if (bestBlock == null) {
log.error("Can't find the best block. Revert FAILED!" + "Please reboot your node to trigger automatic database recovery by the kernel.");
throw new IllegalStateException("Missing the best block from the database.");
}
long currentLevel = bestBlock.getNumber();
final long TARGET_BATCH_SIZE = 1_000, TEN_SEC = 10_000_000_000L;
long currentBatchSize = 0;
long time = System.nanoTime();
// ensure that the given level is lower than current
if (targetLevel >= currentLevel) {
return;
}
// walk back removing blocks greater than the given level value
while (currentLevel > targetLevel) {
// remove all the blocks at that level
List<BlockInfo> currentLevelBlocks = getBlockInfoForLevel(currentLevel);
if (currentLevelBlocks == null || currentLevelBlocks.isEmpty()) {
log.error("Null block information found at " + currentLevel + " when information should exist." + "Please reboot your node to trigger automatic database recovery by the kernel.");
} else {
for (BlockInfo bk_info : currentLevelBlocks) {
blocks.delete(bk_info.getHash());
currentBatchSize++;
}
}
// remove the level
index.remove(currentLevel);
if (currentBatchSize >= TARGET_BATCH_SIZE) {
blocks.commit();
if (System.nanoTime() - time > TEN_SEC) {
log.info("Progress report: current height=" + currentLevel);
time = System.nanoTime();
}
currentBatchSize = 0;
}
--currentLevel;
}
blocks.commit();
log.info("Block store revert COMPLETE.");
log.warn("Please be aware that the current main chain is the same chain that contained the best block encountered at the start of this operation. " + "To keep this revert operation fast the main chain has not been updated based on existing side chains. The main chain will adjust itself when new blocks are imported.");
} catch (Exception e) {
// making sure the blocks get deleted if interrupted
blocks.commit();
} finally {
lock.unlock();
}
}
Aggregations