Skip to content

Commit a091237

Browse files
FIX: ModOperations use UInt256
Signed-off-by: Thomas Zamojski <thomas.zamojski@quadratic-labs.com>
1 parent 0b9d5b2 commit a091237

File tree

6 files changed

+58
-81
lines changed

6 files changed

+58
-81
lines changed

evm/src/main/java/org/hyperledger/besu/evm/UInt256.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
package org.hyperledger.besu.evm;
1616

17+
import java.math.BigInteger;
1718
import java.nio.ByteBuffer;
1819
import java.nio.ByteOrder;
1920
import java.util.Arrays;
@@ -170,6 +171,15 @@ public byte[] toBytesBE() {
170171
return buf.array();
171172
}
172173

174+
/**
175+
* Convert to BigInteger.
176+
*
177+
* @return BigInteger representing the integer.
178+
*/
179+
public BigInteger toBigInteger() {
180+
return new BigInteger(1, toBytesBE());
181+
}
182+
173183
@Override
174184
public String toString() {
175185
StringBuilder sb = new StringBuilder("0x");
@@ -276,7 +286,7 @@ public UInt256 shiftLeft(final int shift) {
276286
*/
277287
public UInt256 shiftRight(final int shift) {
278288
if (shift < 0) return shiftLeft(-shift);
279-
if (shift >= BITSIZE) return ZERO;
289+
if (shift >= length * N_BITS_PER_LIMB) return ZERO;
280290
if (shift == 0 || isZero()) return this;
281291
int[] shifted = new int[N_LIMBS];
282292
shiftRightInto(shifted, this.limbs, this.length, shift);

evm/src/main/java/org/hyperledger/besu/evm/operation/AddModOperation.java

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
package org.hyperledger.besu.evm.operation;
1616

1717
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
1819
import org.hyperledger.besu.evm.frame.MessageFrame;
1920
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
2021

21-
import java.math.BigInteger;
22-
import java.util.Arrays;
23-
2422
import org.apache.tuweni.bytes.Bytes;
2523

2624
/** The Add mod operation. */
@@ -50,29 +48,22 @@ public Operation.OperationResult executeFixedCostOperation(
5048
* @return the operation result
5149
*/
5250
public static OperationResult staticOperation(final MessageFrame frame) {
51+
Bytes resultBytes;
5352

5453
final Bytes value0 = frame.popStackItem();
5554
final Bytes value1 = frame.popStackItem();
5655
final Bytes value2 = frame.popStackItem();
5756

5857
if (value2.isZero()) {
59-
frame.pushStackItem(Bytes.EMPTY);
58+
resultBytes = Bytes.EMPTY;
6059
} else {
61-
BigInteger b0 = new BigInteger(1, value0.toArrayUnsafe());
62-
BigInteger b1 = new BigInteger(1, value1.toArrayUnsafe());
63-
BigInteger b2 = new BigInteger(1, value2.toArrayUnsafe());
64-
65-
BigInteger result = b0.add(b1).mod(b2);
66-
Bytes resultBytes = Bytes.wrap(result.toByteArray());
67-
if (resultBytes.size() > 32) {
68-
resultBytes = resultBytes.slice(resultBytes.size() - 32, 32);
69-
}
70-
71-
final byte[] padding = new byte[32 - resultBytes.size()];
72-
Arrays.fill(padding, result.signum() < 0 ? (byte) 0xFF : 0x00);
73-
74-
frame.pushStackItem(Bytes.concatenate(Bytes.wrap(padding), resultBytes));
60+
UInt256 b0 = UInt256.fromBytesBE(value0.toArrayUnsafe());
61+
UInt256 b1 = UInt256.fromBytesBE(value1.toArrayUnsafe());
62+
UInt256 b2 = UInt256.fromBytesBE(value2.toArrayUnsafe());
63+
resultBytes = Bytes.wrap(b0.addMod(b1, b2).toBytesBE());
7564
}
65+
66+
frame.pushStackItem(resultBytes);
7667
return addModSuccess;
7768
}
7869
}

evm/src/main/java/org/hyperledger/besu/evm/operation/ModOperation.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
package org.hyperledger.besu.evm.operation;
1616

1717
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
1819
import org.hyperledger.besu.evm.frame.MessageFrame;
1920
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
2021

21-
import java.math.BigInteger;
22-
import java.util.Arrays;
23-
2422
import org.apache.tuweni.bytes.Bytes;
2523
import org.apache.tuweni.bytes.Bytes32;
2624

@@ -53,24 +51,15 @@ public Operation.OperationResult executeFixedCostOperation(
5351
public static OperationResult staticOperation(final MessageFrame frame) {
5452
final Bytes value0 = frame.popStackItem();
5553
final Bytes value1 = frame.popStackItem();
54+
Bytes resultBytes;
5655
if (value1.isZero()) {
57-
frame.pushStackItem(Bytes32.ZERO);
56+
resultBytes = (Bytes) Bytes32.ZERO;
5857
} else {
59-
BigInteger b1 = new BigInteger(1, value0.toArrayUnsafe());
60-
BigInteger b2 = new BigInteger(1, value1.toArrayUnsafe());
61-
final BigInteger result = b1.mod(b2);
62-
63-
Bytes resultBytes = Bytes.wrap(result.toByteArray());
64-
if (resultBytes.size() > 32) {
65-
resultBytes = resultBytes.slice(resultBytes.size() - 32, 32);
66-
}
67-
68-
final byte[] padding = new byte[32 - resultBytes.size()];
69-
Arrays.fill(padding, result.signum() < 0 ? (byte) 0xFF : 0x00);
70-
71-
frame.pushStackItem(Bytes.concatenate(Bytes.wrap(padding), resultBytes));
58+
UInt256 b0 = UInt256.fromBytesBE(value0.toArrayUnsafe());
59+
UInt256 b1 = UInt256.fromBytesBE(value1.toArrayUnsafe());
60+
resultBytes = Bytes.wrap(b0.mod(b1).toBytesBE());
7261
}
73-
62+
frame.pushStackItem(resultBytes);
7463
return modSuccess;
7564
}
7665
}

evm/src/main/java/org/hyperledger/besu/evm/operation/MulModOperation.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
package org.hyperledger.besu.evm.operation;
1616

1717
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
1819
import org.hyperledger.besu.evm.frame.MessageFrame;
1920
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
2021

21-
import java.math.BigInteger;
22-
import java.util.Arrays;
23-
2422
import org.apache.tuweni.bytes.Bytes;
2523

2624
/** The Mul mod operation. */
@@ -54,25 +52,17 @@ public static OperationResult staticOperation(final MessageFrame frame) {
5452
final Bytes value1 = frame.popStackItem();
5553
final Bytes value2 = frame.popStackItem();
5654

55+
Bytes resultBytes;
5756
if (value2.isZero()) {
58-
frame.pushStackItem(Bytes.EMPTY);
57+
resultBytes = Bytes.EMPTY;
5958
} else {
60-
BigInteger b0 = new BigInteger(1, value0.toArrayUnsafe());
61-
BigInteger b1 = new BigInteger(1, value1.toArrayUnsafe());
62-
BigInteger b2 = new BigInteger(1, value2.toArrayUnsafe());
63-
64-
BigInteger result = b0.multiply(b1).mod(b2);
65-
Bytes resultBytes = Bytes.wrap(result.toByteArray());
66-
if (resultBytes.size() > 32) {
67-
resultBytes = resultBytes.slice(resultBytes.size() - 32, 32);
68-
}
69-
70-
final byte[] padding = new byte[32 - resultBytes.size()];
71-
Arrays.fill(padding, result.signum() < 0 ? (byte) 0xFF : 0x00);
72-
73-
frame.pushStackItem(Bytes.concatenate(Bytes.wrap(padding), resultBytes));
59+
UInt256 b0 = UInt256.fromBytesBE(value0.toArrayUnsafe());
60+
UInt256 b1 = UInt256.fromBytesBE(value1.toArrayUnsafe());
61+
UInt256 b2 = UInt256.fromBytesBE(value2.toArrayUnsafe());
62+
resultBytes = Bytes.wrap(b0.mulMod(b1, b2).toBytesBE());
7463
}
7564

65+
frame.pushStackItem(resultBytes);
7666
return mulModSuccess;
7767
}
7868
}

evm/src/main/java/org/hyperledger/besu/evm/operation/SModOperation.java

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515
package org.hyperledger.besu.evm.operation;
1616

1717
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
1819
import org.hyperledger.besu.evm.frame.MessageFrame;
1920
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
2021

21-
import java.math.BigInteger;
22-
import java.util.Arrays;
23-
2422
import org.apache.tuweni.bytes.Bytes;
23+
import org.apache.tuweni.bytes.Bytes32;
2524

2625
/** The SMod operation. */
2726
public class SModOperation extends AbstractFixedCostOperation {
@@ -53,32 +52,15 @@ public static OperationResult staticOperation(final MessageFrame frame) {
5352
final Bytes value0 = frame.popStackItem();
5453
final Bytes value1 = frame.popStackItem();
5554

55+
Bytes resultBytes;
5656
if (value1.isZero()) {
57-
frame.pushStackItem(Bytes.EMPTY);
57+
resultBytes = (Bytes) Bytes32.ZERO;
5858
} else {
59-
final BigInteger b1 =
60-
value0.size() < 32
61-
? new BigInteger(1, value0.toArrayUnsafe())
62-
: new BigInteger(value0.toArrayUnsafe());
63-
final BigInteger b2 =
64-
value1.size() < 32
65-
? new BigInteger(1, value1.toArrayUnsafe())
66-
: new BigInteger(value1.toArrayUnsafe());
67-
BigInteger result = b1.abs().mod(b2.abs());
68-
if (b1.signum() < 0) {
69-
result = result.negate();
70-
}
71-
72-
Bytes resultBytes = Bytes.wrap(result.toByteArray());
73-
if (resultBytes.size() > 32) {
74-
resultBytes = resultBytes.slice(resultBytes.size() - 32, 32);
75-
}
76-
77-
final byte[] padding = new byte[32 - resultBytes.size()];
78-
Arrays.fill(padding, result.signum() < 0 ? (byte) 0xFF : 0x00);
79-
80-
frame.pushStackItem(Bytes.concatenate(Bytes.wrap(padding), resultBytes));
59+
UInt256 b0 = UInt256.fromBytesBE(value0.toArrayUnsafe());
60+
UInt256 b1 = UInt256.fromBytesBE(value1.toArrayUnsafe());
61+
resultBytes = Bytes.wrap(b0.signedMod(b1).toBytesBE());
8162
}
63+
frame.pushStackItem(resultBytes);
8264

8365
return smodSuccess;
8466
}

evm/src/test/java/org/hyperledger/besu/evm/UInt256Test.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ public void fromToBytesBE() {
109109
assertThat(asUint.toBytesBE()).isEqualTo(asBigInt.toByteArray());
110110
}
111111

112+
@Test
113+
void testRightShiftCase() {
114+
final BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
115+
int shift = 33;
116+
117+
final BigInteger TWO_TO_256 = BigInteger.valueOf(2).pow(256);
118+
BigInteger expectedUnwrapped = maxLong.shiftRight(shift);
119+
BigInteger expected = expectedUnwrapped.mod(TWO_TO_256);
120+
121+
UInt256 uint256 = UInt256.fromBytesBE(maxLong.toByteArray());
122+
123+
UInt256 result = uint256.shiftRight(shift);
124+
assertThat(result.toBigInteger()).isEqualTo(expected);
125+
}
126+
112127
@Test
113128
public void smallInts() {
114129
UInt256 number = UInt256.fromInt(523);

0 commit comments

Comments
 (0)