Search in sources :

Example 1 with IEvent

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();
}
Also used : Address(org.aion.base.type.Address) IEvent(org.aion.evtmgr.IEvent) DataWord(org.aion.mcf.vm.types.DataWord) BigInteger(java.math.BigInteger) EventBlock(org.aion.evtmgr.impl.evt.EventBlock) IRepositoryCache(org.aion.base.db.IRepositoryCache) BigInteger(java.math.BigInteger) AionBlock(org.aion.zero.impl.types.AionBlock)

Example 2 with IEvent

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);
}
Also used : EventBlock(org.aion.evtmgr.impl.evt.EventBlock) IEvent(org.aion.evtmgr.IEvent)

Example 3 with IEvent

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);
    }
}
Also used : EventTx(org.aion.evtmgr.impl.evt.EventTx) IEvent(org.aion.evtmgr.IEvent)

Example 4 with IEvent

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;
}
Also used : EventTx(org.aion.evtmgr.impl.evt.EventTx) IEvent(org.aion.evtmgr.IEvent) BigInteger(java.math.BigInteger) LRUMap(org.apache.commons.collections4.map.LRUMap)

Example 5 with IEvent

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);
}
Also used : IEvent(org.aion.evtmgr.IEvent) EventConsensus(org.aion.evtmgr.impl.evt.EventConsensus)

Aggregations

IEvent (org.aion.evtmgr.IEvent)13 EventConsensus (org.aion.evtmgr.impl.evt.EventConsensus)4 EventTx (org.aion.evtmgr.impl.evt.EventTx)4 BigInteger (java.math.BigInteger)3 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)3 IHandler (org.aion.evtmgr.IHandler)2 AionBlock (org.aion.zero.impl.types.AionBlock)2 IRepositoryCache (org.aion.base.db.IRepositoryCache)1 Address (org.aion.base.type.Address)1 Solution (org.aion.equihash.Solution)1 EventMiner (org.aion.evtmgr.impl.evt.EventMiner)1 ImportResult (org.aion.mcf.core.ImportResult)1 DataWord (org.aion.mcf.vm.types.DataWord)1 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)1 IAionBlock (org.aion.zero.types.IAionBlock)1 LRUMap (org.apache.commons.collections4.map.LRUMap)1 JSONObject (org.json.JSONObject)1