Search in sources :

Example 1 with IContractDetails

use of org.aion.base.db.IContractDetails 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 2 with IContractDetails

use of org.aion.base.db.IContractDetails in project aion by aionnetwork.

the class AionRepositoryCache method flush.

/**
 * @implNote To maintain intended functionality this method does not call
 *           the parent's {@code flush()} method. The changes are propagated
 *           to the parent through calling the parent's
 *           {@code updateBatch()} method.
 */
@Override
public synchronized void flush() {
    // determine which accounts should get stored
    HashMap<Address, AccountState> cleanedCacheAccounts = new HashMap<>();
    for (Map.Entry<Address, AccountState> entry : cachedAccounts.entrySet()) {
        AccountState account = entry.getValue();
        if (account != null && account.isDirty() && account.isEmpty()) {
            // ignore contract state for empty accounts at storage
            cachedDetails.remove(entry.getKey());
        } else {
            cleanedCacheAccounts.put(entry.getKey(), entry.getValue());
        }
    }
    // determine which contracts should get stored
    for (Map.Entry<Address, IContractDetails<DataWord>> entry : cachedDetails.entrySet()) {
        IContractDetails<DataWord> ctd = entry.getValue();
        // different ContractDetails implementation
        if (ctd != null && ctd instanceof ContractDetailsCacheImpl) {
            ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl) ctd;
            contractDetailsCache.commit();
            if (contractDetailsCache.origContract == null && repository.hasContractDetails(entry.getKey())) {
                // in forked block the contract account might not exist thus
                // it is created without
                // origin, but on the main chain details can contain data
                // which should be merged
                // into a single storage trie so both branches with
                // different stateRoots are valid
                contractDetailsCache.origContract = repository.getContractDetails(entry.getKey());
                contractDetailsCache.commit();
            }
        }
    }
    repository.updateBatch(cleanedCacheAccounts, cachedDetails);
    cachedAccounts.clear();
    cachedDetails.clear();
}
Also used : IContractDetails(org.aion.base.db.IContractDetails) Address(org.aion.base.type.Address) HashMap(java.util.HashMap) ContractDetailsCacheImpl(org.aion.mcf.db.ContractDetailsCacheImpl) DataWord(org.aion.mcf.vm.types.DataWord) AccountState(org.aion.mcf.core.AccountState) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

HashMap (java.util.HashMap)2 IContractDetails (org.aion.base.db.IContractDetails)2 Address (org.aion.base.type.Address)2 DataWord (org.aion.mcf.vm.types.DataWord)2 Map (java.util.Map)1 IByteArrayKeyValueDatabase (org.aion.base.db.IByteArrayKeyValueDatabase)1 AccountState (org.aion.mcf.core.AccountState)1 ContractDetailsCacheImpl (org.aion.mcf.db.ContractDetailsCacheImpl)1 AionContractDetailsImpl (org.aion.zero.db.AionContractDetailsImpl)1 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)1 Test (org.junit.Test)1