diff --git a/framework/src/main/java/org/tron/core/capsule/utils/DecodeResult.java b/framework/src/main/java/org/tron/core/capsule/utils/DecodeResult.java deleted file mode 100644 index 5fc3c862b67..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/DecodeResult.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tron.core.capsule.utils; - -import java.io.Serializable; -import org.bouncycastle.util.encoders.Hex; - -@SuppressWarnings("serial") -public class DecodeResult implements Serializable { - - private int pos; - private Object decoded; - - public DecodeResult(int pos, Object decoded) { - this.pos = pos; - this.decoded = decoded; - } - - public int getPos() { - return pos; - } - - public Object getDecoded() { - return decoded; - } - - public String toString() { - return asString(this.decoded); - } - - private String asString(Object decoded) { - if (decoded instanceof String) { - return (String) decoded; - } else if (decoded instanceof byte[]) { - return Hex.toHexString((byte[]) decoded); - } else if (decoded instanceof Object[]) { - String result = ""; - for (Object item : (Object[]) decoded) { - result += asString(item); - } - return result; - } - throw new RuntimeException("Not a valid type. Should not occur"); - } -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java b/framework/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java deleted file mode 100644 index 90b9abf8c59..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.tron.core.capsule.utils; - -import com.google.common.primitives.UnsignedBytes; - - -/** - * Utility code to do optimized byte-array comparison. This is borrowed and slightly modified from - * Guava's {@link UnsignedBytes} class to be able to compare arrays that start at non-zero offsets. - */ -@SuppressWarnings("restriction") -public abstract class FastByteComparisons { - - public static boolean equalByte(byte[] b1, byte[] b2) { - return b1.length == b2.length && compareTo(b1, 0, b1.length, b2, 0, b2.length) == 0; - } - - /** - * Lexicographically compare two byte arrays. - * - * @param b1 buffer1 - * @param s1 offset1 - * @param l1 length1 - * @param b2 buffer2 - * @param s2 offset2 - * @param l2 length2 - * @return int - */ - public static int compareTo(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { - return LexicographicalComparerHolder.BEST_COMPARER.compareTo( - b1, s1, l1, b2, s2, l2); - } - - private static Comparer lexicographicalComparerJavaImpl() { - return LexicographicalComparerHolder.PureJavaComparer.INSTANCE; - } - - private interface Comparer { - - int compareTo(T buffer1, int offset1, int length1, - T buffer2, int offset2, int length2); - } - - /** - * Uses reflection to gracefully fall back to the Java implementation if {@code Unsafe} isn't - * available. - */ - private static class LexicographicalComparerHolder { - - private static final String UNSAFE_COMPARER_NAME = - LexicographicalComparerHolder.class.getName() + "$UnsafeComparer"; - - private static final Comparer BEST_COMPARER = getBestComparer(); - - /** - * Returns the Unsafe-using Comparer, or falls back to the pure-Java implementation if unable to - * do so. - */ - static Comparer getBestComparer() { - try { - Class theClass = Class.forName(UNSAFE_COMPARER_NAME); - - // yes, UnsafeComparer does implement Comparer - @SuppressWarnings("unchecked") - Comparer comparer = - (Comparer) theClass.getEnumConstants()[0]; - return comparer; - } catch (Throwable t) { // ensure we really catch *everything* - return lexicographicalComparerJavaImpl(); - } - } - - private enum PureJavaComparer implements Comparer { - INSTANCE; - - @Override - public int compareTo(byte[] buffer1, int offset1, int length1, - byte[] buffer2, int offset2, int length2) { - // Short circuit equal case - if (buffer1 == buffer2 - && offset1 == offset2 - && length1 == length2) { - return 0; - } - int end1 = offset1 + length1; - int end2 = offset2 + length2; - for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) { - int a = (buffer1[i] & 0xff); - int b = (buffer2[j] & 0xff); - if (a != b) { - return a - b; - } - } - return length1 - length2; - } - } - - - } -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java index 24b5c502a1c..cd44ccef8c4 100644 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLP.java +++ b/framework/src/main/java/org/tron/core/capsule/utils/RLP.java @@ -1,56 +1,27 @@ package org.tron.core.capsule.utils; import static java.util.Arrays.copyOfRange; -import static org.bouncycastle.util.Arrays.concatenate; -import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; -import static org.tron.common.math.Maths.pow; import static org.tron.common.utils.ByteUtil.byteArrayToInt; -import static org.tron.common.utils.ByteUtil.intToBytesNoLeadZeroes; -import static org.tron.common.utils.ByteUtil.isNullOrZeroArray; -import static org.tron.common.utils.ByteUtil.isSingleZero; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.bouncycastle.util.encoders.Hex; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.tron.common.crypto.Hash; -import org.tron.common.utils.ByteUtil; -import org.tron.common.utils.Value; -import org.tron.core.db.ByteArrayWrapper; /** - * Recursive Length Prefix (RLP) encoding.

The purpose of RLP is to encode arbitrarily nested - * arrays of binary data, and RLP is the main encoding method used to serialize objects in Ethereum. - * The only purpose of RLP is to encode structure; encoding specific atomic data types (eg. strings, - * integers, floats) is left up to higher-order protocols; in Ethereum the standard is that integers - * are represented in big endian binary form. If one wishes to use RLP to encode a dictionary, the - * two suggested canonical forms are to either use [[k1,v1],[k2,v2]...] with keys in lexicographic - * order or to use the higher-level Patricia Tree encoding as Ethereum does.

The RLP encoding - * function takes in an item. An item is defined as follows:

- A string (ie. byte array) is an - * item - A list of items is an item

For example, an empty string is an item, as is the string - * containing the word "cat", a list containing any number of strings, as well as more complex data - * structures like ["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]. Note that in the context - * of the rest of this article, "string" will be used as a synonym for "a certain number of bytes of - * binary data"; no special encodings are used and no knowledge about the content of the strings is - * implied.

See: https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP + * Recursive Length Prefix (RLP) encoding, as used by the account-state trie. + * + *

RLP encodes arbitrarily nested arrays of binary data. It describes structure only: an item is + * either a byte array or a list of items, and how atomic types map onto byte arrays is left to the + * caller. See https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP + * + *

TRON serializes its own data with protobuf; the only consumer of this class is + * {@code org.tron.core.trie.TrieImpl}, which needs RLP because the trie node layout it implements + * is defined in terms of RLP-encoded lists. Accordingly this class carries only what that layout + * requires: list encoding, lazy list decoding, and the {@link LList} view over a decoded list. * * @author Roman Mandeleil * @since 01.04.2014 */ public class RLP { - private static final Logger logger = LoggerFactory.getLogger("rlp"); - private static final String NOT_NUM = "not a number"; - private static final String WRONG_DECODE_ATTEMPT = "wrong decode attempt"; - private static final int MAX_DEPTH = 16; - /** - * Allow for content up to size of 2^64 bytes * - */ - private static final double MAX_ITEM_LENGTH = pow(256, 8, true); /** * Reason for threshold according to Vitalik Buterin: - 56 bytes maximizes the benefit of both * options - if we went with 60 then we would have only had 4 slots for long strings so RLP would @@ -59,6 +30,7 @@ public class RLP { * the cutoff - also, that's where Bitcoin's varint does the cutof */ private static final int SIZE_THRESHOLD = 56; + /** * [0x80] If a string is 0-55 bytes long, the RLP encoding consists of a single byte with value * 0x80 plus the length of the string followed by the string. The range of the first byte is thus @@ -66,12 +38,6 @@ public class RLP { */ private static final int OFFSET_SHORT_ITEM = 0x80; - /** RLP encoding rules are defined as follows: */ - - /* - * For a single byte whose value is in the [0x00, 0x7f] range, that byte is - * its own RLP encoding. - */ /** * [0xb7] If a string is more than 55 bytes long, the RLP encoding consists of a single byte with * value 0xb7 plus the length of the length of the string in binary form, followed by the length @@ -79,7 +45,9 @@ public class RLP { * \xb9\x04\x00 followed by the string. The range of the first byte is thus [0xb8, 0xbf]. */ private static final int OFFSET_LONG_ITEM = 0xb7; + public static final byte[] EMPTY_ELEMENT_RLP = Hash.encodeElement(new byte[0]); + /** * [0xc0] If the total payload of a list (i.e. the combined length of all its items) is 0-55 bytes * long, the RLP encoding consists of a single byte with value 0xc0 plus the length of the list @@ -96,514 +64,12 @@ public class RLP { */ private static final int OFFSET_LONG_LIST = 0xf7; - /* ****************************************************** * DECODING * * ******************************************************/ - private static byte decodeOneByteItem(byte[] data, int index) { - // null item - if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) { - return (byte) (data[index] - OFFSET_SHORT_ITEM); - } - // single byte item - if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - return data[index]; - } - // single byte item - if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM + 1) { - return data[index + 1]; - } - return 0; - } - - public static int decodeInt(byte[] data, int index) { - - int value = 0; - // NOTE: From RLP doc: - // Ethereum integers must be represented in big endian binary form - // with no leading zeroes (thus making the integer value zero be - // equivalent to the empty byte array) - - if (data[index] == 0x00) { - throw new RuntimeException(NOT_NUM); - } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - - return data[index]; - - } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Integer.BYTES) { - - byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); - byte pow = (byte) (length - 1); - for (int i = 1; i <= length; ++i) { - // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..).. - value += (data[index + i] & 0xFF) << (8 * pow); - pow--; - } - } else { - - // If there are more than 4 bytes, it is not going - // to decode properly into an int. - throw new RuntimeException(WRONG_DECODE_ATTEMPT); - } - return value; - } - - static short decodeShort(byte[] data, int index) { - - short value = 0; - - if (data[index] == 0x00) { - throw new RuntimeException(NOT_NUM); - } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - - return data[index]; - - } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Short.BYTES) { - - byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); - byte pow = (byte) (length - 1); - for (int i = 1; i <= length; ++i) { - // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..) - value += (data[index + i] & 0xFF) << (8 * pow); - pow--; - } - } else { - - // If there are more than 2 bytes, it is not going - // to decode properly into a short. - throw new RuntimeException(WRONG_DECODE_ATTEMPT); - } - return value; - } - - public static long decodeLong(byte[] data, int index) { - - long value = 0; - - if (data[index] == 0x00) { - throw new RuntimeException(NOT_NUM); - } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - - return data[index]; - - } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Long.BYTES) { - - byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); - byte pow = (byte) (length - 1); - for (int i = 1; i <= length; ++i) { - // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..).. - value += (long) (data[index + i] & 0xFF) << (8 * pow); - pow--; - } - } else { - - // If there are more than 8 bytes, it is not going - // to decode properly into a long. - throw new RuntimeException(WRONG_DECODE_ATTEMPT); - } - return value; - } - - public static String decodeStringItem(byte[] data, int index) { - - final byte[] valueBytes = decodeItemBytes(data, index); - - if (valueBytes.length == 0) { - // shortcut - return ""; - } else { - return new String(valueBytes); - } - } - - public static BigInteger decodeBigInteger(byte[] data, int index) { - - final byte[] valueBytes = decodeItemBytes(data, index); - - if (valueBytes.length == 0) { - // shortcut - return BigInteger.ZERO; - } else { - BigInteger res = new BigInteger(1, valueBytes); - return res; - } - } - - public static byte[] decodeByteArray(byte[] data, int index) { - - return decodeItemBytes(data, index); - } - - public static int nextItemLength(byte[] data, int index) { - - if (index >= data.length) { - return -1; - } - // [0xf8, 0xff] - if ((data[index] & 0xFF) > OFFSET_LONG_LIST) { - byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_LIST); - - return calcLength(lengthOfLength, data, index); - } - // [0xc0, 0xf7] - if ((data[index] & 0xFF) >= OFFSET_SHORT_LIST - && (data[index] & 0xFF) <= OFFSET_LONG_LIST) { - - return (byte) ((data[index] & 0xFF) - OFFSET_SHORT_LIST); - } - // [0xb8, 0xbf] - if ((data[index] & 0xFF) > OFFSET_LONG_ITEM - && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { - - byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); - return calcLength(lengthOfLength, data, index); - } - // [0x81, 0xb7] - if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM - && (data[index] & 0xFF) <= OFFSET_LONG_ITEM) { - return (byte) ((data[index] & 0xFF) - OFFSET_SHORT_ITEM); - } - // [0x00, 0x80] - if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM) { - return 1; - } - return -1; - } - - public static byte[] decodeIP4Bytes(byte[] data, int index) { - - int offset = 1; - - final byte[] result = new byte[4]; - for (int i = 0; i < 4; i++) { - result[i] = decodeOneByteItem(data, index + offset); - if ((data[index + offset] & 0xFF) > OFFSET_SHORT_ITEM) { - offset += 2; - } else { - offset += 1; - } - } - - // return IP address - return result; - } - - public static int getFirstListElement(byte[] payload, int pos) { - - if (pos >= payload.length) { - return -1; - } - - // [0xf8, 0xff] - if ((payload[pos] & 0xFF) > OFFSET_LONG_LIST) { - byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST); - return pos + lengthOfLength + 1; - } - // [0xc0, 0xf7] - if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST - && (payload[pos] & 0xFF) <= OFFSET_LONG_LIST) { - return pos + 1; - } - // [0xb8, 0xbf] - if ((payload[pos] & 0xFF) > OFFSET_LONG_ITEM - && (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) { - byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM); - return pos + lengthOfLength + 1; - } - return -1; - } - - public static int getNextElementIndex(byte[] payload, int pos) { - - if (pos >= payload.length) { - return -1; - } - - // [0xf8, 0xff] - if ((payload[pos] & 0xFF) > OFFSET_LONG_LIST) { - byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST); - int length = calcLength(lengthOfLength, payload, pos); - return pos + lengthOfLength + length + 1; - } - // [0xc0, 0xf7] - if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST - && (payload[pos] & 0xFF) <= OFFSET_LONG_LIST) { - - byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_LIST); - return pos + 1 + length; - } - // [0xb8, 0xbf] - if ((payload[pos] & 0xFF) > OFFSET_LONG_ITEM - && (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) { - - byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM); - int length = calcLength(lengthOfLength, payload, pos); - return pos + lengthOfLength + length + 1; - } - // [0x81, 0xb7] - if ((payload[pos] & 0xFF) > OFFSET_SHORT_ITEM - && (payload[pos] & 0xFF) <= OFFSET_LONG_ITEM) { - - byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_ITEM); - return pos + 1 + length; - } - // []0x80] - if ((payload[pos] & 0xFF) == OFFSET_SHORT_ITEM) { - return pos + 1; - } - // [0x00, 0x7f] - if ((payload[pos] & 0xFF) < OFFSET_SHORT_ITEM) { - return pos + 1; - } - return -1; - } - /** - * Parse length of long item or list. RLP supports lengths with up to 8 bytes long, but due to - * java limitation it returns either encoded length or {@link Integer#MAX_VALUE} in case if - * encoded length is greater - * - * @param lengthOfLength length of length in bytes - * @param msgData message - * @param pos position to parse from - * @return calculated length - */ - private static int calcLength(int lengthOfLength, byte[] msgData, int pos) { - byte pow = (byte) (lengthOfLength - 1); - int length = 0; - for (int i = 1; i <= lengthOfLength; ++i) { - - int bt = msgData[pos + i] & 0xFF; - int shift = 8 * pow; - - // no leading zeros are acceptable - if (bt == 0 && length == 0) { - throw new RuntimeException("RLP length contains leading zeros"); - } - - // return MAX_VALUE if index of highest bit is more than 31 - if (32 - Integer.numberOfLeadingZeros(bt) + shift > 31) { - return Integer.MAX_VALUE; - } - - length += bt << shift; - pow--; - } - - // check that length is in payload bounds - verifyLength(length, msgData.length - pos - lengthOfLength); - - return length; - } - - public static byte getCommandCode(byte[] data) { - int index = getFirstListElement(data, 0); - final byte command = data[index]; - return ((command & 0xFF) == OFFSET_SHORT_ITEM) ? 0 : command; - } - - /** - * Parse wire byte[] message into RLP elements - * - * @param msgData - raw RLP data - * @param depthLimit - limits depth of decoding - * @return rlpList - outcome of recursive RLP structure - */ - public static RLPList decode2(byte[] msgData, int depthLimit) { - if (depthLimit < 1) { - throw new RuntimeException("Depth limit should be 1 or higher"); - } - RLPList rlpList = new RLPList(); - fullTraverse(msgData, 0, 0, msgData.length, rlpList, depthLimit); - return rlpList; - } - - /** - * Parse wire byte[] message into RLP elements - * - * @param msgData - raw RLP data - * @return rlpList - outcome of recursive RLP structure - */ - public static RLPList decode2(byte[] msgData) { - RLPList rlpList = new RLPList(); - fullTraverse(msgData, 0, 0, msgData.length, rlpList, Integer.MAX_VALUE); - return rlpList; - } - - /** - * Decodes RLP with list without going deep after 1st level list (actually, 2nd as 1st level is - * wrap only) - * - * So assuming you've packed several byte[] with {@link #encodeList(byte[]...)}, you could use - * this method to unpack them, getting RLPList with RLPItem's holding byte[] inside - * - * @param msgData rlp data - * @return list of RLPItems - */ - public static RLPList unwrapList(byte[] msgData) { - return (RLPList) decode2(msgData, 2).get(0); - } - - public static RLPElement decode2OneItem(byte[] msgData, int startPos) { - RLPList rlpList = new RLPList(); - fullTraverse(msgData, 0, startPos, startPos + 1, rlpList, Integer.MAX_VALUE); - return rlpList.get(0); - } - - /** - * Get exactly one message payload - */ - static void fullTraverse(byte[] msgData, int level, int startPos, - int endPos, RLPList rlpList, int depth) { - if (level > MAX_DEPTH) { - throw new RuntimeException( - String.format("Error: Traversing over max RLP depth (%s)", MAX_DEPTH)); - } - - try { - if (msgData == null || msgData.length == 0) { - return; - } - int pos = startPos; - - while (pos < endPos) { - - logger.debug("fullTraverse: level: " + level + " startPos: " + pos + " endPos: " + endPos); - - // It's a list with a payload more than 55 bytes - // data[0] - 0xF7 = how many next bytes allocated - // for the length of the list - if ((msgData[pos] & 0xFF) > OFFSET_LONG_LIST) { - - byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_LIST); - int length = calcLength(lengthOfLength, msgData, pos); - - if (length < SIZE_THRESHOLD) { - throw new RuntimeException("Short list has been encoded as long list"); - } - - // check that length is in payload bounds - verifyLength(length, msgData.length - pos - lengthOfLength); - - byte[] rlpData = new byte[lengthOfLength + length + 1]; - System.arraycopy(msgData, pos, rlpData, 0, lengthOfLength - + length + 1); - - if (level + 1 < depth) { - RLPList newLevelList = new RLPList(); - newLevelList.setRLPData(rlpData); - - fullTraverse(msgData, level + 1, pos + lengthOfLength + 1, - pos + lengthOfLength + length + 1, newLevelList, depth); - rlpList.add(newLevelList); - } else { - rlpList.add(new RLPItem(rlpData)); - } - - pos += lengthOfLength + length + 1; - continue; - } - // It's a list with a payload less than 55 bytes - if ((msgData[pos] & 0xFF) >= OFFSET_SHORT_LIST - && (msgData[pos] & 0xFF) <= OFFSET_LONG_LIST) { - - byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_LIST); - - byte[] rlpData = new byte[length + 1]; - System.arraycopy(msgData, pos, rlpData, 0, length + 1); - - if (level + 1 < depth) { - RLPList newLevelList = new RLPList(); - newLevelList.setRLPData(rlpData); - - if (length > 0) { - fullTraverse(msgData, level + 1, pos + 1, pos + length + 1, newLevelList, depth); - } - rlpList.add(newLevelList); - } else { - rlpList.add(new RLPItem(rlpData)); - } - - pos += 1 + length; - continue; - } - // It's an item with a payload more than 55 bytes - // data[0] - 0xB7 = how much next bytes allocated for - // the length of the string - if ((msgData[pos] & 0xFF) > OFFSET_LONG_ITEM - && (msgData[pos] & 0xFF) < OFFSET_SHORT_LIST) { - - byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_ITEM); - int length = calcLength(lengthOfLength, msgData, pos); - - if (length < SIZE_THRESHOLD) { - throw new RuntimeException("Short item has been encoded as long item"); - } - - // check that length is in payload bounds - verifyLength(length, msgData.length - pos - lengthOfLength); - - // now we can parse an item for data[1]..data[length] - byte[] item = new byte[length]; - System.arraycopy(msgData, pos + lengthOfLength + 1, item, - 0, length); - - RLPItem rlpItem = new RLPItem(item); - rlpList.add(rlpItem); - pos += lengthOfLength + length + 1; - - continue; - } - // It's an item less than 55 bytes long, - // data[0] - 0x80 == length of the item - if ((msgData[pos] & 0xFF) > OFFSET_SHORT_ITEM - && (msgData[pos] & 0xFF) <= OFFSET_LONG_ITEM) { - - byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_ITEM); - - byte[] item = new byte[length]; - System.arraycopy(msgData, pos + 1, item, 0, length); - - if (length == 1 && (item[0] & 0xFF) < OFFSET_SHORT_ITEM) { - throw new RuntimeException("Single byte has been encoded as byte string"); - } - - RLPItem rlpItem = new RLPItem(item); - rlpList.add(rlpItem); - pos += 1 + length; - - continue; - } - // null item - if ((msgData[pos] & 0xFF) == OFFSET_SHORT_ITEM) { - byte[] item = ByteUtil.EMPTY_BYTE_ARRAY; - RLPItem rlpItem = new RLPItem(item); - rlpList.add(rlpItem); - pos += 1; - continue; - } - // single byte item - if ((msgData[pos] & 0xFF) < OFFSET_SHORT_ITEM) { - - byte[] item = {(byte) (msgData[pos] & 0xFF)}; - - RLPItem rlpItem = new RLPItem(item); - rlpList.add(rlpItem); - pos += 1; - } - } - } catch (Exception e) { - throw new RuntimeException( - "RLP wrong encoding (" + Hex.toHexString(msgData, startPos, endPos - startPos) + ")", e); - } catch (OutOfMemoryError e) { - throw new RuntimeException("Invalid RLP (excessive mem allocation while parsing) (" + Hex - .toHexString(msgData, startPos, endPos - startPos) + ")", e); - } - } - - /** - * Compares supplied length information with maximum possible + * Compares supplied length information with maximum possible. * * @param suppliedLength Length info from header * @param availableLength Length of remaining object @@ -616,53 +82,6 @@ private static void verifyLength(int suppliedLength, int availableLength) { } } - /** - * Reads any RLP encoded byte-array and returns all objects as byte-array or list of byte-arrays - * - * @param data RLP encoded byte-array - * @param pos position in the array to start reading - * @return DecodeResult encapsulates the decoded items as a single Object and the final read - * position - */ - public static DecodeResult decode(byte[] data, int pos) { - if (data == null || data.length < 1) { - return null; - } - int prefix = data[pos] & 0xFF; - if (prefix == OFFSET_SHORT_ITEM) { // 0x80 - return new DecodeResult(pos + 1, ""); // means no length or 0 - } else if (prefix < OFFSET_SHORT_ITEM) { // [0x00, 0x7f] - return new DecodeResult(pos + 1, new byte[]{data[pos]}); // byte is its own RLP encoding - } else if (prefix <= OFFSET_LONG_ITEM) { // [0x81, 0xb7] - int len = prefix - OFFSET_SHORT_ITEM; // length of the encoded bytes - return new DecodeResult(pos + 1 + len, copyOfRange(data, pos + 1, pos + 1 + len)); - } else if (prefix < OFFSET_SHORT_LIST) { // [0xb8, 0xbf] - int lenlen = prefix - OFFSET_LONG_ITEM; // length of length the encoded bytes - int lenbytes = byteArrayToInt( - copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes - // check that length is in payload bounds - verifyLength(lenbytes, data.length - pos - 1 - lenlen); - return new DecodeResult(pos + 1 + lenlen + lenbytes, - copyOfRange(data, pos + 1 + lenlen, pos + 1 + lenlen - + lenbytes)); - } else if (prefix <= OFFSET_LONG_LIST) { // [0xc0, 0xf7] - int len = prefix - OFFSET_SHORT_LIST; // length of the encoded list - int prevPos = pos; - pos++; - return decodeList(data, pos, len); - } else if (prefix <= 0xFF) { // [0xf8, 0xff] - int lenlen = prefix - OFFSET_LONG_LIST; // length of length the encoded list - int lenlist = byteArrayToInt( - copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes - pos = pos + lenlen + 1; // start at position of first element in list - int prevPos = lenlist; - return decodeList(data, pos, lenlist); - } else { - throw new RuntimeException( - "Only byte values between 0x00 and 0xFF are supported, but got: " + prefix); - } - } - public static LList decodeLazyList(byte[] data) { LList lList = decodeLazyList(data, 0, data.length); return lList == null ? null : lList.getList(0); @@ -715,271 +134,10 @@ public static LList decodeLazyList(byte[] data, int pos, int length) { return ret; } - private static DecodeResult decodeList(byte[] data, int pos, int len) { - // check that length is in payload bounds - verifyLength(len, data.length - pos); - int prevPos; - List slice = new ArrayList<>(); - for (int i = 0; i < len; ) { - // Get the next item in the data list and append it - DecodeResult result = decode(data, pos); - slice.add(result.getDecoded()); - // Increment pos by the amount bytes in the previous read - prevPos = result.getPos(); - i += (prevPos - pos); - pos = prevPos; - } - return new DecodeResult(pos, slice.toArray()); - } - - /** - * Turn Object into its RLP encoded equivalent of a byte-array Support for String, Integer, - * BigInteger and Lists of any of these types. - * - * @param input as object or List of objects - * @return byte[] RLP encoded - */ - public static byte[] encode(Object input) { - Value val = new Value(input); - if (val.isList()) { - List inputArray = val.asList(); - if (inputArray.isEmpty()) { - return encodeLength(inputArray.size(), OFFSET_SHORT_LIST); - } - byte[] output = ByteUtil.EMPTY_BYTE_ARRAY; - for (Object object : inputArray) { - output = concatenate(output, encode(object)); - } - byte[] prefix = encodeLength(output.length, OFFSET_SHORT_LIST); - return concatenate(prefix, output); - } else { - byte[] inputAsBytes = toBytes(input); - if (inputAsBytes.length == 1 && (inputAsBytes[0] & 0xff) <= 0x80) { - return inputAsBytes; - } else { - byte[] firstByte = encodeLength(inputAsBytes.length, OFFSET_SHORT_ITEM); - return concatenate(firstByte, inputAsBytes); - } - } - } - /* ****************************************************** * ENCODING * * ******************************************************/ - /** - * Integer limitation goes up to 2^31-1 so length can never be bigger than MAX_ITEM_LENGTH - */ - public static byte[] encodeLength(int length, int offset) { - if (length < SIZE_THRESHOLD) { - byte firstByte = (byte) (length + offset); - return new byte[]{firstByte}; - } else if (length < MAX_ITEM_LENGTH) { - byte[] binaryLength; - if (length > 0xFF) { - binaryLength = intToBytesNoLeadZeroes(length); - } else { - binaryLength = new byte[]{(byte) length}; - } - byte firstByte = (byte) (binaryLength.length + offset + SIZE_THRESHOLD - 1); - return concatenate(new byte[]{firstByte}, binaryLength); - } else { - throw new RuntimeException("Input too long"); - } - } - - public static byte[] encodeByte(byte singleByte) { - if ((singleByte & 0xFF) == 0) { - return new byte[]{(byte) OFFSET_SHORT_ITEM}; - } else if ((singleByte & 0xFF) <= 0x7F) { - return new byte[]{singleByte}; - } else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 1), singleByte}; - } - } - - public static byte[] encodeShort(short singleShort) { - - if ((singleShort & 0xFF) == singleShort) { - return encodeByte((byte) singleShort); - } else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 2), - (byte) (singleShort >> 8 & 0xFF), - (byte) (singleShort >> 0 & 0xFF)}; - } - } - - public static byte[] encodeInt(int singleInt) { - - if ((singleInt & 0xFF) == singleInt) { - return encodeByte((byte) singleInt); - } else if ((singleInt & 0xFFFF) == singleInt) { - return encodeShort((short) singleInt); - } else if ((singleInt & 0xFFFFFF) == singleInt) { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 3), - (byte) (singleInt >>> 16), - (byte) (singleInt >>> 8), - (byte) singleInt}; - } else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 4), - (byte) (singleInt >>> 24), - (byte) (singleInt >>> 16), - (byte) (singleInt >>> 8), - (byte) singleInt}; - } - } - - public static byte[] encodeString(String srcString) { - return Hash.encodeElement(srcString.getBytes()); - } - - public static byte[] encodeBigInteger(BigInteger srcBigInteger) { - if (srcBigInteger.compareTo(BigInteger.ZERO) < 0) { - throw new RuntimeException("negative numbers are not allowed"); - } - - if (srcBigInteger.equals(BigInteger.ZERO)) { - return encodeByte((byte) 0); - } else { - return Hash.encodeElement(asUnsignedByteArray(srcBigInteger)); - } - } - - public static int calcElementPrefixSize(byte[] srcData) { - - if (isNullOrZeroArray(srcData)) { - return 0; - } else if (isSingleZero(srcData)) { - return 0; - } else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { - return 0; - } else if (srcData.length < SIZE_THRESHOLD) { - return 1; - } else { - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = srcData.length; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - - return 1 + byteNum; - } - } - - public static byte[] encodeListHeader(int size) { - - if (size == 0) { - return new byte[]{(byte) OFFSET_SHORT_LIST}; - } - - int totalLength = size; - - byte[] header; - if (totalLength < SIZE_THRESHOLD) { - - header = new byte[1]; - header[0] = (byte) (OFFSET_SHORT_LIST + totalLength); - } else { - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = totalLength; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - tmpLength = totalLength; - - byte[] lenBytes = new byte[byteNum]; - for (int i = 0; i < byteNum; ++i) { - lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); - } - // first byte = F7 + bytes.length - header = new byte[1 + lenBytes.length]; - header[0] = (byte) (OFFSET_LONG_LIST + byteNum); - System.arraycopy(lenBytes, 0, header, 1, lenBytes.length); - - } - - return header; - } - - public static byte[] encodeLongElementHeader(int length) { - - if (length < SIZE_THRESHOLD) { - - if (length == 0) { - return new byte[]{(byte) 0x80}; - } else { - return new byte[]{(byte) (0x80 + length)}; - } - - } else { - - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = length; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - - byte[] lenBytes = new byte[byteNum]; - for (int i = 0; i < byteNum; ++i) { - lenBytes[byteNum - 1 - i] = (byte) ((length >> (8 * i)) & 0xFF); - } - - // first byte = F7 + bytes.length - byte[] header = new byte[1 + lenBytes.length]; - header[0] = (byte) (OFFSET_LONG_ITEM + byteNum); - System.arraycopy(lenBytes, 0, header, 1, lenBytes.length); - - return header; - } - } - - public static byte[] encodeSet(Set data) { - - int dataLength = 0; - Set encodedElements = new HashSet<>(); - for (ByteArrayWrapper element : data) { - - byte[] encodedElement = Hash.encodeElement(element.getData()); - dataLength += encodedElement.length; - encodedElements.add(encodedElement); - } - - byte[] listHeader = encodeListHeader(dataLength); - - byte[] output = new byte[listHeader.length + dataLength]; - - System.arraycopy(listHeader, 0, output, 0, listHeader.length); - - int cummStart = listHeader.length; - for (byte[] element : encodedElements) { - System.arraycopy(element, 0, output, cummStart, element.length); - cummStart += element.length; - } - - return output; - } - - /** - * A handy shortcut for {@link #encodeElement(byte[])} + {@link #encodeList(byte[]...)}

- * Encodes each data element and wraps them all into a list. - */ - public static byte[] wrapList(byte[]... data) { - byte[][] elements = new byte[data.length][]; - for (int i = 0; i < data.length; i++) { - elements[i] = Hash.encodeElement(data[i]); - } - return encodeList(elements); - } - public static byte[] encodeList(byte[]... elements) { if (elements == null) { @@ -1074,100 +232,10 @@ public static byte[] encodeList(Object... elements) { return data; } - /* - * Utility function to convert Objects into byte arrays + /** + * A lazy view over a decoded RLP list: the elements are recorded as offsets into the original + * payload and materialised only when read. */ - private static byte[] toBytes(Object input) { - if (input instanceof byte[]) { - return (byte[]) input; - } else if (input instanceof String) { - String inputString = (String) input; - return inputString.getBytes(); - } else if (input instanceof Long) { - Long inputLong = (Long) input; - return (inputLong == 0) ? ByteUtil.EMPTY_BYTE_ARRAY - : asUnsignedByteArray(BigInteger.valueOf(inputLong)); - } else if (input instanceof Integer) { - Integer inputInt = (Integer) input; - return (inputInt == 0) ? ByteUtil.EMPTY_BYTE_ARRAY - : asUnsignedByteArray(BigInteger.valueOf(inputInt)); - } else if (input instanceof BigInteger) { - BigInteger inputBigInt = (BigInteger) input; - return (inputBigInt.equals(BigInteger.ZERO)) ? ByteUtil.EMPTY_BYTE_ARRAY - : asUnsignedByteArray(inputBigInt); - } else if (input instanceof Value) { - Value val = (Value) input; - return toBytes(val.asObj()); - } - throw new RuntimeException( - "Unsupported type: Only accepting String, Integer and BigInteger for now"); - } - - public static byte[] decodeItemBytes(byte[] data, int index) { - - final int length = calculateItemLength(data, index); - // [0x80] - if (length == 0) { - - return new byte[0]; - - // [0x00, 0x7f] - single byte with item - } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - - byte[] valueBytes = new byte[1]; - System.arraycopy(data, index, valueBytes, 0, 1); - return valueBytes; - - // [0x01, 0xb7] - 1-55 bytes item - } else if ((data[index] & 0xFF) <= OFFSET_LONG_ITEM) { - - byte[] valueBytes = new byte[length]; - System.arraycopy(data, index + 1, valueBytes, 0, length); - return valueBytes; - - // [0xb8, 0xbf] - 56+ bytes item - } else if ((data[index] & 0xFF) > OFFSET_LONG_ITEM - && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { - - byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); - byte[] valueBytes = new byte[length]; - System.arraycopy(data, index + 1 + lengthOfLength, valueBytes, 0, length); - return valueBytes; - } else { - throw new RuntimeException(WRONG_DECODE_ATTEMPT); - } - } - - private static int calculateItemLength(byte[] data, int index) { - - // [0xb8, 0xbf] - 56+ bytes item - if ((data[index] & 0xFF) > OFFSET_LONG_ITEM - && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { - - byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); - return calcLength(lengthOfLength, data, index); - - // [0x81, 0xb7] - 0-55 bytes item - } else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM - && (data[index] & 0xFF) <= OFFSET_LONG_ITEM) { - - return (byte) (data[index] - OFFSET_SHORT_ITEM); - - // [0x80] - item = 0 itself - } else if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) { - - return (byte) 0; - - // [0x00, 0x7f] - 1 byte item, no separate length representation - } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { - - return (byte) 1; - - } else { - throw new RuntimeException(WRONG_DECODE_ATTEMPT); - } - } - public static final class LList { private final byte[] rlp; diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLPElement.java b/framework/src/main/java/org/tron/core/capsule/utils/RLPElement.java deleted file mode 100644 index b2af70fa215..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLPElement.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.tron.core.capsule.utils; - -import java.io.Serializable; - -/** - * Wrapper class for decoded elements from an RLP encoded byte array. - */ -public interface RLPElement extends Serializable { - - byte[] getRLPData(); -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLPItem.java b/framework/src/main/java/org/tron/core/capsule/utils/RLPItem.java deleted file mode 100644 index 6279d6cc00c..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLPItem.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.tron.core.capsule.utils; - -/** - */ -public class RLPItem implements RLPElement { - - private final byte[] rlpData; - - public RLPItem(byte[] rlpData) { - this.rlpData = rlpData; - } - - public byte[] getRLPData() { - if (rlpData.length == 0) { - return null; - } - return rlpData; - } -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/RLPList.java b/framework/src/main/java/org/tron/core/capsule/utils/RLPList.java deleted file mode 100644 index 8ef5680b5c2..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/RLPList.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.tron.core.capsule.utils; - -import java.util.ArrayList; -import org.tron.common.utils.ByteArray; - -/** - */ -public class RLPList extends ArrayList implements RLPElement { - - private byte[] rlpData; - - public static void recursivePrint(RLPElement element) { - - if (element == null) { - throw new RuntimeException("RLPElement object can't be null"); - } - if (element instanceof RLPList) { - - RLPList rlpList = (RLPList) element; - System.out.print("["); - for (RLPElement singleElement : rlpList) { - recursivePrint(singleElement); - } - System.out.print("]"); - } else { - String hex = ByteArray.toHexString(element.getRLPData()); - System.out.print(hex + ", "); - } - } - - public byte[] getRLPData() { - return rlpData; - } - - public void setRLPData(byte[] rlpData) { - this.rlpData = rlpData; - } -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/TxInputUtil.java b/framework/src/main/java/org/tron/core/capsule/utils/TxInputUtil.java deleted file mode 100644 index 6920a313627..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/TxInputUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.core.capsule.utils; - -import com.google.protobuf.ByteString; -import org.tron.protos.Protocol.TXInput; - -public class TxInputUtil { - - /** - * new transaction input. - * - * @param txId byte[] txId - * @param vout int vout - * @param signature byte[] signature - * @param pubKey byte[] pubKey - * @return {@link TXInput} - */ - public static TXInput newTxInput(byte[] txId, long vout, byte[] - signature, byte[] pubKey) { - - TXInput.raw.Builder rawBuilder = TXInput.raw.newBuilder(); - - TXInput.raw rawData = rawBuilder - .setTxID(ByteString.copyFrom(txId)) - .setVout(vout) - .setPubKey(ByteString.copyFrom(pubKey)).build(); - - return TXInput.newBuilder() - .setSignature(ByteString.copyFrom(signature)) - .setRawData(rawData).build(); - } -} diff --git a/framework/src/main/java/org/tron/core/capsule/utils/TxOutputUtil.java b/framework/src/main/java/org/tron/core/capsule/utils/TxOutputUtil.java deleted file mode 100644 index 73313df32b4..00000000000 --- a/framework/src/main/java/org/tron/core/capsule/utils/TxOutputUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.core.capsule.utils; - -import com.google.protobuf.ByteString; -import org.tron.common.utils.ByteArray; -import org.tron.protos.Protocol.TXOutput; - -public class TxOutputUtil { - - /** - * new transaction output. - * - * @param value int value - * @param address String address - * @return {@link TXOutput} - */ - public static TXOutput newTxOutput(long value, String address) { - return TXOutput.newBuilder() - .setValue(value) - .setPubKeyHash(ByteString.copyFrom(ByteArray.fromHexString(address))) - .build(); - } -} diff --git a/framework/src/main/java/org/tron/core/trie/TrieImpl.java b/framework/src/main/java/org/tron/core/trie/TrieImpl.java index 586c3b2b893..ba928094790 100644 --- a/framework/src/main/java/org/tron/core/trie/TrieImpl.java +++ b/framework/src/main/java/org/tron/core/trie/TrieImpl.java @@ -21,8 +21,8 @@ import org.slf4j.LoggerFactory; import org.tron.common.crypto.Hash; import org.tron.common.es.ExecutorServiceManager; +import org.tron.common.utils.FastByteComparisons; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.utils.FastByteComparisons; import org.tron.core.capsule.utils.RLP; import org.tron.core.db2.common.ConcurrentHashDB; import org.tron.core.db2.common.DB; @@ -321,7 +321,7 @@ public boolean equals(Object o) { TrieImpl trieImpl1 = (TrieImpl) o; - return FastByteComparisons.equalByte(getRootHash(), trieImpl1.getRootHash()); + return FastByteComparisons.isEqual(getRootHash(), trieImpl1.getRootHash()); } @@ -561,7 +561,7 @@ public Node getRoot() { } public void setRoot(byte[] root) { - if (root != null && !FastByteComparisons.equalByte(root, EMPTY_TRIE_HASH)) { + if (root != null && !FastByteComparisons.isEqual(root, EMPTY_TRIE_HASH)) { this.root = new Node(root); } else { this.root = null; diff --git a/framework/src/test/java/org/tron/core/TxInputUtilTest.java b/framework/src/test/java/org/tron/core/TxInputUtilTest.java deleted file mode 100644 index 17d0082256f..00000000000 --- a/framework/src/test/java/org/tron/core/TxInputUtilTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.core; - -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.utils.ByteArray; -import org.tron.core.capsule.utils.TxInputUtil; -import org.tron.protos.Protocol.TXInput; - -@Slf4j -public class TxInputUtilTest { - - @Test - public void testNewput() { - byte[] bytes = new byte[32]; - for (int i = 0; i < bytes.length; i++) { - System.out.println("-----------" + bytes[i]); - } - } - - @Test - public void testNewTxInput() { - byte[] txId = ByteArray - .fromHexString("2c0937534dd1b3832d05d865e8e6f2bf23218300b33a992740d45ccab7d4f519"); - long vout = 777L; - byte[] signature = ByteArray - .fromHexString("ded9c2181fd7ea468a7a7b1475defe90bb0fc0ca8d0f2096b0617465cea6568c"); - byte[] pubkey = ByteArray - .fromHexString("a0c9d5524c055381fe8b1950e0c3b09d252add57a7aec061ae258aa03ee25822"); - TXInput txInput = TxInputUtil.newTxInput(txId, vout, signature, pubkey); - - Assert.assertArrayEquals(txId, txInput.getRawData().getTxID().toByteArray()); - Assert.assertEquals(vout, txInput.getRawData().getVout()); - Assert.assertArrayEquals(signature, txInput.getSignature().toByteArray()); - Assert.assertArrayEquals(pubkey, txInput.getRawData().getPubKey().toByteArray()); - - } -} diff --git a/framework/src/test/java/org/tron/core/TxOutputUtilTest.java b/framework/src/test/java/org/tron/core/TxOutputUtilTest.java deleted file mode 100644 index b9247f6f68a..00000000000 --- a/framework/src/test/java/org/tron/core/TxOutputUtilTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * java-tron is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-tron is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.tron.core; - -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.utils.ByteArray; -import org.tron.core.capsule.utils.TxOutputUtil; -import org.tron.protos.Protocol.TXOutput; - -@Slf4j -public class TxOutputUtilTest { - - @Test - public void testNewTxOutput() { - long value = 123456L; - String address = "3450dde5007c67a50ec2e09489fa53ec1ff59c61e7ddea9638645e6e5f62e5f5"; - TXOutput txOutput = TxOutputUtil.newTxOutput(value, address); - - Assert.assertEquals(value, txOutput.getValue()); - Assert.assertEquals(address, ByteArray.toHexString(txOutput.getPubKeyHash().toByteArray())); - - long value3 = 9852448L; - String address3 = "0xfd1a5decba973b0d31e84e7d8f4a5b10d33ab37ce6533f1ff5a9db2d9db8ef"; - String address4 = "fd1a5decba973b0d31e84e7d8f4a5b10d33ab37ce6533f1ff5a9db2d9db8ef"; - TXOutput txOutput3 = TxOutputUtil.newTxOutput(value3, address3); - - Assert.assertEquals(value3, txOutput3.getValue()); - Assert.assertEquals(address4, ByteArray.toHexString(txOutput3.getPubKeyHash().toByteArray())); - - long value5 = 67549L; - String address5 = null; - TXOutput txOutput5 = TxOutputUtil.newTxOutput(value5, address5); - - Assert.assertEquals(value5, txOutput5.getValue()); - Assert.assertEquals("", ByteArray.toHexString(txOutput5.getPubKeyHash().toByteArray())); - - } - -} diff --git a/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java b/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java deleted file mode 100644 index 008224f98a1..00000000000 --- a/framework/src/test/java/org/tron/core/capsule/utils/DecodeResultTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.tron.core.capsule.utils; - -import org.bouncycastle.util.encoders.Hex; -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.utils.ByteUtil; - -public class DecodeResultTest { - - @Test - public void testConstruct() { - DecodeResult decodeResult = new DecodeResult(0, "decoded"); - Assert.assertEquals(decodeResult.getPos(), 0); - Assert.assertEquals(decodeResult.getDecoded(), "decoded"); - Assert.assertEquals(decodeResult.toString(), "decoded"); - } - - @Test - public void testToString() { - DecodeResult decodeResult = new DecodeResult(0, "decoded"); - Assert.assertEquals(decodeResult.toString(), "decoded"); - decodeResult = new DecodeResult(0, ByteUtil.intToBytes(1000)); - Assert.assertEquals(Hex.toHexString(ByteUtil.intToBytes(1000)), decodeResult.toString()); - Object[] decodedData = {"aa","bb"}; - decodeResult = new DecodeResult(0, decodedData); - Assert.assertEquals("aabb", decodeResult.toString()); - } -} diff --git a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java b/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java deleted file mode 100644 index 9c2e8550634..00000000000 --- a/framework/src/test/java/org/tron/core/capsule/utils/RLPListTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.tron.core.capsule.utils; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.math.BigInteger; -import java.util.Random; -import org.bouncycastle.util.BigIntegers; -import org.junit.Assert; -import org.junit.Test; -import org.tron.common.utils.Value; - -public class RLPListTest { - - @Test - public void testRecursivePrint() { - RLPItem element = new RLPItem("rlpItem".getBytes()); - Assert.assertEquals("rlpItem", new String(element.getRLPData())); - RLPList.recursivePrint(element); - RLPList rlpList = new RLPList(); - rlpList.add(new RLPItem("rlpItem0".getBytes())); - RLPList.recursivePrint(rlpList); - Assert.assertThrows(RuntimeException.class, () -> RLPList.recursivePrint(null)); - - RLPItem rlpItem = new RLPItem(new byte[0]); - Assert.assertNull(rlpItem.getRLPData()); - - } - - @Test - public void testGetRLPData() { - RLPList rlpList = new RLPList(); - rlpList.setRLPData("rlpData".getBytes()); - Assert.assertEquals(new String(rlpList.getRLPData()), "rlpData"); - } - - @Test - public void testToBytes() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Method method = RLP.class.getDeclaredMethod("toBytes", Object.class); - method.setAccessible(true); - - byte[] aBytes = new byte[10]; - byte[] bBytes = (byte[]) method.invoke(RLP.class, aBytes); - Assert.assertArrayEquals(aBytes, bBytes); - - int i = new Random().nextInt(); - byte[] cBytes = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(i)); - byte[] dBytes = (byte[]) method.invoke(RLP.class, i); - Assert.assertArrayEquals(cBytes, dBytes); - - long j = new Random().nextInt(); - byte[] eBytes = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(j)); - byte[] fBytes = (byte[]) method.invoke(RLP.class, j); - Assert.assertArrayEquals(eBytes, fBytes); - - String test = "testA"; - byte[] gBytes = test.getBytes(); - byte[] hBytes = (byte[]) method.invoke(RLP.class, test); - Assert.assertArrayEquals(gBytes, hBytes); - - BigInteger bigInteger = BigInteger.valueOf(100); - byte[] iBytes = BigIntegers.asUnsignedByteArray(bigInteger); - byte[] jBytes = (byte[]) method.invoke(RLP.class, bigInteger); - Assert.assertArrayEquals(iBytes, jBytes); - - Value v = new Value(new byte[0]); - byte[] kBytes = v.asBytes(); - byte[] lBytes = (byte[]) method.invoke(RLP.class, v); - Assert.assertArrayEquals(kBytes, lBytes); - - char c = 'a'; - Assert.assertThrows(Exception.class, - () -> method.invoke(RLP.class, c)); - } - - @Test - public void testEncode() { - byte[] aBytes = RLP.encode(new byte[1]); - Assert.assertEquals(1, aBytes.length); - } -} diff --git a/framework/src/test/java/org/tron/core/tire/TrieTest.java b/framework/src/test/java/org/tron/core/tire/TrieTest.java index a12472a8a34..4572849a2b6 100644 --- a/framework/src/test/java/org/tron/core/tire/TrieTest.java +++ b/framework/src/test/java/org/tron/core/tire/TrieTest.java @@ -27,8 +27,8 @@ import java.util.Random; import org.junit.Assert; import org.junit.Test; -import org.tron.core.capsule.utils.FastByteComparisons; -import org.tron.core.capsule.utils.RLP; +import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.FastByteComparisons; import org.tron.core.trie.TrieImpl; import org.tron.core.trie.TrieImpl.Node; @@ -47,38 +47,38 @@ public class TrieTest { public void test() { TrieImpl trie = new TrieImpl(); trie.put(new byte[]{1}, c.getBytes()); - Assert.assertArrayEquals(trie.get(RLP.encodeInt(1)), c.getBytes()); + Assert.assertArrayEquals(trie.get(ByteUtil.intToBytesNoLeadZeroes(1)), c.getBytes()); trie.put(new byte[]{1, 0}, ca.getBytes()); trie.put(new byte[]{1, 1}, cat.getBytes()); trie.put(new byte[]{1, 2}, dog.getBytes()); - trie.put(RLP.encodeInt(5), doge.getBytes()); - trie.put(RLP.encodeInt(6), doge.getBytes()); - trie.put(RLP.encodeInt(7), doge.getBytes()); - trie.put(RLP.encodeInt(11), doge.getBytes()); - trie.put(RLP.encodeInt(12), dude.getBytes()); - trie.put(RLP.encodeInt(13), test.getBytes()); - trie.delete(RLP.encodeInt(3)); + trie.put(ByteUtil.intToBytesNoLeadZeroes(5), doge.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(6), doge.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(7), doge.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(11), doge.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(12), dude.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(13), test.getBytes()); + trie.delete(ByteUtil.intToBytesNoLeadZeroes(3)); byte[] rootHash = trie.getRootHash(); TrieImpl trieCopy = new TrieImpl(trie.getCache(), rootHash); - Assert.assertNull(trie.prove(RLP.encodeInt(111))); + Assert.assertNull(trie.prove(ByteUtil.intToBytesNoLeadZeroes(111))); Map map = trieCopy.prove(new byte[]{1, 1}); boolean result = trie .verifyProof(trieCopy.getRootHash(), new byte[]{1, 1}, (LinkedHashMap) map); Assert.assertTrue(result); - assertTrue(RLP.encodeInt(5), trieCopy); - assertTrue(RLP.encodeInt(5), RLP.encodeInt(6), trieCopy); - assertTrue(RLP.encodeInt(6), trieCopy); - assertTrue(RLP.encodeInt(6), RLP.encodeInt(5), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(5), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(5), ByteUtil.intToBytesNoLeadZeroes(6), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(6), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(6), ByteUtil.intToBytesNoLeadZeroes(5), trieCopy); // - trie.put(RLP.encodeInt(5), doge.getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(5), doge.getBytes()); byte[] rootHash2 = trie.getRootHash(); Assert.assertArrayEquals(rootHash, rootHash2); trieCopy = new TrieImpl(trie.getCache(), rootHash2); // - assertTrue(RLP.encodeInt(5), trieCopy); - assertTrue(RLP.encodeInt(5), RLP.encodeInt(6), trieCopy); - assertTrue(RLP.encodeInt(6), trieCopy); - assertTrue(RLP.encodeInt(6), RLP.encodeInt(5), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(5), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(5), ByteUtil.intToBytesNoLeadZeroes(6), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(6), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(6), ByteUtil.intToBytesNoLeadZeroes(5), trieCopy); } @Test @@ -86,13 +86,13 @@ public void test1() { TrieImpl trie = new TrieImpl(); int n = 100; for (int i = 1; i < n; i++) { - trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash1 = trie.getRootHash(); TrieImpl trie2 = new TrieImpl(); for (int i = 1; i < n; i++) { - trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie2.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash2 = trie2.getRootHash(); Assert.assertArrayEquals(rootHash1, rootHash2); @@ -103,17 +103,18 @@ public void test2() { TrieImpl trie = new TrieImpl(); int n = 100; for (int i = 1; i < n; i++) { - trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash = trie.getRootHash(); TrieImpl trieCopy = new TrieImpl(trie.getCache(), rootHash); for (int i = 1; i < n; i++) { - assertTrue(RLP.encodeInt(i), trieCopy); + assertTrue(ByteUtil.intToBytesNoLeadZeroes(i), trieCopy); } for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++) { if (i != j) { - assertFalse(RLP.encodeInt(i), RLP.encodeInt(j), trieCopy); + assertFalse(ByteUtil.intToBytesNoLeadZeroes(i), + ByteUtil.intToBytesNoLeadZeroes(j), trieCopy); } } } @@ -139,14 +140,14 @@ public void testOrder() { List value = new ArrayList<>(); for (int i = 1; i < n; i++) { value.add(i); - trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } - trie.put(RLP.encodeInt(10), String.valueOf(10).getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(10), String.valueOf(10).getBytes()); value.add(10); byte[] rootHash1 = trie.getRootHash(); TrieImpl baseline = new TrieImpl(); for (int i = 1; i < n; i++) { - baseline.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + baseline.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } Assert.assertArrayEquals(baseline.getRootHash(), rootHash1); Collections.shuffle(value, new Random(SHUFFLE_SEED)); @@ -213,7 +214,7 @@ private static List parseSeq(String csv) { private static void assertTrieRootHash(byte[] rootHash1, List value) { TrieImpl trie2 = new TrieImpl(); for (int i : value) { - trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie2.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash2 = trie2.getRootHash(); Assert.assertArrayEquals(rootHash1, rootHash2); @@ -250,13 +251,13 @@ public void testOrderNoDuplicate() { List value = new ArrayList<>(); for (int i = 1; i < n; i++) { value.add(i); - trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash1 = trie.getRootHash(); Collections.shuffle(value, new Random(42)); TrieImpl trie2 = new TrieImpl(); for (int i : value) { - trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + trie2.put(ByteUtil.intToBytesNoLeadZeroes(i), String.valueOf(i).getBytes()); } byte[] rootHash2 = trie2.getRootHash(); Assert.assertArrayEquals(rootHash1, rootHash2); diff --git a/framework/src/test/java/org/tron/program/SupplementTest.java b/framework/src/test/java/org/tron/program/SupplementTest.java index f95f3222108..dcb771362ff 100644 --- a/framework/src/test/java/org/tron/program/SupplementTest.java +++ b/framework/src/test/java/org/tron/program/SupplementTest.java @@ -11,9 +11,7 @@ import java.math.BigInteger; import javax.annotation.Resource; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.tron.common.BaseTest; import org.tron.common.TestConstants; import org.tron.common.entity.PeerInfo; @@ -21,7 +19,6 @@ import org.tron.common.utils.JsonUtil; import org.tron.common.utils.Value; import org.tron.core.capsule.StorageRowCapsule; -import org.tron.core.capsule.utils.RLP; import org.tron.core.config.TronLogShutdownHook; import org.tron.core.config.args.Args; import org.tron.core.services.http.HttpSelfFormatFieldName; @@ -34,9 +31,6 @@ public class SupplementTest extends BaseTest { @Resource private StorageRowStore storageRowStore; - @Rule - public ExpectedException thrown = ExpectedException.none(); - @BeforeClass public static void init() throws IOException { dbPath = dbPath(); @@ -109,17 +103,6 @@ public void testGet() throws Exception { assertFalse(CompactEncoder.hasTerminator(new byte[] {1,2,3,4,5,6,7})); CompactEncoder.unpackToNibbles(new byte[] {1,2,3,4,5,6,7}); CompactEncoder.binToNibblesNoTerminator(new byte[] {1,2,3,4,5,6,7}); - - assertNotNull(RLP.decodeIP4Bytes(new byte[] {1,2,3,4,5,6,7}, 0)); - RLP.decodeByteArray(new byte[] {1,2,3,4,5,6,7}, 0); - RLP.nextItemLength(new byte[] {1,2,3,4,5,6,7}, 0); - RLP.decodeStringItem(new byte[] {1,2,3,4,5,6,7}, 0); - RLP.decodeInt(new byte[] {1,2,3,4,5,6,7}, 0); - RLP.decode2OneItem(new byte[] {1,2,3,4,5,6,7}, 0); - RLP.decode2(new byte[] {1,2,3,4,5,6,7}, 1); - RLP.decode2(new byte[] {1,2,3,4,5,6,7}); - thrown.expect(ClassCastException.class); - RLP.unwrapList(new byte[] {1,2,3,4,5,6,7}); } @Test