Search in sources :

Example 6 with IAvmResourceFactory

use of org.aion.avm.stub.IAvmResourceFactory in project aion by aionnetwork.

the class BlockchainForkingTest method testVmTypeRetrieval_ForkWithConflictingContractVM.

/**
 * Ensures that if a side-chain block is imported after a main-chain block creating the same
 * contract address X but using different VMs, then each chain will operate on the correct VM.
 */
@Test
public void testVmTypeRetrieval_ForkWithConflictingContractVM() throws Exception {
    TestResourceProvider resourceProvider = TestResourceProvider.initializeAndCreateNewProvider(AvmPathManager.getPathOfProjectRootDirectory());
    IAvmResourceFactory resourceFactory = resourceProvider.factoryForVersion1;
    // blocks to be built
    MiningBlock block, fastBlock, slowBlock, lowBlock, highBlock;
    // transactions used in blocks
    AionTransaction deployOnAVM, deployOnFVM, callTxOnFVM;
    // for processing block results
    Pair<ImportResult, AionBlockSummary> connectResult;
    ImportResult result;
    AionTxReceipt receipt;
    // build a blockchain
    TransactionTypeRule.allowAVMContractTransaction();
    List<ECKey> accounts = generateAccounts(10);
    StandaloneBlockchain.Builder builder = new StandaloneBlockchain.Builder();
    StandaloneBlockchain sourceChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build().bc;
    StandaloneBlockchain testChain = builder.withValidatorConfiguration("simple").withDefaultAccounts(accounts).build().bc;
    ECKey sender = accounts.remove(0);
    assertThat(testChain).isNotEqualTo(sourceChain);
    assertThat(testChain.genesis).isEqualTo(sourceChain.genesis);
    long time = System.currentTimeMillis();
    // add a block to both chains
    block = sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), Collections.emptyList(), true, time / 10_000L).block;
    assertThat(sourceChain.tryToConnect(block)).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(testChain.tryToConnect(block)).isEqualTo(ImportResult.IMPORTED_BEST);
    // ****** setup side chain ******
    // deploy contracts on different VMs for the two chains
    deployOnAVM = deployStatefulnessAVMContract(resourceFactory, sender);
    fastBlock = sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), Arrays.asList(deployOnAVM), true, time / 10_000L).block;
    deployOnFVM = deployContract(sender);
    slowBlock = new MiningBlock(sourceChain.createNewMiningBlockInternal(sourceChain.getBestBlock(), Arrays.asList(deployOnFVM), true, time / 10_000L).block);
    MiningBlockHeader newBlockHeader = MiningBlockHeader.Builder.newInstance().withHeader(slowBlock.getHeader()).withTimestamp(time / 10_000L + 100).build();
    slowBlock.updateHeader(newBlockHeader);
    time += 100;
    // sourceChain imports only fast block
    connectResult = sourceChain.tryToConnectAndFetchSummary(fastBlock);
    result = connectResult.getLeft();
    receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(receipt.isSuccessful()).isTrue();
    AionAddress contract = TxUtil.calculateContractAddress(receipt.getTransaction());
    // testChain imports both blocks
    connectResult = testChain.tryToConnectAndFetchSummary(fastBlock);
    result = connectResult.getLeft();
    receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    assertThat(receipt.isSuccessful()).isTrue();
    assertThat(TxUtil.calculateContractAddress(receipt.getTransaction())).isEqualTo(contract);
    connectResult = testChain.tryToConnectAndFetchSummary(slowBlock);
    result = connectResult.getLeft();
    receipt = connectResult.getRight().getReceipts().get(0);
    assertThat(result).isEqualTo(ImportResult.IMPORTED_NOT_BEST);
    assertThat(receipt.isSuccessful()).isTrue();
    assertThat(TxUtil.calculateContractAddress(receipt.getTransaction())).isEqualTo(contract);
    // ****** check that the correct contract details are kept ******
    // check that both chains have the correct vm type for the AVM contract
    byte[] codeHashAVM = sourceChain.getRepository().getAccountState(contract).getCodeHash();
    assertThat(testChain.getRepository().getVMUsed(contract, codeHashAVM)).isEqualTo(sourceChain.getRepository().getVMUsed(contract, codeHashAVM));
    // check that only the second chain has the vm type for the FVM contract
    byte[] codeHashFVM = ((AionRepositoryImpl) testChain.getRepository().getSnapshotTo(slowBlock.getStateRoot())).getAccountState(contract).getCodeHash();
    assertThat(sourceChain.getRepository().getVMUsed(contract, codeHashFVM)).isEqualTo(InternalVmType.UNKNOWN);
    assertThat(testChain.getRepository().getVMUsed(contract, codeHashFVM)).isEqualTo(InternalVmType.FVM);
    // check the stored information details
    ContractInformation infoSingleImport = sourceChain.getRepository().getIndexedContractInformation(contract);
    System.out.println("without side chain:" + infoSingleImport);
    assertThat(infoSingleImport.getVmUsed(codeHashAVM)).isEqualTo(InternalVmType.AVM);
    assertThat(infoSingleImport.getInceptionBlocks(codeHashAVM)).isEqualTo(Set.of(fastBlock.getHashWrapper()));
    assertThat(infoSingleImport.getVmUsed(codeHashFVM)).isEqualTo(InternalVmType.UNKNOWN);
    assertThat(infoSingleImport.getInceptionBlocks(codeHashFVM)).isEmpty();
    ContractInformation infoMultiImport = testChain.getRepository().getIndexedContractInformation(contract);
    System.out.println("with side chain:" + infoMultiImport);
    assertThat(infoMultiImport.getVmUsed(codeHashAVM)).isEqualTo(InternalVmType.AVM);
    assertThat(infoMultiImport.getInceptionBlocks(codeHashAVM)).isEqualTo(Set.of(fastBlock.getHashWrapper()));
    assertThat(infoMultiImport.getVmUsed(codeHashFVM)).isEqualTo(InternalVmType.FVM);
    assertThat(infoMultiImport.getInceptionBlocks(codeHashFVM)).isEqualTo(Set.of(slowBlock.getHashWrapper()));
    // build two blocks where the second block has a higher total difficulty
    callTxOnFVM = callSetValue(sender, contract, 9, BigInteger.ONE);
    lowBlock = testChain.createNewMiningBlockInternal(slowBlock, Arrays.asList(callTxOnFVM), true, time / 10_000L + 101).block;
    int expectedCount = 3;
    List<AionTransaction> callTxOnAVM = callStatefulnessAVM(resourceFactory, sender, expectedCount, BigInteger.ONE, contract);
    highBlock = sourceChain.createNewMiningBlockInternal(fastBlock, callTxOnAVM, true, time / 10_000L).block;
    assertThat(highBlock.getDifficultyBI()).isGreaterThan(lowBlock.getDifficultyBI());
    // build first chain with highBlock applied directly
    connectResult = sourceChain.tryToConnectAndFetchSummary(highBlock);
    // get last tx
    receipt = connectResult.getRight().getReceipts().get(expectedCount);
    assertThat(receipt.isSuccessful()).isTrue();
    result = connectResult.getLeft();
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    // collect the consensus information from the block & receipt
    AionBlockSummary blockSummary = connectResult.getRight();
    byte[] stateRoot = blockSummary.getBlock().getStateRoot();
    byte[] blockReceiptsRoot = blockSummary.getBlock().getReceiptsRoot();
    byte[] receiptTrieEncoded = receipt.getReceiptTrieEncoded();
    int returnedCount = resourceFactory.newDecoder(blockSummary.getReceipts().get(expectedCount).getTransactionOutput()).decodeOneInteger();
    assertThat(returnedCount).isEqualTo(expectedCount);
    // ****** test fork behavior ******
    // first import lowBlock
    assertThat(testChain.tryToConnect(lowBlock)).isEqualTo(ImportResult.IMPORTED_BEST);
    // next import highBlock causing the fork
    connectResult = testChain.tryToConnectAndFetchSummary(highBlock);
    receipt = connectResult.getRight().getReceipts().get(expectedCount);
    assertThat(receipt.isSuccessful()).isTrue();
    System.out.println(receipt);
    result = connectResult.getLeft();
    assertThat(result).isEqualTo(ImportResult.IMPORTED_BEST);
    // collect the consensus information from the block & receipt
    blockSummary = connectResult.getRight();
    assertThat(testChain.getBestBlock()).isEqualTo(sourceChain.getBestBlock());
    assertThat(blockSummary.getBlock().getStateRoot()).isEqualTo(stateRoot);
    assertThat(blockSummary.getBlock().getReceiptsRoot()).isEqualTo(blockReceiptsRoot);
    assertThat(receipt.getReceiptTrieEncoded()).isEqualTo(receiptTrieEncoded);
    returnedCount = resourceFactory.newDecoder(blockSummary.getReceipts().get(expectedCount).getTransactionOutput()).decodeOneInteger();
    assertThat(returnedCount).isEqualTo(expectedCount);
}
Also used : ImportResult(org.aion.zero.impl.core.ImportResult) AionAddress(org.aion.types.AionAddress) AionTransaction(org.aion.base.AionTransaction) ECKey(org.aion.crypto.ECKey) MiningBlock(org.aion.zero.impl.types.MiningBlock) TestResourceProvider(org.aion.zero.impl.vm.TestResourceProvider) ContractInformation(org.aion.zero.impl.db.ContractInformation) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) AionTxReceipt(org.aion.base.AionTxReceipt) Test(org.junit.Test)

Example 7 with IAvmResourceFactory

use of org.aion.avm.stub.IAvmResourceFactory in project aion by aionnetwork.

the class StakingContractHelper method getEffectiveStake.

/**
 * this method called by the kernel for querying the correct stakes in the staking contract by giving desired coinbase address and the block signing address.
 * @param signingAddress the block signing address
 * @param coinbase the staker's coinbase for receiving the block rewards
 * @return the stake amount of the staker
 */
public BigInteger getEffectiveStake(AionAddress signingAddress, AionAddress coinbase, Block block) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
    if (signingAddress == null || coinbase == null) {
        throw new NullPointerException();
    }
    if (!AvmProvider.tryAcquireLock(10, TimeUnit.MINUTES)) {
        throw new IllegalStateException("Failed to acquire the avm lock!");
    }
    if (!AvmProvider.isVersionEnabled(LATEST_AVM_VERSION)) {
        AvmProvider.enableAvmVersion(LATEST_AVM_VERSION, AvmConfigurations.getProjectRootDirectory());
    }
    IAvmResourceFactory resourceFactory = AvmProvider.getResourceFactory(LATEST_AVM_VERSION);
    if (this.effectiveStake == null) {
        this.effectiveStake = resourceFactory.newStreamingEncoder().encodeOneString("getEffectiveStake").getEncoding();
    }
    byte[] abi = ByteUtil.merge(this.effectiveStake, resourceFactory.newStreamingEncoder().encodeOneAddress(signingAddress).getEncoding(), resourceFactory.newStreamingEncoder().encodeOneAddress(coinbase).getEncoding());
    AvmProvider.releaseLock();
    AionTransaction callTx = AionTransaction.create(keyForCallandEstimate, BigInteger.ZERO.toByteArray(), stakingContractAddr, BigInteger.ZERO.toByteArray(), abi, 2_000_000L, 10_000_000_000L, TransactionTypes.DEFAULT, null);
    AionTxReceipt receipt = null;
    try {
        receipt = callConstant(callTx, block);
    } catch (VmFatalException e) {
        LOG_VM.error("VM fatal exception! Shutting down the kernel!", e);
        System.exit(SystemExitCodes.FATAL_VM_ERROR);
    }
    if (receipt == null || Arrays.equals(receipt.getTransactionOutput(), new byte[0])) {
        LOG_CONS.debug("getEffectiveStake failed due to the " + (receipt == null ? "null receipt" : "empty transactionOutput"));
        return BigInteger.ZERO;
    }
    if (!AvmProvider.tryAcquireLock(10, TimeUnit.MINUTES)) {
        throw new IllegalStateException("Failed to acquire the avm lock!");
    }
    BigInteger output = resourceFactory.newDecoder(receipt.getTransactionOutput()).decodeOneBigInteger();
    AvmProvider.releaseLock();
    return output;
}
Also used : IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory) VmFatalException(org.aion.zero.impl.vm.common.VmFatalException) BigInteger(java.math.BigInteger) AionTransaction(org.aion.base.AionTransaction) AionTxReceipt(org.aion.base.AionTxReceipt)

Example 8 with IAvmResourceFactory

use of org.aion.avm.stub.IAvmResourceFactory in project aion by aionnetwork.

the class PendingStateTest method testAddPendingTransaction_AVMContractDeploy_Success.

@Test
public void testAddPendingTransaction_AVMContractDeploy_Success() throws Exception {
    TestResourceProvider resourceProvider = TestResourceProvider.initializeAndCreateNewProvider(AvmPathManager.getPathOfProjectRootDirectory());
    IAvmResourceFactory resourceFactory = resourceProvider.factoryForVersion1;
    // Successful transaction
    byte[] jar = resourceFactory.newContractFactory().getDeploymentBytes(AvmContract.HELLO_WORLD);
    AionTransaction transaction = AionTransaction.create(deployerKey, BigInteger.ZERO.toByteArray(), null, BigInteger.ZERO.toByteArray(), jar, 5_000_000, energyPrice, TransactionTypes.AVM_CREATE_CODE, null);
    assertEquals(pendingState.addTransactionFromApiServer(transaction), TxResponse.SUCCESS);
}
Also used : IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory) AionTransaction(org.aion.base.AionTransaction) TestResourceProvider(org.aion.zero.impl.vm.TestResourceProvider) Test(org.junit.Test)

Example 9 with IAvmResourceFactory

use of org.aion.avm.stub.IAvmResourceFactory in project aion by aionnetwork.

the class InvalidBlockTest method makeTransactions.

private List<AionTransaction> makeTransactions(AvmVersion version, int num, BigInteger initialNonce) {
    List<AionTransaction> transactions = new ArrayList<>();
    IAvmResourceFactory factory = (version == AvmVersion.VERSION_1) ? resourceProvider.factoryForVersion1 : resourceProvider.factoryForVersion2;
    byte[] jar = factory.newContractFactory().getDeploymentBytes(AvmContract.GENERIC_CONTRACT);
    BigInteger nonce = initialNonce;
    for (int i = 0; i < num; i++) {
        AionTransaction transaction = AionTransaction.create(deployerKey, nonce.toByteArray(), null, BigInteger.ZERO.toByteArray(), jar, 5_000_000L, 10_000_000_000L, TransactionTypes.AVM_CREATE_CODE, null);
        transactions.add(transaction);
        nonce = nonce.add(BigInteger.ONE);
    }
    return transactions;
}
Also used : IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory) ArrayList(java.util.ArrayList) BigInteger(java.math.BigInteger) AionTransaction(org.aion.base.AionTransaction)

Example 10 with IAvmResourceFactory

use of org.aion.avm.stub.IAvmResourceFactory in project aion by aionnetwork.

the class MultiVersionAvmTest method makeHelloWorldCallTransaction.

private AionTransaction makeHelloWorldCallTransaction(AvmVersion version, BigInteger nonce, AionAddress contract) {
    IAvmResourceFactory factory = (version == AvmVersion.VERSION_1) ? resourceProvider.factoryForVersion1 : resourceProvider.factoryForVersion2;
    byte[] callData = factory.newStreamingEncoder().encodeOneString("sayHello").getEncoding();
    return AionTransaction.create(this.deployerKey, nonce.toByteArray(), contract, BigInteger.ZERO.toByteArray(), callData, 2_000_000, energyPrice, TransactionTypes.DEFAULT, null);
}
Also used : IAvmResourceFactory(org.aion.avm.stub.IAvmResourceFactory)

Aggregations

IAvmResourceFactory (org.aion.avm.stub.IAvmResourceFactory)16 AionTransaction (org.aion.base.AionTransaction)9 URLClassLoader (java.net.URLClassLoader)6 AionTxReceipt (org.aion.base.AionTxReceipt)5 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)5 MiningBlock (org.aion.zero.impl.types.MiningBlock)5 Test (org.junit.Test)5 AionAddress (org.aion.types.AionAddress)4 ImportResult (org.aion.zero.impl.core.ImportResult)4 BigInteger (java.math.BigInteger)3 TestResourceProvider (org.aion.zero.impl.vm.TestResourceProvider)3 AvmVersion (org.aion.avm.stub.AvmVersion)2 ArrayList (java.util.ArrayList)1 RepositoryCache (org.aion.base.db.RepositoryCache)1 ECKey (org.aion.crypto.ECKey)1 AionRepositoryCache (org.aion.zero.impl.db.AionRepositoryCache)1 ContractInformation (org.aion.zero.impl.db.ContractInformation)1 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)1 VmFatalException (org.aion.zero.impl.vm.common.VmFatalException)1