From 4bb14da6b2b462753e2c961e949a91e0fad367cb Mon Sep 17 00:00:00 2001 From: huzhenyuan Date: Sat, 25 Aug 2018 18:18:13 +0800 Subject: [PATCH] fix bug for precompile --- .../org/tron/common/runtime/vm/DataWord.java | 1 + .../runtime/vm/PrecompiledContracts.java | 98 ++++++++++--------- .../runtime/vm/PrecompiledContractsTest.java | 6 +- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/tron/common/runtime/vm/DataWord.java b/src/main/java/org/tron/common/runtime/vm/DataWord.java index b3e571494eb..76c1e9c76b5 100644 --- a/src/main/java/org/tron/common/runtime/vm/DataWord.java +++ b/src/main/java/org/tron/common/runtime/vm/DataWord.java @@ -39,6 +39,7 @@ public class DataWord implements Comparable { /* Maximum value of the DataWord */ + public static final int DATAWORD_UNIT_SIZE = 32; public static final BigInteger _2_256 = BigInteger.valueOf(2).pow(256); public static final BigInteger MAX_VALUE = _2_256.subtract(BigInteger.ONE); public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack diff --git a/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java b/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java index 18464d20e4d..1c50da04eed 100644 --- a/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java +++ b/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java @@ -35,9 +35,11 @@ import java.util.HashMap; import java.util.List; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.spongycastle.util.encoders.Hex; import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.Hash; import org.tron.common.crypto.zksnark.BN128; import org.tron.common.crypto.zksnark.BN128Fp; import org.tron.common.crypto.zksnark.BN128G1; @@ -50,11 +52,14 @@ import org.tron.common.storage.Deposit; import org.tron.common.utils.BIUtil; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.actuator.Actuator; import org.tron.core.actuator.ActuatorFactory; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract; @@ -83,8 +88,8 @@ public class PrecompiledContracts { private static final BN128Multiplication altBN128Mul = new BN128Multiplication(); private static final BN128Pairing altBN128Pairing = new BN128Pairing(); private static final VoteWitnessNative voteContract = new VoteWitnessNative(); - private static final FreezeBalanceNative freezeBalance = new FreezeBalanceNative(); - private static final UnfreezeBalanceNative unFreezeBalance = new UnfreezeBalanceNative(); +// private static final FreezeBalanceNative freezeBalance = new FreezeBalanceNative(); +// private static final UnfreezeBalanceNative unFreezeBalance = new UnfreezeBalanceNative(); private static final WithdrawBalanceNative withdrawBalance = new WithdrawBalanceNative(); private static final ProposalApproveNative proposalApprove = new ProposalApproveNative(); private static final ProposalCreateNative proposalCreate = new ProposalCreateNative(); @@ -94,6 +99,9 @@ public class PrecompiledContracts { private static final TransferAssetNative transferAsset = new TransferAssetNative(); private static final GetTransferAssetNative getTransferAssetAmount = new GetTransferAssetNative(); + private static final ECKey addressCheckECKey = new ECKey(); + private static final String addressCheckECKeyAddress = Wallet.encode58Check(addressCheckECKey.getAddress()); + private static final DataWord ecRecoverAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000000001"); @@ -113,10 +121,10 @@ public class PrecompiledContracts { "0000000000000000000000000000000000000000000000000000000000000008"); private static final DataWord voteContractAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010001"); - private static final DataWord freezeBalanceAddr = new DataWord( - "0000000000000000000000000000000000000000000000000000000000010002"); - private static final DataWord unFreezeBalanceAddr = new DataWord( - "0000000000000000000000000000000000000000000000000000000000010003"); +// private static final DataWord freezeBalanceAddr = new DataWord( +// "0000000000000000000000000000000000000000000000000000000000010002"); +// private static final DataWord unFreezeBalanceAddr = new DataWord( +// "0000000000000000000000000000000000000000000000000000000000010003"); private static final DataWord withdrawBalanceAddr = new DataWord( "0000000000000000000000000000000000000000000000000000000000010004"); private static final DataWord proposalApproveAddr = new DataWord( @@ -154,12 +162,12 @@ public static PrecompiledContract getContractForAddress(DataWord address) { if (address.equals(voteContractAddr)) { return voteContract; } - if (address.equals(freezeBalanceAddr)) { - return freezeBalance; - } - if (address.equals(unFreezeBalanceAddr)) { - return unFreezeBalance; - } +// if (address.equals(freezeBalanceAddr)) { +// return freezeBalance; +// } +// if (address.equals(unFreezeBalanceAddr)) { +// return unFreezeBalance; +// } if (address.equals(withdrawBalanceAddr)) { return withdrawBalance; } @@ -185,14 +193,11 @@ public static PrecompiledContract getContractForAddress(DataWord address) { return getTransferAssetAmount; } - - /* - // Byzantium precompiles - if (address.equals(modExpAddr) && config.eip198()) return modExp; - if (address.equals(altBN128AddAddr) && config.eip213()) return altBN128Add; - if (address.equals(altBN128MulAddr) && config.eip213()) return altBN128Mul; - if (address.equals(altBN128PairingAddr) && config.eip212()) return altBN128Pairing; - */ + // Byzantium precompiles + if (address.equals(modExpAddr)) return modExp; + if (address.equals(altBN128AddAddr)) return altBN128Add; + if (address.equals(altBN128MulAddr)) return altBN128Mul; + if (address.equals(altBN128PairingAddr)) return altBN128Pairing; return null; } @@ -310,14 +315,13 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - /* - byte[] result = null; - if (data == null) result = Hash.ripemd160(EMPTY_BYTE_ARRAY); - else result = Hash.ripemd160(data); - - return Pair.of(true, new DataWord(result).getData()); - */ - return null; + byte[] target = new byte[160]; + if (data == null) { + data = EMPTY_BYTE_ARRAY; + } + byte[] orig = Sha256Hash.hash(data); + System.arraycopy(orig, 0, target, 0, 160); + return Pair.of(true, Sha256Hash.hash(target)); } } @@ -685,9 +689,10 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length != 2 * DataWord.DATAWORD_UNIT_SIZE) { + return Pair.of(false, new DataWord(0).getData()); } + byte[] witnessAddress = new byte[32]; System.arraycopy(data, 0, witnessAddress, 0, 32); byte[] value = new byte[8]; @@ -920,8 +925,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length != 2 * DataWord.DATAWORD_UNIT_SIZE) { + return Pair.of(false, new DataWord(0).getData()); } byte[] proposalId = new byte[32]; @@ -955,7 +960,7 @@ public Pair execute(byte[] data) { } catch (ContractValidateException e) { logger.debug("ContractValidateException when calling proposalApproveNative in vm"); logger.debug("ContractValidateException: {}", e.getMessage()); - return null; + return Pair.of(false, new DataWord(0).getData()); } return Pair.of(true, new DataWord(1).getData()); } @@ -980,8 +985,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length == 0 || (data.length % (2 * DataWord.DATAWORD_UNIT_SIZE) != 0 )) { + return Pair.of(false, new DataWord(0).getData()); } HashMap parametersMap = new HashMap<>(); @@ -1046,8 +1051,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE) { + return Pair.of(false, new DataWord(0).getData()); } Contract.ProposalDeleteContract.Builder builder = Contract.ProposalDeleteContract .newBuilder(); @@ -1098,8 +1103,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE) { + return Pair.of(false, new DataWord(0).getData()); } DataWord address = new DataWord(data); return Pair.of(true, new DataWord(address.getLast20Bytes()).getData()); @@ -1125,8 +1130,9 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + int checklength = addressCheckECKeyAddress.length(); + if (data == null || data.length != checklength) { + return Pair.of(false, new DataWord(0).getData()); } String addressBase58 = new String(data); @@ -1155,13 +1161,13 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || (data.length <= DataWord.DATAWORD_UNIT_SIZE * 2 || data.length > DataWord.DATAWORD_UNIT_SIZE * 3)) { + return Pair.of(false, new DataWord(0).getData()); } byte[] toAddress = new byte[32]; System.arraycopy(data, 0, toAddress, 0, 32); - byte[] amount = new byte[32]; + byte[] amount = new byte[8]; System.arraycopy(data, 32 + 16 + 8, amount, 0, 8); // we already have a restrict for token name length, no more than 32 bytes. don't need to check again byte[] name = new byte[32]; @@ -1224,8 +1230,8 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null) { - data = EMPTY_BYTE_ARRAY; + if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE * 2) { + return Pair.of(false, new DataWord(0).getData()); } byte[] targetAddress = new byte[32]; diff --git a/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java b/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java index 8431097be09..e327f255979 100644 --- a/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java +++ b/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java @@ -285,9 +285,9 @@ public void proposalTest() { @Test public void convertFromTronBytesAddressNativeTest() { - PrecompiledContract contract = createPrecompiledContract(convertFromTronBytesAddressAddr, WITNESS_ADDRESS); - byte[] solidityAddress = contract.execute(Hex.decode(WITNESS_ADDRESS)).getRight(); - Assert.assertArrayEquals(solidityAddress,new DataWord(Hex.decode(WITNESS_ADDRESS_BASE)).getData()); + PrecompiledContract contract = createPrecompiledContract(convertFromTronBytesAddressAddr, WITNESS_ADDRESS); + byte[] solidityAddress = contract.execute(new DataWord(WITNESS_ADDRESS).getData()).getRight(); + Assert.assertArrayEquals(solidityAddress,new DataWord(Hex.decode(WITNESS_ADDRESS_BASE)).getData()); } @Test