use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainForkingTest method testSameBlockDifferentNonceAndSolutionSimple.
/*-
* Tests the case where multiple threads submit a single block (content) but
* with different mining nonces and solutions. In this case our rules dictate
* that all subsequent blocks are considered invalid.
*
* (common ancestor)
* / \
* / \
* / \
* (a)o (b)x
*
* Given:
* a.td == b.td
*/
@Test
public void testSameBlockDifferentNonceAndSolutionSimple() {
StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
StandaloneBlockchain.Bundle b = builder.withValidatorConfiguration("simple").build();
StandaloneBlockchain bc = b.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.emptyList(), true);
AionBlock sameBlock = new AionBlock(block.getEncoded());
ImportResult firstRes = bc.tryToConnect(block);
// check that the returned block is the first block
assertThat(bc.getBestBlock() == block).isTrue();
ImportResult secondRes = bc.tryToConnect(sameBlock);
// the second block should get rejected, so check that the reference still refers
// to the first block (we dont change the published reference)
assertThat(bc.getBestBlock() == block).isTrue();
assertThat(firstRes).isEqualTo(ImportResult.IMPORTED_BEST);
assertThat(secondRes).isEqualTo(ImportResult.EXIST);
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainIntegrationTest method testAppendIncorrectTimestampBlock.
@Test
public void testAppendIncorrectTimestampBlock() {
StandaloneBlockchain.Bundle bundle = (new StandaloneBlockchain.Builder()).withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.EMPTY_LIST, true);
// set the block to be created 1 month in the future
block.getHeader().setTimestamp((System.currentTimeMillis() / 1000) + 2592000);
ImportResult result = bc.tryToConnect(block);
assertThat(result.isSuccessful()).isFalse();
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class BlockchainIntegrationTest method testSimpleFailedTransactionInsufficientBalance.
@Test
public void testSimpleFailedTransactionInsufficientBalance() {
// generate a recipient
final Address receiverAddress = Address.wrap(ByteUtil.hexStringToBytes("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE"));
StandaloneBlockchain.Bundle bundle = (new StandaloneBlockchain.Builder()).withValidatorConfiguration("simple").withDefaultAccounts().build();
StandaloneBlockchain bc = bundle.bc;
// (byte[] nonce, byte[] from, byte[] to, byte[] value, byte[] data)
AionTransaction tx = new AionTransaction(BigInteger.valueOf(1).toByteArray(), receiverAddress, BigInteger.valueOf(100).toByteArray(), ByteUtil.EMPTY_BYTE_ARRAY, 1L, 1L);
tx.sign(bundle.privateKeys.get(0));
AionBlock block = bc.createNewBlock(bc.getBestBlock(), Collections.singletonList(tx), true);
assertThat(block.getTransactionsList()).isEmpty();
assertThat(block.getTxTrieRoot()).isEqualTo(HashUtil.EMPTY_TRIE_HASH);
ImportResult connection = bc.tryToConnect(block);
assertThat(connection).isEqualTo(ImportResult.IMPORTED_BEST);
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class AionBlockLoader method blockWork.
private void blockWork(AionBlock block) {
if (block.getNumber() >= blockchain.getBestBlock().getNumber() || blockchain.getBlockByHash(block.getHash()) == null) {
if (block.getNumber() > 0 && !isValid(block.getHeader())) {
throw new RuntimeException();
}
ImportResult result = blockchain.tryToConnect(block);
System.out.println(df.format(new Date()) + " Imported block " + block.getShortDescr() + ": " + result + " (prework: " + exec1.getQueue().size() + ", work: " + exec2.getQueue().size() + ", blocks: " + exec1.getOrderMap().size() + ")");
} else {
if (block.getNumber() % 10000 == 0) {
System.out.println("Skipping block #" + block.getNumber());
}
}
}
use of org.aion.mcf.core.ImportResult in project aion by aionnetwork.
the class AionBlockchainImpl method tryToConnect.
public synchronized ImportResult tryToConnect(final AionBlock block) {
long currentTimestamp = System.currentTimeMillis() / THOUSAND_MS;
if (block.getTimestamp() > (currentTimestamp + this.chainConfiguration.getConstants().getClockDriftBufferTime()))
return INVALID_BLOCK;
if (LOG.isDebugEnabled()) {
LOG.debug("Try connect block hash: {}, number: {}", Hex.toHexString(block.getHash()).substring(0, 6), block.getNumber());
}
if (getBlockStore().getMaxNumber() >= block.getNumber() && getBlockStore().isBlockExist(block.getHash())) {
if (LOG.isDebugEnabled()) {
LOG.debug("Block already exist hash: {}, number: {}", Hex.toHexString(block.getHash()).substring(0, 6), block.getNumber());
}
// retry of well known block
return EXIST;
}
final ImportResult ret;
// The simple case got the block
// to connect to the main chain
final AionBlockSummary summary;
if (bestBlock.isParentOf(block)) {
summary = add(block);
ret = summary == null ? INVALID_BLOCK : IMPORTED_BEST;
} else {
if (getBlockStore().isBlockExist(block.getParentHash())) {
BigInteger oldTotalDiff = getTotalDifficulty();
summary = tryConnectAndFork(block);
ret = summary == null ? INVALID_BLOCK : (isMoreThan(getTotalDifficulty(), oldTotalDiff) ? IMPORTED_BEST : IMPORTED_NOT_BEST);
} else {
summary = null;
ret = NO_PARENT;
}
}
if (ret.isSuccessful()) {
if (this.evtMgr != null) {
IEvent evtOnBlock = new EventBlock(EventBlock.CALLBACK.ONBLOCK0);
evtOnBlock.setFuncArgs(Collections.singletonList(summary));
this.evtMgr.newEvent(evtOnBlock);
IEvent evtTrace = new EventBlock(EventBlock.CALLBACK.ONTRACE0);
String str = String.format("Block chain size: [ %d ]", this.getSizeInternal());
evtTrace.setFuncArgs(Collections.singletonList(str));
this.evtMgr.newEvent(evtTrace);
if (ret == IMPORTED_BEST) {
if (LOG.isTraceEnabled()) {
LOG.trace("IMPORTED_BEST");
}
IEvent evtOnBest = new EventBlock(EventBlock.CALLBACK.ONBEST0);
evtOnBest.setFuncArgs(Arrays.asList(block, summary.getReceipts()));
this.evtMgr.newEvent(evtOnBest);
}
}
}
return ret;
}
Aggregations