Search in sources :

Example 1 with IRepositoryCache

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

the class AionRepositoryImplTest method test17NodePreviousRootTest.

// test that intermediate nodes also get rolled back properly
// intermediate nodes get created when two accounts have a common substring
@Test
public void test17NodePreviousRootTest() {
    // not that it matters since things are going to be hashed, but at least
    // the root node should point to a node that contains references to both
    final Address DOG_ACC = Address.wrap("00000000000000000000000000000dog".getBytes());
    final Address DOGE_ACC = Address.wrap("0000000000000000000000000000doge".getBytes());
    AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
    IRepositoryCache track = repository.startTracking();
    track.addBalance(DOG_ACC, BigInteger.ONE);
    track.addBalance(DOGE_ACC, BigInteger.ONE);
    track.flush();
    final byte[] root = repository.getRoot();
    repository.flush();
    System.out.println("trie state after adding two accounts");
    System.out.println(repository.getWorldState().getTrieDump());
    track = repository.startTracking();
    track.addBalance(DOG_ACC, BigInteger.ONE);
    track.flush();
    System.out.println("trie state after updating balance on one account");
    System.out.println(repository.getWorldState().getTrieDump());
    assertThat(repository.getBalance(DOG_ACC)).isEqualTo(BigInteger.TWO);
    repository.flush();
    repository.syncToRoot(root);
    assertThat(repository.getBalance(DOG_ACC)).isEqualTo(BigInteger.ONE);
}
Also used : Address(org.aion.base.type.Address) IRepositoryCache(org.aion.base.db.IRepositoryCache) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) Test(org.junit.Test)

Example 2 with IRepositoryCache

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

the class AionRepositoryImplTest method testSyncToPreviousRootWithFlush.

@Test
public void testSyncToPreviousRootWithFlush() {
    final Address FIRST_ACC = Address.wrap("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE");
    AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
    byte[] originalRoot = repository.getRoot();
    IRepositoryCache track = repository.startTracking();
    track.addBalance(FIRST_ACC, BigInteger.ONE);
    track.flush();
    byte[] newRoot = repository.getRoot();
    System.out.println("state after add one account");
    System.out.println(repository.getWorldState().getTrieDump());
    // flush into cache/db
    repository.flush();
    track = repository.startTracking();
    // total should be 2
    track.addBalance(FIRST_ACC, BigInteger.ONE);
    track.flush();
    assertThat(repository.getBalance(FIRST_ACC)).isEqualTo(BigInteger.TWO);
    System.out.println("state after adding balance to FIRST_ACC");
    System.out.println(repository.getWorldState().getTrieDump());
    // flush this state into cache/db
    repository.flush();
    repository.setRoot(newRoot);
    System.out.println("state after rewinding to previous root");
    System.out.println(repository.getWorldState().getTrieDump());
    assertThat(repository.getBalance(FIRST_ACC)).isEqualTo(BigInteger.ONE);
}
Also used : Address(org.aion.base.type.Address) IRepositoryCache(org.aion.base.db.IRepositoryCache) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) Test(org.junit.Test)

Example 3 with IRepositoryCache

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

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

the class AionRepositoryImplTest method testSyncToPreviousRootNoFlush.

/**
 * Tests behaviour for trie when trying to revert to a previous root without
 * first flushing. Note the behaviour here. Interestingly enough, it seems like
 * the trie must first be flushed, so that the root node is in the caching/db layer.
 *
 * Otherwise the retrieval methods will not be able to find the temporal root value.
 */
@Test
public void testSyncToPreviousRootNoFlush() {
    final Address FIRST_ACC = Address.wrap("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE");
    final Address SECOND_ACC = Address.wrap("BEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEF");
    final AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
    byte[] originalRoot = repository.getRoot();
    // now create a new account
    IRepositoryCache track = repository.startTracking();
    track.addBalance(FIRST_ACC, BigInteger.ONE);
    track.flush();
    System.out.println("after first account added");
    System.out.println(repository.getWorldState().getTrieDump());
    byte[] firstRoot = repository.getRoot();
    track = repository.startTracking();
    track.addBalance(SECOND_ACC, BigInteger.TWO);
    track.flush();
    byte[] secondRoot = repository.getRoot();
    System.out.println("after second account added");
    System.out.println(repository.getWorldState().getTrieDump());
    assertThat(firstRoot).isNotEqualTo(originalRoot);
    assertThat(secondRoot).isNotEqualTo(firstRoot);
    repository.syncToRoot(firstRoot);
    assertThat(repository.getRoot()).isEqualTo(firstRoot);
    BigInteger balance = repository.getBalance(FIRST_ACC);
    // notice that the first blocks balance is also zero
    assertThat(balance).isEqualTo(BigInteger.ZERO);
}
Also used : Address(org.aion.base.type.Address) IRepositoryCache(org.aion.base.db.IRepositoryCache) BigInteger(java.math.BigInteger) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) Test(org.junit.Test)

Example 5 with IRepositoryCache

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

the class AionRepositoryImplTest method testAccountStateUpdateStorageRow.

@Test
public void testAccountStateUpdateStorageRow() {
    AionRepositoryImpl repository = AionRepositoryImpl.createForTesting(repoConfig);
    IRepositoryCache track = repository.startTracking();
    Address defaultAccount = Address.wrap(ByteUtil.hexStringToBytes("CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3CAF3"));
    track.addBalance(defaultAccount, BigInteger.valueOf(1));
    // Consider the original root the one after an account has been added
    byte[] originalRoot = repository.getRoot();
    byte[] key = HashUtil.blake128("hello".getBytes());
    byte[] value = HashUtil.blake128("world".getBytes());
    track.addStorageRow(defaultAccount, new DataWord(key), new DataWord(value));
    track.flush();
    byte[] retrievedValue = repository.getStorageValue(defaultAccount, new DataWord(key)).getNoLeadZeroesData();
    assertThat(retrievedValue).isEqualTo(value);
    byte[] newRoot = repository.getRoot();
    System.out.println(String.format("original root: %s", ByteUtil.toHexString(originalRoot)));
    System.out.println(String.format("new root: %s", ByteUtil.toHexString(newRoot)));
}
Also used : Address(org.aion.base.type.Address) IRepositoryCache(org.aion.base.db.IRepositoryCache) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) DataWord(org.aion.mcf.vm.types.DataWord) Test(org.junit.Test)

Aggregations

IRepositoryCache (org.aion.base.db.IRepositoryCache)8 Address (org.aion.base.type.Address)8 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)7 Test (org.junit.Test)7 DataWord (org.aion.mcf.vm.types.DataWord)3 BigInteger (java.math.BigInteger)2 IByteArrayKeyValueDatabase (org.aion.base.db.IByteArrayKeyValueDatabase)1 IEvent (org.aion.evtmgr.IEvent)1 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)1 AionContractDetailsImpl (org.aion.zero.db.AionContractDetailsImpl)1 AionBlock (org.aion.zero.impl.types.AionBlock)1