Search in sources :

Example 6 with DataWord

use of org.aion.mcf.vm.types.DataWord in project aion by aionnetwork.

the class AionContractDetailsTest method testExternalStorageTransition.

@Test
public void testExternalStorageTransition() {
    Address address = Address.wrap(RandomUtils.nextBytes(Address.ADDRESS_LEN));
    byte[] code = RandomUtils.nextBytes(512);
    Map<DataWord, DataWord> elements = new HashMap<>();
    AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
    IByteArrayKeyValueDatabase externalStorage = repository.getDetailsDatabase();
    AionContractDetailsImpl original = new AionContractDetailsImpl(0, 1000000);
    original.setExternalStorageDataSource(externalStorage);
    original.setAddress(address);
    original.setCode(code);
    for (int i = 0; i < IN_MEMORY_STORAGE_LIMIT / 64 + 10; i++) {
        DataWord key = new DataWord(RandomUtils.nextBytes(16));
        DataWord value = new DataWord(RandomUtils.nextBytes(16));
        elements.put(key, value);
        original.put(key, value);
    }
    original.syncStorage();
    assertTrue(!externalStorage.isEmpty());
    IContractDetails deserialized = deserialize(original.getEncoded(), externalStorage);
    // adds keys for in-memory storage limit overflow
    for (int i = 0; i < 10; i++) {
        DataWord key = new DataWord(RandomUtils.nextBytes(16));
        DataWord value = new DataWord(RandomUtils.nextBytes(16));
        elements.put(key, value);
        deserialized.put(key, value);
    }
    deserialized.syncStorage();
    assertTrue(!externalStorage.isEmpty());
    deserialized = deserialize(deserialized.getEncoded(), externalStorage);
    Map<DataWord, DataWord> storage = deserialized.getStorage();
    assertEquals(elements.size(), storage.size());
    for (DataWord key : elements.keySet()) {
        assertEquals(elements.get(key), storage.get(key));
    }
}
Also used : IContractDetails(org.aion.base.db.IContractDetails) Address(org.aion.base.type.Address) IByteArrayKeyValueDatabase(org.aion.base.db.IByteArrayKeyValueDatabase) HashMap(java.util.HashMap) DataWord(org.aion.mcf.vm.types.DataWord) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) AionContractDetailsImpl(org.aion.zero.db.AionContractDetailsImpl) Test(org.junit.Test)

Example 7 with DataWord

use of org.aion.mcf.vm.types.DataWord 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 8 with DataWord

use of org.aion.mcf.vm.types.DataWord in project aion by aionnetwork.

the class AionRepositoryDummy method createAccount.

public AccountState createAccount(Address addr) {
    AccountState accountState = new AccountState();
    worldState.put(addr.toByteArrayWrapper(), accountState);
    IContractDetails<DataWord> contractDetails = this.cfg.contractDetailsImpl();
    detailsDB.put(addr.toByteArrayWrapper(), contractDetails);
    return accountState;
}
Also used : DataWord(org.aion.mcf.vm.types.DataWord) AccountState(org.aion.mcf.core.AccountState)

Example 9 with DataWord

use of org.aion.mcf.vm.types.DataWord in project aion by aionnetwork.

the class AionRepositoryDummy method loadAccount.

public void loadAccount(Address addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, IContractDetails<DataWord>> cacheDetails) {
    AccountState account = getAccountState(addr);
    IContractDetails<DataWord> details = getContractDetails(addr);
    if (account == null) {
        account = new AccountState();
    } else {
        account = new AccountState(account);
    }
    if (details == null) {
        details = this.cfg.contractDetailsImpl();
    } else {
        details = details.clone();
    }
    cacheAccounts.put(addr.toByteArrayWrapper(), account);
    cacheDetails.put(addr.toByteArrayWrapper(), details);
}
Also used : DataWord(org.aion.mcf.vm.types.DataWord) AccountState(org.aion.mcf.core.AccountState)

Example 10 with DataWord

use of org.aion.mcf.vm.types.DataWord in project aion by aionnetwork.

the class AionRepositoryImpl method updateBatch.

@Override
public synchronized void updateBatch(Map<Address, AccountState> stateCache, Map<Address, IContractDetails<DataWord>> detailsCache) {
    for (Map.Entry<Address, AccountState> entry : stateCache.entrySet()) {
        Address address = entry.getKey();
        AccountState accountState = entry.getValue();
        IContractDetails<DataWord> contractDetails = detailsCache.get(address);
        if (accountState.isDeleted()) {
            // TODO-A: batch operations here
            rwLock.readLock().lock();
            try {
                worldState.delete(address.toBytes());
            } catch (Exception e) {
                LOG.error("key deleted exception [{}]", e.toString());
            } finally {
                rwLock.readLock().unlock();
            }
            LOG.debug("key deleted <key={}>", Hex.toHexString(address.toBytes()));
        } else {
            if (!contractDetails.isDirty()) {
                // ContractState class
                if (accountState.isDirty()) {
                    updateAccountState(address, accountState);
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
                    }
                }
                continue;
            }
            ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl) contractDetails;
            if (contractDetailsCache.origContract == null) {
                contractDetailsCache.origContract = this.cfg.contractDetailsImpl();
                try {
                    contractDetailsCache.origContract.setAddress(address);
                } catch (Exception e) {
                    e.printStackTrace();
                    LOG.error("contractDetailsCache setAddress exception [{}]", e.toString());
                }
                contractDetailsCache.commit();
            }
            contractDetails = contractDetailsCache.origContract;
            updateContractDetails(address, contractDetails);
            if (!Arrays.equals(accountState.getCodeHash(), EMPTY_TRIE_HASH)) {
                accountState.setStateRoot(contractDetails.getStorageHash());
            }
            updateAccountState(address, accountState);
            if (LOG.isTraceEnabled()) {
                LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
            }
        }
    }
    LOG.trace("updated: detailsCache.size: {}", detailsCache.size());
    stateCache.clear();
    detailsCache.clear();
}
Also used : Address(org.aion.base.type.Address) ContractDetailsCacheImpl(org.aion.mcf.db.ContractDetailsCacheImpl) DataWord(org.aion.mcf.vm.types.DataWord) AccountState(org.aion.mcf.core.AccountState)

Aggregations

DataWord (org.aion.mcf.vm.types.DataWord)29 Address (org.aion.base.type.Address)11 AccountState (org.aion.mcf.core.AccountState)11 Test (org.junit.Test)9 AionContractDetailsImpl (org.aion.zero.db.AionContractDetailsImpl)5 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)5 HashMap (java.util.HashMap)3 IByteArrayKeyValueDatabase (org.aion.base.db.IByteArrayKeyValueDatabase)3 IRepositoryCache (org.aion.base.db.IRepositoryCache)3 ByteArrayWrapper (org.aion.base.util.ByteArrayWrapper)3 ContractDetailsCacheImpl (org.aion.mcf.db.ContractDetailsCacheImpl)3 IContractDetails (org.aion.base.db.IContractDetails)2 RLPElement (org.aion.rlp.RLPElement)2 RLPList (org.aion.rlp.RLPList)2 AionTransaction (org.aion.zero.types.AionTransaction)2 BigInteger (java.math.BigInteger)1 Map (java.util.Map)1 ByteUtil.toHexString (org.aion.base.util.ByteUtil.toHexString)1 IEvent (org.aion.evtmgr.IEvent)1 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)1