diff --git a/lib/fastvm-93a258f.jar b/lib/fastvm-39cde69.jar similarity index 84% rename from lib/fastvm-93a258f.jar rename to lib/fastvm-39cde69.jar index 4e32552ea1..e1b9a15036 100644 Binary files a/lib/fastvm-93a258f.jar and b/lib/fastvm-39cde69.jar differ diff --git a/modAionImpl/build.gradle b/modAionImpl/build.gradle index 14bbb48bd7..62bfbf75ae 100644 --- a/modAionImpl/build.gradle +++ b/modAionImpl/build.gradle @@ -24,7 +24,7 @@ dependencies { compile project(':modEvtMgrImpl') compile project(':modPrecompiled') compile project(':modTxPool') - compile files("${rootProject.projectDir}/lib/fastvm-93a258f.jar") + compile files("${rootProject.projectDir}/lib/fastvm-39cde69.jar") compile 'org.json:json:20180813' compile 'info.picocli:picocli:4.0.0' compile files("${rootProject.projectDir}/lib/aion-types-22a3be9.jar") diff --git a/modAionImpl/src/org/aion/zero/impl/valid/TXValidator.java b/modAionImpl/src/org/aion/zero/impl/valid/TXValidator.java index cfc62425cb..75ee9a269c 100644 --- a/modAionImpl/src/org/aion/zero/impl/valid/TXValidator.java +++ b/modAionImpl/src/org/aion/zero/impl/valid/TXValidator.java @@ -3,6 +3,7 @@ import static org.aion.zero.impl.vm.common.TxNrgRule.isValidNrgContractCreate; import static org.aion.zero.impl.vm.common.TxNrgRule.isValidNrgContractCreateAfterUnity; import static org.aion.zero.impl.vm.common.TxNrgRule.isValidNrgTx; +import static org.aion.zero.impl.vm.common.TxNrgRule.isValidNrgTxAfterUnity; import java.util.Collections; import java.util.Map; @@ -64,12 +65,12 @@ private static boolean isValid0(AionTransaction tx) { private static boolean isValidAfterUnity(AionTransaction tx) { long nrg = tx.getEnergyLimit(); if (tx.isContractCreationTransaction()) { - if (!isValidNrgContractCreateAfterUnity(nrg)) { + if (!isValidNrgContractCreateAfterUnity(nrg, tx.getData())) { LOG.error("invalid contract create nrg!"); return false; } } else { - if (!isValidNrgTx(nrg)) { + if (!isValidNrgTxAfterUnity(nrg, tx.getData())) { LOG.error("invalid tx nrg!"); return false; } diff --git a/modAionImpl/src/org/aion/zero/impl/vm/avm/AvmConfigurations.java b/modAionImpl/src/org/aion/zero/impl/vm/avm/AvmConfigurations.java index 07d3b236c7..c4c1d82dae 100644 --- a/modAionImpl/src/org/aion/zero/impl/vm/avm/AvmConfigurations.java +++ b/modAionImpl/src/org/aion/zero/impl/vm/avm/AvmConfigurations.java @@ -13,11 +13,12 @@ public final class AvmConfigurations { private static AvmVersionSchedule multiVersionSchedule = null; private static String projectRootDir = null; private static IEnergyRules energyRules = (t, l) -> (t == IEnergyRules.TransactionType.CREATE) ? TxNrgRule.isValidNrgContractCreate(l) : TxNrgRule.isValidNrgTx(l); + // The AVM does check the energy requirement regarding the transaction data context. Therefor We only check the basic rule in here. private static IEnergyRules energyRulesAfterUnityFork = (t, l) -> (t == IEnergyRules.TransactionType.CREATE) - ? TxNrgRule.isValidNrgContractCreateAfterUnity(l) - : TxNrgRule.isValidNrgTx(l); + ? TxNrgRule.isValidNrgContractCreateAfterUnity(l, null) + : TxNrgRule.isValidNrgTxAfterUnity(l, null); private AvmConfigurations() {} diff --git a/modAionImpl/src/org/aion/zero/impl/vm/common/TransactionUtil.java b/modAionImpl/src/org/aion/zero/impl/vm/common/TransactionUtil.java new file mode 100644 index 0000000000..10be338c8d --- /dev/null +++ b/modAionImpl/src/org/aion/zero/impl/vm/common/TransactionUtil.java @@ -0,0 +1,35 @@ +package org.aion.zero.impl.vm.common; + +import org.aion.fastvm.FvmConstants; + +/** Duplicate from the fastVM module. */ +public final class TransactionUtil { + + public static long computeTransactionCost(boolean isCreate, byte[] data) { + long nonZeroes = nonZeroBytesInData(data); + long zeroes = zeroBytesInData(data); + + return (isCreate ? FvmConstants.CREATE_TRANSACTION_FEE : 0) + + FvmConstants.TRANSACTION_BASE_FEE + + zeroes * FvmConstants.ZERO_BYTE_FEE + + nonZeroes * FvmConstants.NONZERO_BYTE_FEE; + } + + private static long nonZeroBytesInData(byte[] data) { + int total = (data == null) ? 0 : data.length; + + return total - zeroBytesInData(data); + } + + private static long zeroBytesInData(byte[] data) { + if (data == null) { + return 0; + } + + int c = 0; + for (byte b : data) { + c += (b == 0) ? 1 : 0; + } + return c; + } +} diff --git a/modAionImpl/src/org/aion/zero/impl/vm/common/TxNrgRule.java b/modAionImpl/src/org/aion/zero/impl/vm/common/TxNrgRule.java index d23b8b94e3..4e1a1a3e55 100644 --- a/modAionImpl/src/org/aion/zero/impl/vm/common/TxNrgRule.java +++ b/modAionImpl/src/org/aion/zero/impl/vm/common/TxNrgRule.java @@ -16,8 +16,8 @@ public static boolean isValidNrgContractCreate(long energyLimit) { return (energyLimit >= CONTRACT_CREATE_TX_NRG_MIN) && (energyLimit <= CONTRACT_CREATE_TX_NRG_MAX); } - public static boolean isValidNrgContractCreateAfterUnity(long energyLimit) { - return (energyLimit >= (CONTRACT_CREATE_TX_NRG_MIN + TX_NRG_MIN)) + public static boolean isValidNrgContractCreateAfterUnity(long energyLimit, byte[] data) { + return (energyLimit >= TransactionUtil.computeTransactionCost(true, data)) && (energyLimit <= CONTRACT_CREATE_TX_NRG_MAX); } @@ -25,6 +25,11 @@ public static boolean isValidNrgTx(long energyLimit) { return (energyLimit >= TX_NRG_MIN) && (energyLimit <= TX_NRG_MAX); } + public static boolean isValidNrgTxAfterUnity(long energyLimit, byte[] data) { + return (energyLimit >= TransactionUtil.computeTransactionCost(false, data)) + && (energyLimit <= TX_NRG_MAX); + } + public static boolean isValidTxNrgPrice(long energyPrice) { return (energyPrice >= NRGPRICE_MIN) && (energyPrice <= NRGPRICE_MAX); } diff --git a/modAionImpl/src/org/aion/zero/impl/vm/fvm/ExternalStateForFvm.java b/modAionImpl/src/org/aion/zero/impl/vm/fvm/ExternalStateForFvm.java index 89eea53afe..9161b06475 100644 --- a/modAionImpl/src/org/aion/zero/impl/vm/fvm/ExternalStateForFvm.java +++ b/modAionImpl/src/org/aion/zero/impl/vm/fvm/ExternalStateForFvm.java @@ -312,9 +312,9 @@ public void incrementNonce(AionAddress address) { * @return whether the energy limit is valid. */ @Override - public boolean isValidEnergyLimitForCreate(long energyLimit) { + public boolean isValidEnergyLimitForCreate(long energyLimit, byte[] data) { return (this.isLocalCall) || ((this.isUnityForkEnabled) - ? TxNrgRule.isValidNrgContractCreateAfterUnity(energyLimit) + ? TxNrgRule.isValidNrgContractCreateAfterUnity(energyLimit, data) : TxNrgRule.isValidNrgContractCreate(energyLimit)); } @@ -329,8 +329,16 @@ public boolean isValidEnergyLimitForCreate(long energyLimit) { * @return whether the energy limit is valid. */ @Override - public boolean isValidEnergyLimitForNonCreate(long energyLimit) { - return (this.isLocalCall) ? true : TxNrgRule.isValidNrgTx(energyLimit); + public boolean isValidEnergyLimitForNonCreate(long energyLimit, byte[] data) { + if (this.isLocalCall) { + return true; + } else { + if (this.isUnityForkEnabled) { + return TxNrgRule.isValidNrgTxAfterUnity(energyLimit, data); + } else { + return TxNrgRule.isValidNrgTx(energyLimit); + } + } } /** diff --git a/modBase/build.gradle b/modBase/build.gradle index 777b363b7e..ecd48037dd 100644 --- a/modBase/build.gradle +++ b/modBase/build.gradle @@ -4,7 +4,7 @@ test.dependsOn copyNativeLibsForModuleTests clean.dependsOn deleteNativeLibs dependencies { - compile files("${rootProject.projectDir}/lib/fastvm-93a258f.jar") + compile files("${rootProject.projectDir}/lib/fastvm-39cde69.jar") compile files("${rootProject.projectDir}/lib/aion-types-22a3be9.jar") compile project(':modUtil') compile project(':modLogger')