aionnetwork / AVM

Enabling Java code to run in a blockchain environment
https://theoan.com/
MIT License
49 stars 25 forks source link

Handle case of call to self-destructed DApp #343

Closed jeff-aion closed 5 years ago

jeff-aion commented 5 years ago

Sending a call to a self-destructed DApp instance results in this exception:

java.lang.NullPointerException

    at org.aion.avm.core.persistence.ContractEnvironmentState.loadFromGraph(ContractEnvironmentState.java:12)

    at org.aion.avm.core.DAppExecutor.call(DAppExecutor.java:33)

    at org.aion.avm.core.AvmImpl.commonInvoke(AvmImpl.java:378)

    at org.aion.avm.core.AvmImpl.runExternalInvoke(AvmImpl.java:304)

    at org.aion.avm.core.AvmImpl.backgroundProcessTransaction(AvmImpl.java:213)

    at org.aion.avm.core.AvmImpl.access$200(AvmImpl.java:37)

    at org.aion.avm.core.AvmImpl$AvmExecutorThread.run(AvmImpl.java:87)

At first glance, I suspect that the problem is that we are not failing earlier-on, possibly due to the DApp code still being present in the SoftCache. This hypothesis hasn't been verified, however.

zhikezhang commented 5 years ago

The last BlockchainRuntime.call in this following test case could be probably not correct. The response should be probably null instead of JUST_RETURN. It is in in SelfDestructResource.java.

public static int callToDeleteSuccess(Address beneficiary, Address target) {
    // Call the target to get them to delete themselves.
    BigInteger value = BigInteger.ZERO;
    byte[] data = ABIEncoder.encodeMethodArguments("deleteAndReturn", beneficiary);
    long energyLimit = BlockchainRuntime.getRemainingEnergy() / 2;
    byte[] response = BlockchainRuntime.call(target, value, data, energyLimit).getReturnData();
    assert (DELETE_AND_RETURN == (Integer)ABIDecoder.decodeOneObject(response));

    // Call back to ourselves, to verify that we are ok.
    data = ABIEncoder.encodeMethodArguments("justReturn");
    energyLimit = BlockchainRuntime.getRemainingEnergy() / 2;
    response = BlockchainRuntime.call(BlockchainRuntime.getAddress(), value, data, energyLimit).getReturnData();
    assert (JUST_RETURN == (Integer)ABIDecoder.decodeOneObject(response));

    // Try to call them, verifying that they are not accessible.
    data = ABIEncoder.encodeMethodArguments("justReturn");
    energyLimit = BlockchainRuntime.getRemainingEnergy() / 2;
    response = BlockchainRuntime.call(target, value, data, energyLimit).getReturnData();
    assert (JUST_RETURN == (Integer)ABIDecoder.decodeOneObject(response));
    return CALL_TO_DELETE_SUCCESS;
}