You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuweni.apache.org by to...@apache.org on 2021/05/29 07:05:55 UTC

[incubator-tuweni] branch main updated: UInt compat fixes

This is an automated email from the ASF dual-hosted git repository.

toulmean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git


The following commit(s) were added to refs/heads/main by this push:
     new 09091de  UInt compat fixes
     new 7990069  Merge pull request #250 from atoulme/uint_fixes
09091de is described below

commit 09091deb4c5d1e39f351c2b155a67767ec77024d
Author: Antoine Toulme <an...@lunar-ocean.com>
AuthorDate: Fri May 28 23:02:59 2021 -0700

    UInt compat fixes
---
 .../org/apache/tuweni/evm/impl/berlin/OpCodes.kt   |   4 +-
 .../tuweni/units/bigints/BaseUInt256Value.java     |   6 +
 .../org/apache/tuweni/units/bigints/UInt256.java   |   6 +-
 .../apache/tuweni/units/bigints/UInt256Value.java  | 145 +++++++++++++++++++--
 .../apache/tuweni/units/bigints/UInt32Value.java   |   9 ++
 .../apache/tuweni/units/bigints/UInt384Value.java  |   9 ++
 .../apache/tuweni/units/bigints/UInt64Value.java   |   9 ++
 .../apache/tuweni/units/bigints/UInt256Test.java   |   5 +
 .../apache/tuweni/units/bigints/UInt32Test.java    |   4 +
 .../apache/tuweni/units/bigints/UInt384Test.java   |   5 +
 .../apache/tuweni/units/bigints/UInt64Test.java    |   5 +
 .../org/apache/tuweni/units/ethereum/WeiTest.java  |  20 +++
 12 files changed, 210 insertions(+), 17 deletions(-)

diff --git a/evm/src/main/kotlin/org/apache/tuweni/evm/impl/berlin/OpCodes.kt b/evm/src/main/kotlin/org/apache/tuweni/evm/impl/berlin/OpCodes.kt
index eb0de1d..fa54494 100644
--- a/evm/src/main/kotlin/org/apache/tuweni/evm/impl/berlin/OpCodes.kt
+++ b/evm/src/main/kotlin/org/apache/tuweni/evm/impl/berlin/OpCodes.kt
@@ -102,7 +102,7 @@ val slt = Opcode { gasManager, _, stack, _, _, _, _ ->
   if (null == item || null == item2) {
     Result(EVMExecutionStatusCode.STACK_UNDERFLOW)
   } else {
-    if (item.toBigInteger() < item2.toBigInteger()) {
+    if (item.toSignedBigInteger() < item2.toSignedBigInteger()) {
       stack.push(UInt256.ONE)
     } else {
       stack.push(UInt256.ZERO)
@@ -134,7 +134,7 @@ val sgt = Opcode { gasManager, _, stack, _, _, _, _ ->
   if (null == item || null == item2) {
     Result(EVMExecutionStatusCode.STACK_UNDERFLOW)
   } else {
-    if (item.toBigInteger() > item2.toBigInteger()) {
+    if (item.toSignedBigInteger() > item2.toSignedBigInteger()) {
       stack.push(UInt256.ONE)
     } else {
       stack.push(UInt256.ZERO)
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/BaseUInt256Value.java b/units/src/main/java/org/apache/tuweni/units/bigints/BaseUInt256Value.java
index a6329cb..4bef9ac 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/BaseUInt256Value.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/BaseUInt256Value.java
@@ -19,6 +19,7 @@ import org.apache.tuweni.bytes.Bytes32;
 import org.apache.tuweni.bytes.MutableBytes32;
 
 import java.math.BigInteger;
+import java.nio.ByteOrder;
 import java.util.function.Function;
 
 /**
@@ -381,4 +382,9 @@ public abstract class BaseUInt256Value<T extends UInt256Value<T>> implements UIn
   public MutableBytes32 mutableCopy() {
     return MutableBytes32.wrap(value.toArrayUnsafe());
   }
+
+  @Override
+  public long toLong(ByteOrder order) {
+    return value.toLong(order);
+  }
 }
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/UInt256.java b/units/src/main/java/org/apache/tuweni/units/bigints/UInt256.java
index 94173b3..3bb2f4a 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/UInt256.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/UInt256.java
@@ -451,7 +451,7 @@ public final class UInt256 implements UInt256Value<UInt256> {
     if (divisor.isZero()) {
       return UInt256.ZERO;
     } else {
-      BigInteger result = this.toBigInteger().divide(divisor.toBigInteger());
+      BigInteger result = this.toSignedBigInteger().divide(divisor.toSignedBigInteger());
       Bytes resultBytes = Bytes.wrap(result.toByteArray());
       if (resultBytes.size() > 32) {
         resultBytes = resultBytes.slice(resultBytes.size() - 32, 32);
@@ -532,8 +532,8 @@ public final class UInt256 implements UInt256Value<UInt256> {
       return UInt256.ZERO;
     }
 
-    BigInteger bi = this.toBigInteger();
-    BigInteger result = bi.abs().mod(modulus.toBigInteger().abs());
+    BigInteger bi = this.toSignedBigInteger();
+    BigInteger result = bi.abs().mod(modulus.toSignedBigInteger().abs());
 
     if (bi.signum() < 0) {
       result = result.negate();
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/UInt256Value.java b/units/src/main/java/org/apache/tuweni/units/bigints/UInt256Value.java
index 7c1cc35..63d0a70 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/UInt256Value.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/UInt256Value.java
@@ -13,9 +13,14 @@
 package org.apache.tuweni.units.bigints;
 
 
+import static java.nio.ByteOrder.BIG_ENDIAN;
+
 import org.apache.tuweni.bytes.Bytes;
 import org.apache.tuweni.bytes.Bytes32;
 
+import java.math.BigInteger;
+import java.nio.ByteOrder;
+
 
 /**
  * Represents a 256-bit (32 bytes) unsigned integer value.
@@ -336,13 +341,33 @@ public interface UInt256Value<T extends UInt256Value<T>> extends Bytes32 {
    * @return True if this value fits a java {@code int} (i.e. is less or equal to {@code Integer.MAX_VALUE}).
    */
   default boolean fitsInt() {
-    // Ints are 4 bytes, so anything but the 4 last bytes must be zeroes
-    for (int i = 0; i < Bytes32.SIZE - 4; i++) {
-      if (get(i) != 0)
-        return false;
+    return fitsInt(ByteOrder.BIG_ENDIAN);
+  }
+
+  /**
+   * Returns true if the value can fit in an int according to the byte order.
+   *
+   * @param order the byte order, little or big endian
+   * @return True if this value fits a java {@code int} (i.e. is less or equal to {@code Integer.MAX_VALUE}).
+   */
+  default boolean fitsInt(ByteOrder order) {
+    if (order == ByteOrder.BIG_ENDIAN) {
+      // Ints are 4 bytes, so anything but the 4 last bytes must be zeroes
+      for (int i = 0; i < Bytes32.SIZE - 4; i++) {
+        if (get(i) != 0)
+          return false;
+      }
+      // Lastly, the left-most byte of the int must not start with a 1.
+      return get(Bytes32.SIZE - 4) >= 0;
+    } else {
+      // Ints are 4 bytes, so only the 4 first bytes must not be zeroes
+      for (int i = 4; i < Bytes32.SIZE - 4; i++) {
+        if (get(i) != 0)
+          return false;
+      }
+      // Lastly, the right-most byte of the int must not start with a 1.
+      return get(3) >= 0;
     }
-    // Lastly, the left-most byte of the int must not start with a 1.
-    return get(Bytes32.SIZE - 4) >= 0;
   }
 
   /**
@@ -358,19 +383,63 @@ public interface UInt256Value<T extends UInt256Value<T>> extends Bytes32 {
     return getInt(Bytes32.SIZE - 4);
   }
 
+  @Override
+  default int toInt(ByteOrder order) {
+    if (!fitsInt(order)) {
+      throw new ArithmeticException("Value does not fit a 4 byte int");
+    }
+    if (order == ByteOrder.BIG_ENDIAN) {
+      return getInt(Bytes32.SIZE - 4, order);
+    } else {
+      return getInt(0, order);
+    }
+  }
+
+  @Override
+  default long toLong(ByteOrder order) {
+    if (!fitsLong(order)) {
+      throw new ArithmeticException("Value does not fit a 8 byte long");
+    }
+    if (order == ByteOrder.BIG_ENDIAN) {
+      return getLong(Bytes32.SIZE - 8, order);
+    } else {
+      return getLong(0, order);
+    }
+  }
+
   /**
    * Returns true if the value can fit in a long.
    *
    * @return True if this value fits a java {@code long} (i.e. is less or equal to {@code Long.MAX_VALUE}).
    */
   default boolean fitsLong() {
-    // Longs are 8 bytes, so anything but the 8 last bytes must be zeroes
-    for (int i = 0; i < Bytes32.SIZE - 8; i++) {
-      if (get(i) != 0)
-        return false;
+    return fitsLong(ByteOrder.BIG_ENDIAN);
+  }
+
+  /**
+   * Returns true if the value can fit in a long.
+   *
+   * @param order byte order, little or big endian
+   * @return True if this value fits a java {@code long} (i.e. is less or equal to {@code Long.MAX_VALUE}).
+   */
+  default boolean fitsLong(ByteOrder order) {
+    if (order == ByteOrder.BIG_ENDIAN) {
+      // Longs are 8 bytes, so anything but the 8 last bytes must be zeroes
+      for (int i = 0; i < Bytes32.SIZE - 8; i++) {
+        if (get(i) != 0)
+          return false;
+      }
+      // Lastly, the left-most byte of the long must not start with a 1.
+      return get(Bytes32.SIZE - 8) >= 0;
+    } else {
+      // Longs are 8 bytes, so only the 8 first bytes may not be zeroes
+      for (int i = 8; i < Bytes32.SIZE; i++) {
+        if (get(i) != 0)
+          return false;
+      }
+      // Lastly, the left-most byte of the long must not start with a 1.
+      return get(7) >= 0;
     }
-    // Lastly, the left-most byte of the long must not start with a 1.
-    return get(Bytes32.SIZE - 8) >= 0;
   }
 
   /**
@@ -433,4 +502,56 @@ public interface UInt256Value<T extends UInt256Value<T>> extends Bytes32 {
   default boolean lessOrEqualThan(UInt256Value<T> other) {
     return compareTo(other) <= 0;
   }
+
+  /**
+   * Returns the decimal representation of this value as a String.
+   *
+   * @return the decimal representation of this value as a String.
+   */
+  default String toDecimalString() {
+    return toBigInteger().toString(10);
+  }
+
+  /**
+   * The BigInteger corresponding to interpreting these bytes as a two's-complement signed integer.
+   *
+   * @return A {@link BigInteger} corresponding to interpreting these bytes as a two's-complement signed integer.
+   */
+  default BigInteger toSignedBigInteger() {
+    return toSignedBigInteger(BIG_ENDIAN);
+  }
+
+  /**
+   * The BigInteger corresponding to interpreting these bytes as a two's-complement signed integer.
+   *
+   * @param order The byte-order for decoding the integer.
+   * @return A {@link BigInteger} corresponding to interpreting these bytes as a two's-complement signed integer.
+   */
+  default BigInteger toSignedBigInteger(ByteOrder order) {
+    if (size() == 0) {
+      return BigInteger.ZERO;
+    }
+    return new BigInteger((order == BIG_ENDIAN) ? toArrayUnsafe() : reverse().toArrayUnsafe());
+  }
+
+  /**
+   * The BigInteger corresponding to interpreting these bytes as an unsigned integer.
+   *
+   * @return A positive (or zero) {@link BigInteger} corresponding to interpreting these bytes as an unsigned integer.
+   */
+  @Override
+  default BigInteger toBigInteger() {
+    return toUnsignedBigInteger();
+  }
+
+  /**
+   * The BigInteger corresponding to interpreting these bytes as an unsigned integer.
+   *
+   * @param order The byte-order for decoding the integer.
+   * @return A positive (or zero) {@link BigInteger} corresponding to interpreting these bytes as an unsigned integer.
+   */
+  @Override
+  default BigInteger toBigInteger(ByteOrder order) {
+    return toUnsignedBigInteger(order);
+  }
 }
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/UInt32Value.java b/units/src/main/java/org/apache/tuweni/units/bigints/UInt32Value.java
index 72cdca8..c45b2a9 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/UInt32Value.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/UInt32Value.java
@@ -390,4 +390,13 @@ public interface UInt32Value<T extends UInt32Value<T>> extends Comparable<T> {
   default int bitLength() {
     return toBytes().bitLength();
   }
+
+  /**
+   * Returns the decimal representation of this value as a String.
+   *
+   * @return the decimal representation of this value as a String.
+   */
+  default String toDecimalString() {
+    return toBigInteger().toString(10);
+  }
 }
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/UInt384Value.java b/units/src/main/java/org/apache/tuweni/units/bigints/UInt384Value.java
index 1dd3829..62859b6 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/UInt384Value.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/UInt384Value.java
@@ -409,4 +409,13 @@ public interface UInt384Value<T extends UInt384Value<T>> extends Comparable<T> {
   default int bitLength() {
     return toBytes().bitLength();
   }
+
+  /**
+   * Returns the decimal representation of this value as a String.
+   *
+   * @return the decimal representation of this value as a String.
+   */
+  default String toDecimalString() {
+    return toBigInteger().toString(10);
+  }
 }
diff --git a/units/src/main/java/org/apache/tuweni/units/bigints/UInt64Value.java b/units/src/main/java/org/apache/tuweni/units/bigints/UInt64Value.java
index e396056..6def37a 100644
--- a/units/src/main/java/org/apache/tuweni/units/bigints/UInt64Value.java
+++ b/units/src/main/java/org/apache/tuweni/units/bigints/UInt64Value.java
@@ -403,4 +403,13 @@ public interface UInt64Value<T extends UInt64Value<T>> extends Comparable<T> {
   default int bitLength() {
     return toBytes().bitLength();
   }
+
+  /**
+   * Returns the decimal representation of this value as a String.
+   *
+   * @return the decimal representation of this value as a String.
+   */
+  default String toDecimalString() {
+    return toBigInteger().toString(10);
+  }
 }
diff --git a/units/src/test/java/org/apache/tuweni/units/bigints/UInt256Test.java b/units/src/test/java/org/apache/tuweni/units/bigints/UInt256Test.java
index 010ed5d..76b1490 100644
--- a/units/src/test/java/org/apache/tuweni/units/bigints/UInt256Test.java
+++ b/units/src/test/java/org/apache/tuweni/units/bigints/UInt256Test.java
@@ -1168,4 +1168,9 @@ class UInt256Test {
     String msg = String.format("Expected %s but got %s", expected.toHexString(), actual.toHexString());
     assertEquals(expected, actual, msg);
   }
+
+  @Test
+  void testToDecimalString() {
+    assertEquals("3456", UInt256.valueOf(3456).toDecimalString());
+  }
 }
diff --git a/units/src/test/java/org/apache/tuweni/units/bigints/UInt32Test.java b/units/src/test/java/org/apache/tuweni/units/bigints/UInt32Test.java
index c9a82bd..6fb4ace 100644
--- a/units/src/test/java/org/apache/tuweni/units/bigints/UInt32Test.java
+++ b/units/src/test/java/org/apache/tuweni/units/bigints/UInt32Test.java
@@ -863,4 +863,8 @@ class UInt32Test {
     assertEquals(4294967295L, UInt32.MAX_VALUE.toLong());
   }
 
+  @Test
+  void testToDecimalString() {
+    assertEquals("3456", UInt32.valueOf(3456).toDecimalString());
+  }
 }
diff --git a/units/src/test/java/org/apache/tuweni/units/bigints/UInt384Test.java b/units/src/test/java/org/apache/tuweni/units/bigints/UInt384Test.java
index a8f4d22..8e3957b 100644
--- a/units/src/test/java/org/apache/tuweni/units/bigints/UInt384Test.java
+++ b/units/src/test/java/org/apache/tuweni/units/bigints/UInt384Test.java
@@ -1096,4 +1096,9 @@ class UInt384Test {
     String msg = String.format("Expected %s but got %s", expected.toHexString(), actual.toHexString());
     assertEquals(expected, actual, msg);
   }
+
+  @Test
+  void testToDecimalString() {
+    assertEquals("3456", UInt384.valueOf(3456).toDecimalString());
+  }
 }
diff --git a/units/src/test/java/org/apache/tuweni/units/bigints/UInt64Test.java b/units/src/test/java/org/apache/tuweni/units/bigints/UInt64Test.java
index 8d64fb3..bbfc7e3 100644
--- a/units/src/test/java/org/apache/tuweni/units/bigints/UInt64Test.java
+++ b/units/src/test/java/org/apache/tuweni/units/bigints/UInt64Test.java
@@ -848,4 +848,9 @@ class UInt64Test {
     String msg = String.format("Expected %s but got %s", expected.toHexString(), actual.toHexString());
     assertEquals(expected, actual, msg);
   }
+
+  @Test
+  void testToDecimalString() {
+    assertEquals("3456", UInt64.valueOf(3456).toDecimalString());
+  }
 }
diff --git a/units/src/test/java/org/apache/tuweni/units/ethereum/WeiTest.java b/units/src/test/java/org/apache/tuweni/units/ethereum/WeiTest.java
index e056867..f9113d9 100644
--- a/units/src/test/java/org/apache/tuweni/units/ethereum/WeiTest.java
+++ b/units/src/test/java/org/apache/tuweni/units/ethereum/WeiTest.java
@@ -16,6 +16,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.tuweni.units.bigints.UInt256;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -65,4 +68,21 @@ class WeiTest {
   void testFromEth() {
     assertEquals(Wei.valueOf((long) Math.pow(10, 18)), Wei.fromEth(1));
   }
+
+  @Test
+  void testToInt() {
+    assertTrue(Wei.valueOf(100L).fitsInt());
+    assertEquals(100, Wei.valueOf(100L).toInt());
+  }
+
+  @Test
+  void testToLong() {
+    assertTrue(Wei.valueOf(100L).fitsLong());
+    assertEquals(100L, Wei.valueOf(100L).toLong());
+  }
+
+  @Test
+  void toBigIntegerIsPositive() {
+    assertEquals(1, Wei.valueOf(UInt256.MAX_VALUE).toBigInteger().signum());
+  }
 }

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tuweni.apache.org
For additional commands, e-mail: commits-help@tuweni.apache.org