use of org.aion.evtmgr.IEvent in project aion by aionnetwork.
the class AionHub method loadBlockchain.
private void loadBlockchain() {
this.repository.getBlockStore().load();
AionBlock bestBlock = this.repository.getBlockStore().getBestBlock();
boolean recovered = true;
boolean bestBlockShifted = true;
int countRecoveryAttempts = 0;
// fix the trie if necessary
while (// the best block was updated after recovery attempt
bestBlockShifted && // allow 5 recovery attempts
(countRecoveryAttempts < 5) && // recover only for non-null blocks
bestBlock != null && !this.repository.isValidRoot(bestBlock.getStateRoot())) {
long bestBlockNumber = bestBlock.getNumber();
byte[] bestBlockRoot = bestBlock.getStateRoot();
recovered = this.blockchain.recoverWorldState(this.repository, bestBlockNumber);
if (recovered) {
bestBlock = this.repository.getBlockStore().getBestBlock();
// checking is the best block has changed since attempting recovery
if (bestBlock == null) {
bestBlockShifted = true;
} else {
bestBlockShifted = // block number changed
!(bestBlockNumber == bestBlock.getNumber()) || // root hash changed
!(Arrays.equals(bestBlockRoot, bestBlock.getStateRoot()));
}
if (bestBlockShifted) {
LOG.info("Rebuilding world state SUCCEEDED by REVERTING to a previous block.");
} else {
LOG.info("Rebuilding world state SUCCEEDED.");
}
} else {
LOG.error("Rebuilding world state FAILED. " + "Stop the kernel (Ctrl+C) and use the command line revert option to move back to a valid block. " + "Check the Aion wiki for recommendations on choosing the block number.");
}
countRecoveryAttempts++;
}
// rebuild from genesis if (1) no best block (2) recovery failed
if (bestBlock == null || !recovered) {
if (bestBlock == null) {
LOG.info("DB is empty - adding Genesis");
} else {
LOG.info("DB could not be recovered - adding Genesis");
}
AionGenesis genesis = cfg.getGenesis();
// initialization section for network balance contract
IRepositoryCache track = repository.startTracking();
Address networkBalanceAddress = PrecompiledContracts.totalCurrencyAddress;
track.createAccount(networkBalanceAddress);
for (Map.Entry<Integer, BigInteger> addr : genesis.getNetworkBalances().entrySet()) {
track.addStorageRow(networkBalanceAddress, new DataWord(addr.getKey()), new DataWord(addr.getValue()));
}
for (Address addr : genesis.getPremine().keySet()) {
track.createAccount(addr);
track.addBalance(addr, genesis.getPremine().get(addr).getBalance());
}
track.flush();
repository.commitBlock(genesis.getHeader());
this.repository.getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true);
blockchain.setBestBlock(genesis);
blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty());
if (this.eventMgr != null) {
List<IEvent> evts = new ArrayList<>();
evts.add(new EventBlock(EventBlock.CALLBACK.ONBLOCK0));
evts.add(new EventBlock(EventBlock.CALLBACK.ONTRACE0));
this.eventMgr.registerEvent(evts);
} else {
LOG.error("Event manager is null !!!");
System.exit(-1);
}
LOG.info("loaded genesis block <num={}, root={}>", 0, ByteUtil.toHexString(genesis.getStateRoot()));
} else {
blockchain.setBestBlock(bestBlock);
BigInteger totalDifficulty = this.repository.getBlockStore().getTotalDifficulty();
blockchain.setTotalDifficulty(totalDifficulty);
LOG.info("loaded block <num={}, root={}>", blockchain.getBestBlock().getNumber(), LogUtil.toHexF8(blockchain.getBestBlock().getStateRoot()));
}
if (!Arrays.equals(blockchain.getBestBlock().getStateRoot(), EMPTY_TRIE_HASH)) {
this.repository.syncToRoot(blockchain.getBestBlock().getStateRoot());
}
this.repository.getBlockStore().load();
}
use of org.aion.evtmgr.IEvent in project aion by aionnetwork.
the class AionPendingStateImpl method regBlockEvents.
private void regBlockEvents() {
List<IEvent> evts = new ArrayList<>();
evts.add(new EventBlock(EventBlock.CALLBACK.ONBLOCK0));
evts.add(new EventBlock(EventBlock.CALLBACK.ONBEST0));
this.evtMgr.registerEvent(evts);
}
use of org.aion.evtmgr.IEvent in project aion by aionnetwork.
the class AionPendingStateImpl method processBest.
@Override
public synchronized void processBest(AionBlock newBlock, List receipts) {
synchronized (txPool) {
if (getBestBlock() != null && !getBestBlock().isParentOf(newBlock)) {
// need to switch the state to another fork
IAionBlock commonAncestor = findCommonAncestor(getBestBlock(), newBlock);
if (LOG.isDebugEnabled()) {
LOG.debug("New best block from another fork: " + newBlock.getShortDescr() + ", old best: " + getBestBlock().getShortDescr() + ", ancestor: " + commonAncestor.getShortDescr());
}
// first return back the transactions from forked blocks
IAionBlock rollback = getBestBlock();
while (!rollback.isEqual(commonAncestor)) {
List<AionTransaction> atl = rollback.getTransactionsList();
if (!atl.isEmpty()) {
this.txPool.add(atl);
}
rollback = blockchain.getBlockByHash(rollback.getParentHash());
}
// rollback the state snapshot to the ancestor
pendingState = repository.getSnapshotTo(commonAncestor.getStateRoot()).startTracking();
// next process blocks from new fork
IAionBlock main = newBlock;
List<IAionBlock> mainFork = new ArrayList<>();
while (!main.isEqual(commonAncestor)) {
mainFork.add(main);
main = blockchain.getBlockByHash(main.getParentHash());
}
// processing blocks from ancestor to new block
for (int i = mainFork.size() - 1; i >= 0; i--) {
processBestInternal(mainFork.get(i), null);
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("PendingStateImpl.processBest: " + newBlock.getShortDescr());
}
processBestInternal(newBlock, receipts);
}
best = newBlock;
if (LOG.isTraceEnabled()) {
LOG.trace("PendingStateImpl.processBest: updateState");
}
updateState(best);
if (LOG.isTraceEnabled()) {
LOG.trace("PendingStateImpl.processBest: txPool.updateBlkNrgLimit");
}
txPool.updateBlkNrgLimit(best.getNrgLimit());
if (LOG.isTraceEnabled()) {
LOG.trace("PendingStateImpl.processBest: flushCachePendingTx");
}
flushCachePendingTx();
IEvent evtChange = new EventTx(EventTx.CALLBACK.PENDINGTXSTATECHANGE0);
this.evtMgr.newEvent(evtChange);
}
}
use of org.aion.evtmgr.IEvent in project aion by aionnetwork.
the class AionPendingStateImpl method addPendingTransactions.
@Override
public synchronized List<AionTransaction> addPendingTransactions(List<AionTransaction> transactions) {
int unknownTx = 0;
List<AionTransaction> newPending = new ArrayList<>();
// Map<Address, BigInteger> dbNonce = new HashMap<>();
for (AionTransaction tx : transactions) {
BigInteger txNonce = new BigInteger(1, tx.getNonce());
BigInteger bestNonce = bestNonce(tx.getFrom());
if (txNonce.compareTo(bestNonce) > 0) {
addToTxCache(tx);
LOG.debug("Adding transaction to cache: from = {}, nonce = {}", tx.getFrom(), txNonce);
} else if (txNonce.equals(bestNonce)) {
Map<BigInteger, AionTransaction> cache = pendingTxCache.geCacheTx(tx.getFrom());
do {
if (addNewTxIfNotExist(tx)) {
unknownTx++;
if (addPendingTransactionImpl(tx, txNonce)) {
newPending.add(tx);
} else {
break;
}
}
txNonce = txNonce.add(BigInteger.ONE);
} while (cache != null && (tx = cache.get(txNonce)) != null);
}
/* else {
// check repay tx
if (dbNonce.get(tx.getFrom()) == null) {
dbNonce.put(tx.getFrom(), this.repository.getNonce(tx.getFrom()));
}
if (dbNonce.get(tx.getFrom()).compareTo(txNonce) < 1) {
if (addNewTxIfNotExist(tx)) {
unknownTx++;
if (addPendingTransactionImpl(tx, txNonce)) {
newPending.add(tx);
}
}
}
} */
}
if (LOG.isDebugEnabled()) {
LOG.debug("Wire transaction list added: total: {}, new: {}, valid (added to pending): {} (current #of known txs: {})", transactions.size(), unknownTx, newPending, receivedTxs.size());
}
if (!newPending.isEmpty()) {
IEvent evtRecv = new EventTx(EventTx.CALLBACK.PENDINGTXRECEIVED0);
evtRecv.setFuncArgs(Collections.singletonList(newPending));
this.evtMgr.newEvent(evtRecv);
IEvent evtChange = new EventTx(EventTx.CALLBACK.PENDINGTXSTATECHANGE0);
this.evtMgr.newEvent(evtChange);
}
// Broadcast new pending transactions
AionImpl.inst().broadcastTransactions(newPending);
return newPending;
}
use of org.aion.evtmgr.IEvent in project aion by aionnetwork.
the class SyncMgr method setupEventHandler.
private void setupEventHandler() {
List<IEvent> events = new ArrayList<>();
events.add(new EventConsensus(EventConsensus.CALLBACK.ON_SYNC_DONE));
this.evtMgr.registerEvent(events);
}
Aggregations