use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainRewardTest method testBlockchainRewardMonotonicallyIncreasing.
/**
* Test that blocks between the lower and upper bounds follow
* a certain function [0, 259200]
*
* Note: this test is resource consuming!
*
* Check {@link org.aion.zero.impl.core.RewardsCalculator} for algorithm related
* to the ramp-up block time
*/
@Ignore
@Test
public void testBlockchainRewardMonotonicallyIncreasing() {
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withDefaultAccounts().withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = bundle.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
ImportResult res = bc.tryToConnect(block);
assertThat(res).isEqualTo(ImportResult.IMPORTED_BEST);
Address coinbase = block.getCoinbase();
BigInteger previousBalance = bc.getRepository().getBalance(coinbase);
// first block already sealed
for (int i = 2; i < 99999; i++) {
AionBlock b = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
ImportResult r = bc.tryToConnect(b);
assertThat(r).isEqualTo(ImportResult.IMPORTED_BEST);
// note the assumption here that blocks are mined by one coinbase
BigInteger balance = bc.getRepository().getBalance(coinbase);
assertThat(balance).isGreaterThan(previousBalance);
previousBalance = balance;
if (b.getNumber() % 1000 == 0)
System.out.println("added block #: " + i);
}
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class AionPoW method processSolution.
/**
* Processes a received solution.
*
* @param solution
* The generated equihash solution
*/
protected synchronized void processSolution(Solution solution) {
if (!shutDown.get()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Best block num [{}]", blockchain.getBestBlock().getNumber());
LOG.debug("Best block nonce [{}]", Hex.toHexString(blockchain.getBestBlock().getNonce()));
LOG.debug("Best block hash [{}]", Hex.toHexString(blockchain.getBestBlock().getHash()));
}
AionBlock block = (AionBlock) solution.getBlock();
if (!Arrays.equals(block.getHeader().getNonce(), new byte[32])) {
// block has been processed
return;
}
// set the nonce and solution
block.getHeader().setNonce(solution.getNonce());
block.getHeader().setSolution(solution.getSolution());
block.getHeader().setTimestamp(solution.getTimeStamp());
// This can be improved
ImportResult importResult = AionImpl.inst().addNewMinedBlock(block);
// Check that the new block was successfully added
if (importResult.isSuccessful()) {
if (importResult == IMPORTED_BEST) {
LOG.info("block sealed <num={}, hash={}, diff={}, tx={}>", block.getNumber(), block.getShortHash(), // LogUtil.toHexF8(newBlock.getHash()),
block.getHeader().getDifficultyBI().toString(), block.getTransactionsList().size());
} else {
LOG.debug("block sealed <num={}, hash={}, diff={}, tx={}, result={}>", block.getNumber(), // LogUtil.toHexF8(newBlock.getHash()),
block.getShortHash(), block.getHeader().getDifficultyBI().toString(), block.getTransactionsList().size(), importResult);
}
// TODO: fire block mined event
} else {
LOG.info("Unable to import a new mined block; restarting mining.\n" + "Mined block import result is " + importResult + " : " + block.getShortHash());
}
}
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockPropagationHandler method processIncomingBlock.
public PropStatus processIncomingBlock(final int nodeId, final AionBlock block) {
if (block == null)
return PropStatus.DROPPED;
ByteArrayWrapper hashWrapped = new ByteArrayWrapper(block.getHash());
if (!this.blockHeaderValidator.validate(block.getHeader(), log))
return PropStatus.DROPPED;
// guarantees if multiple requests of same block appears, only one goes through
synchronized (this.cacheMap) {
if (this.cacheMap.containsKey(hashWrapped))
return PropStatus.DROPPED;
// regardless if block processing is successful, place into cache
this.cacheMap.put(hashWrapped, true);
}
AionBlock bestBlock = this.blockchain.getBestBlock();
// assumption is that we are on the correct chain
if (bestBlock.getNumber() > block.getNumber())
return PropStatus.DROPPED;
// this implies we only propagate blocks from our own chain
if (!bestBlock.isParentOf(block))
return PropStatus.DROPPED;
// send
boolean sent = send(block, nodeId);
// process
ImportResult result = this.blockchain.tryToConnect(block);
// process resulting state
if (sent && result.isSuccessful())
return PropStatus.PROP_CONNECTED;
if (result.isSuccessful())
return PropStatus.CONNECTED;
if (sent)
return PropStatus.PROPAGATED;
// should never reach here, but just in case
return PropStatus.DROPPED;
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithPartialWorldState.
/**
* Test the recovery of the world state in the case where it is missing from the database.
*/
@Test
public void testRecoverWorldStateWithPartialWorldState() {
final int NUMBER_OF_BLOCKS = 10;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
// first half of blocks will be correct
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
result = chain.tryToConnect(chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true));
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
}
// second half of blocks will miss the state root
List<byte[]> statesToDelete = new ArrayList<>();
for (int i = 0; i < NUMBER_OF_BLOCKS / 2; i++) {
AionBlock next = chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
statesToDelete.add(next.getStateRoot());
}
AionBlock bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) ((AionRepositoryImpl) chain.getRepository()).getWorldState();
IByteArrayKeyValueDatabase database = (IByteArrayKeyValueDatabase) trie.getCache().getDb();
for (byte[] key : statesToDelete) {
database.delete(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality
boolean worked = chain.recoverWorldState(chain.getRepository(), bestBlock.getNumber());
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state is ok
assertThat(worked).isTrue();
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isTrue();
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainDataRecoveryTest method testRecoverWorldStateWithoutGenesis.
/**
* Test the recovery of the world state in the case where it is missing from the database.
*/
@Test
public void testRecoverWorldStateWithoutGenesis() {
final int NUMBER_OF_BLOCKS = 10;
// build a blockchain with a few blocks
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle bundle = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain chain = bundle.bc;
// all blocks will be incorrect
ImportResult result;
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
AionBlock next = chain.createNewBlock(chain.getBestBlock(), Collections.emptyList(), true);
result = chain.tryToConnect(next);
assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
}
AionBlock bestBlock = chain.getBestBlock();
assertThat(bestBlock.getNumber()).isEqualTo(NUMBER_OF_BLOCKS);
chain.getRepository().flush();
// delete some world state root entries from the database
TrieImpl trie = (TrieImpl) ((AionRepositoryImpl) chain.getRepository()).getWorldState();
IByteArrayKeyValueDatabase database = (IByteArrayKeyValueDatabase) trie.getCache().getDb();
List<byte[]> statesToDelete = new ArrayList<>();
statesToDelete.addAll(database.keys());
for (byte[] key : statesToDelete) {
database.delete(key);
assertThat(trie.isValidRoot(key)).isFalse();
}
// ensure that the world state was corrupted
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
// call the recovery functionality
boolean worked = chain.recoverWorldState(chain.getRepository(), bestBlock.getNumber());
// ensure that the blockchain is ok
assertThat(chain.getBestBlockHash()).isEqualTo(bestBlock.getHash());
// ensure that the world state was not recovered
assertThat(worked).isFalse();
assertThat(trie.isValidRoot(chain.getBestBlock().getStateRoot())).isFalse();
}
Aggregations