Search in sources :

Example 1 with SecureTrie

use of org.aion.zero.impl.trie.SecureTrie in project aion by aionnetwork.

the class FvmContractDetailsTest method testDecode_withInLineStorageAndTransition.

@Test
public void testDecode_withInLineStorageAndTransition() {
    SecureTrie trie = new SecureTrie(null);
    Map<ByteArrayWrapper, ByteArrayWrapper> storage = new HashMap<>();
    for (int i = 0; i < 3; i++) {
        byte[] key = RandomUtils.nextBytes(32);
        byte[] value = RandomUtils.nextBytes(100);
        trie.update(key, RLP.encodeElement(value));
        storage.put(ByteArrayWrapper.wrap(key), ByteArrayWrapper.wrap(value));
    }
    RLPElement storageTrie = RLP.decode2SharedList(trie.serialize());
    AionAddress address = new AionAddress(RandomUtils.nextBytes(AionAddress.LENGTH));
    byte[] codeBytes = RandomUtils.nextBytes(100);
    RLPElement code = mock(SharedRLPItem.class);
    when(code.getRLPData()).thenReturn(codeBytes);
    byte[] rootHash = RandomUtils.nextBytes(32);
    RLPElement root = mock(SharedRLPItem.class);
    when(root.getRLPData()).thenReturn(rootHash);
    Logger log = mock(Logger.class);
    ByteArrayKeyValueDatabase db = new MockDB("db", log);
    db.open();
    assertThat(db.isEmpty()).isTrue();
    RLPContractDetails input = new RLPContractDetails(address, false, root, storageTrie, code);
    FvmContractDetails details = FvmContractDetails.decodeAtRoot(input, db, rootHash);
    assertThat(details.address).isEqualTo(address);
    // because it uses the setCodes method
    assertThat(details.isDirty()).isTrue();
    assertThat(details.isDeleted()).isFalse();
    assertThat(details.getCodes().size()).isEqualTo(1);
    assertThat(details.getCodes().values()).contains(ByteArrayWrapper.wrap(codeBytes));
    assertThat(details.getCode(h256(codeBytes))).isEqualTo(codeBytes);
    byte[] storageHash = trie.getRootHash();
    assertThat(details.getStorageHash()).isEqualTo(storageHash);
    for (ByteArrayWrapper key : storage.keySet()) {
        assertThat(details.get(key)).isEqualTo(storage.get(key));
    }
    assertThat(db.isEmpty()).isFalse();
}
Also used : AionAddress(org.aion.types.AionAddress) HashMap(java.util.HashMap) RLPContractDetails(org.aion.zero.impl.db.DetailsDataStore.RLPContractDetails) MockDB(org.aion.db.impl.mockdb.MockDB) Logger(org.slf4j.Logger) SecureTrie(org.aion.zero.impl.trie.SecureTrie) ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) RLPElement(org.aion.rlp.RLPElement) ByteArrayKeyValueDatabase(org.aion.db.impl.ByteArrayKeyValueDatabase) Test(org.junit.Test)

Example 2 with SecureTrie

use of org.aion.zero.impl.trie.SecureTrie in project aion by aionnetwork.

the class FvmContractDetailsTest method testDecode_withInLineStorageAndEmptyStorageTrie.

@Test
public void testDecode_withInLineStorageAndEmptyStorageTrie() {
    SecureTrie trie = new SecureTrie(null);
    RLPElement storageTrie = RLP.decode2SharedList(trie.serialize());
    AionAddress address = new AionAddress(RandomUtils.nextBytes(AionAddress.LENGTH));
    byte[] codeBytes = RandomUtils.nextBytes(100);
    RLPElement code = mock(SharedRLPItem.class);
    when(code.getRLPData()).thenReturn(codeBytes);
    byte[] storageHash = EMPTY_TRIE_HASH;
    RLPElement root = mock(SharedRLPItem.class);
    when(root.getRLPData()).thenReturn(storageHash);
    ByteArrayKeyValueDatabase db = new MockDB("db", log);
    db.open();
    assertThat(db.isEmpty()).isTrue();
    RLPContractDetails input = new RLPContractDetails(address, false, root, storageTrie, code);
    FvmContractDetails details = FvmContractDetails.decodeAtRoot(input, db, storageHash);
    assertThat(details.address).isEqualTo(address);
    // because it uses the setCodes method
    assertThat(details.isDirty()).isTrue();
    assertThat(details.isDeleted()).isFalse();
    assertThat(details.getCodes().size()).isEqualTo(1);
    assertThat(details.getCodes().values()).contains(ByteArrayWrapper.wrap(codeBytes));
    assertThat(details.getCode(h256(codeBytes))).isEqualTo(codeBytes);
    assertThat(details.getStorageHash()).isEqualTo(storageHash);
}
Also used : AionAddress(org.aion.types.AionAddress) RLPElement(org.aion.rlp.RLPElement) ByteArrayKeyValueDatabase(org.aion.db.impl.ByteArrayKeyValueDatabase) RLPContractDetails(org.aion.zero.impl.db.DetailsDataStore.RLPContractDetails) MockDB(org.aion.db.impl.mockdb.MockDB) SecureTrie(org.aion.zero.impl.trie.SecureTrie) Test(org.junit.Test)

Example 3 with SecureTrie

use of org.aion.zero.impl.trie.SecureTrie in project aion by aionnetwork.

the class AvmContractDetails method decodeAtRoot.

/**
 * Decodes an AvmContractDetails object from the RLP encoding and returns a snapshot to the
 * specific point in the blockchain history given by the consensus root hash.
 *
 * @param input the stored encoding representing the contract details
 * @param storageSource the data source for the contract storage data
 * @param objectGraphSource the data source for the object graph
 * @param consensusRoot the consensus root linking to specific external storage and object graph
 *     data at the point of interest in the blockchain history
 * @return a snapshot of the contract details with the information it contained at the specified
 *     point in the blockchain history
 */
public static AvmContractDetails decodeAtRoot(RLPContractDetails input, ByteArrayKeyValueStore storageSource, ByteArrayKeyValueStore objectGraphSource, byte[] consensusRoot) {
    Objects.requireNonNull(input, "The contract data for the snapshot cannot be null.");
    Objects.requireNonNull(consensusRoot, "The consensus root for the snapshot cannot be null.");
    // additional null check are performed by the constructor
    AvmContractDetails details = new AvmContractDetails(input.address, storageSource, objectGraphSource);
    RLPElement code = input.code;
    if (code instanceof SharedRLPList) {
        for (RLPElement e : ((SharedRLPList) code)) {
            if (e.isList()) {
                details.setCode(SharedRLPList.getRLPDataCopy((SharedRLPList) e));
            } else {
                details.setCode(e.getRLPData());
            }
        }
    } else if (code instanceof RLPList) {
        for (RLPElement e : ((RLPList) code)) {
            details.setCode(e.getRLPData());
        }
    } else {
        details.setCode(code.getRLPData());
    }
    // The root is the concatenated storage hash.
    // It points to the external storage hash and the object graph hash.
    RLPElement storage = input.storageTrie;
    // Instantiates the storage interpreting the storage root according to the VM specification.
    byte[] storageRootHash;
    Optional<byte[]> concatenatedData = details.objectGraphSource.get(consensusRoot);
    if (concatenatedData.isPresent()) {
        SharedRLPList data = RLP.decode2SharedList(concatenatedData.get());
        if (!(data.get(0).isList())) {
            throw new IllegalArgumentException("Invalid concatenated storage for AVM.");
        }
        SharedRLPList pair = (SharedRLPList) data.get(0);
        if (pair.size() != 2) {
            throw new IllegalArgumentException("Invalid concatenated storage for AVM.");
        }
        storageRootHash = pair.get(0).getRLPData();
        details.objectGraphHash = pair.get(1).getRLPData();
    } else {
        // As a result the concatenated storage hash cannot be missing from the database.
        throw new IllegalArgumentException("Invalid concatenated storage for AVM.");
    }
    // load/deserialize storage trie
    if (input.isExternalStorage) {
        // ensure transition from old encoding
        details.storageTrie = new SecureTrie(details.externalStorageSource, storageRootHash);
    } else {
        details.storageTrie = new SecureTrie(null);
        details.storageTrie.deserialize((SharedRLPList) storage);
        // switch from in-memory to external storage
        details.storageTrie.getCache().setDB(details.externalStorageSource);
        details.storageTrie.sync();
    }
    if (Arrays.equals(storageRootHash, ConstantUtil.EMPTY_TRIE_HASH)) {
        details.storageTrie = new SecureTrie(details.storageTrie.getCache(), "".getBytes());
    }
    return details;
}
Also used : RLPElement(org.aion.rlp.RLPElement) SharedRLPList(org.aion.rlp.SharedRLPList) SecureTrie(org.aion.zero.impl.trie.SecureTrie) RLPList(org.aion.rlp.RLPList) SharedRLPList(org.aion.rlp.SharedRLPList)

Example 4 with SecureTrie

use of org.aion.zero.impl.trie.SecureTrie in project aion by aionnetwork.

the class FvmContractDetails method decodeAtRoot.

/**
 * Decodes an FvmContractDetails object from the RLP encoding and returns a snapshot to the
 * specific point in the blockchain history given by the consensus root hash.
 *
 * @param input the stored encoding representing the contract details
 * @param storageSource the data source for the contract storage data
 * @param consensusRoot the consensus root linking to specific external storage and object graph
 *     data at the point of interest in the blockchain history
 * @return a snapshot of the contract details with the information it contained at the specified
 *     point in the blockchain history
 */
public static FvmContractDetails decodeAtRoot(RLPContractDetails input, ByteArrayKeyValueStore storageSource, byte[] consensusRoot) {
    Objects.requireNonNull(input, "The contract data for the snapshot cannot be null.");
    Objects.requireNonNull(consensusRoot, "The consensus root for the snapshot cannot be null.");
    // additional null check are performed by the constructor
    FvmContractDetails details = new FvmContractDetails(input.address, storageSource);
    RLPElement code = input.code;
    if (code instanceof SharedRLPList) {
        for (RLPElement e : ((SharedRLPList) code)) {
            if (e.isList()) {
                details.setCode(SharedRLPList.getRLPDataCopy((SharedRLPList) e));
            } else {
                details.setCode(e.getRLPData());
            }
        }
    } else if (code instanceof RLPList) {
        for (RLPElement e : ((RLPList) code)) {
            details.setCode(e.getRLPData());
        }
    } else {
        details.setCode(code.getRLPData());
    }
    // NOTE: under normal circumstances the VM type is set by the details data store
    // Do not forget to set the vmType value externally during tests!!!
    RLPElement storage = input.storageTrie;
    // load/deserialize storage trie
    if (input.isExternalStorage) {
        // ensure transition from old encoding
        details.storageTrie = new SecureTrie(details.externalStorageSource, consensusRoot);
    } else {
        details.storageTrie = new SecureTrie(null);
        details.storageTrie.deserialize((SharedRLPList) storage);
        // switch from in-memory to external storage
        details.storageTrie.getCache().setDB(details.externalStorageSource);
        details.storageTrie.sync();
    }
    if (Arrays.equals(consensusRoot, ConstantUtil.EMPTY_TRIE_HASH)) {
        details.storageTrie = new SecureTrie(details.storageTrie.getCache(), "".getBytes());
    }
    return details;
}
Also used : RLPElement(org.aion.rlp.RLPElement) SharedRLPList(org.aion.rlp.SharedRLPList) SecureTrie(org.aion.zero.impl.trie.SecureTrie) RLPList(org.aion.rlp.RLPList) SharedRLPList(org.aion.rlp.SharedRLPList)

Example 5 with SecureTrie

use of org.aion.zero.impl.trie.SecureTrie in project aion by aionnetwork.

the class AionRepositoryImpl method getReferencedStorageNodes.

@VisibleForTesting
public List<byte[]> getReferencedStorageNodes(byte[] value, int limit, AionAddress contract) {
    if (limit <= 0) {
        return Collections.emptyList();
    } else {
        byte[] subKey = h256(("details-storage/" + contract.toString()).getBytes());
        ByteArrayKeyValueStore db = new XorDataSource(selectDatabase(DatabaseType.STORAGE), subKey, false);
        Trie trie = new SecureTrie(db);
        Map<ByteArrayWrapper, byte[]> refs = trie.getReferencedTrieNodes(value, limit);
        List<byte[]> converted = new ArrayList<>();
        for (ByteArrayWrapper key : refs.keySet()) {
            converted.add(ByteUtil.xorAlignRight(key.toBytes(), subKey));
        }
        return converted;
    }
}
Also used : XorDataSource(org.aion.db.store.XorDataSource) ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) ArrayList(java.util.ArrayList) ByteArrayKeyValueStore(org.aion.db.impl.ByteArrayKeyValueStore) SecureTrie(org.aion.zero.impl.trie.SecureTrie) Trie(org.aion.zero.impl.trie.Trie) SecureTrie(org.aion.zero.impl.trie.SecureTrie) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

SecureTrie (org.aion.zero.impl.trie.SecureTrie)8 RLPElement (org.aion.rlp.RLPElement)6 AionAddress (org.aion.types.AionAddress)5 RLPContractDetails (org.aion.zero.impl.db.DetailsDataStore.RLPContractDetails)5 Test (org.junit.Test)5 ByteArrayKeyValueDatabase (org.aion.db.impl.ByteArrayKeyValueDatabase)4 MockDB (org.aion.db.impl.mockdb.MockDB)4 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)4 HashMap (java.util.HashMap)3 Logger (org.slf4j.Logger)3 RLPList (org.aion.rlp.RLPList)2 SharedRLPList (org.aion.rlp.SharedRLPList)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 ArrayList (java.util.ArrayList)1 ByteArrayKeyValueStore (org.aion.db.impl.ByteArrayKeyValueStore)1 XorDataSource (org.aion.db.store.XorDataSource)1 Trie (org.aion.zero.impl.trie.Trie)1