diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListDecoder.java index 6cf09718be8..21caf98f643 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListDecoder.java @@ -56,7 +56,7 @@ public static BlockAccessList decode(final RLPInput in) { scIn.readList( changeIn -> { changeIn.enterList(); - int txIndex = changeIn.readIntScalar(); + long txIndex = changeIn.readUnsignedIntScalar(); UInt256 newVal = UInt256.fromBytes(changeIn.readBytes()); changeIn.leaveList(); return new StorageChange(txIndex, newVal); @@ -72,7 +72,7 @@ public static BlockAccessList decode(final RLPInput in) { acctIn.readList( bcIn -> { bcIn.enterList(); - int txIndex = bcIn.readIntScalar(); + long txIndex = bcIn.readUnsignedIntScalar(); Wei postBalance = Wei.of(UInt256.fromBytes(bcIn.readBytes())); bcIn.leaveList(); return new BalanceChange(txIndex, postBalance); @@ -82,7 +82,7 @@ public static BlockAccessList decode(final RLPInput in) { acctIn.readList( ncIn -> { ncIn.enterList(); - int txIndex = ncIn.readIntScalar(); + long txIndex = ncIn.readUnsignedIntScalar(); long newNonce = ncIn.readLongScalar(); ncIn.leaveList(); return new NonceChange(txIndex, newNonce); @@ -92,7 +92,7 @@ public static BlockAccessList decode(final RLPInput in) { acctIn.readList( ccIn -> { ccIn.enterList(); - int txIndex = ccIn.readIntScalar(); + long txIndex = ccIn.readUnsignedIntScalar(); Bytes newCode = ccIn.readBytes(); ccIn.leaveList(); return new CodeChange(txIndex, newCode); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListEncoder.java index 1013da998a3..b5d6695ec2c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlockAccessListEncoder.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.ethereum.rlp.RLPOutput; import org.apache.tuweni.units.bigints.UInt256; -import org.apache.tuweni.units.bigints.UInt64; public final class BlockAccessListEncoder { @@ -40,7 +39,7 @@ public static void encode(final BlockAccessList bal, final RLPOutput out) { sc.changes(), (chg, chgOut) -> { chgOut.startList(); - chgOut.writeUInt64Scalar(UInt64.valueOf(chg.txIndex())); + chgOut.writeUnsignedInt(chg.txIndex()); chgOut.writeUInt256Scalar(chg.newValue()); chgOut.endList(); }); @@ -55,7 +54,7 @@ public static void encode(final BlockAccessList bal, final RLPOutput out) { acct.balanceChanges(), (bc, bcOut) -> { bcOut.startList(); - bcOut.writeUInt64Scalar(UInt64.valueOf(bc.txIndex())); + bcOut.writeUnsignedInt(bc.txIndex()); bcOut.writeUInt256Scalar(UInt256.fromBytes(bc.postBalance())); bcOut.endList(); }); @@ -64,7 +63,7 @@ public static void encode(final BlockAccessList bal, final RLPOutput out) { acct.nonceChanges(), (nc, ncOut) -> { ncOut.startList(); - ncOut.writeUInt64Scalar(UInt64.valueOf(nc.txIndex())); + ncOut.writeUnsignedInt(nc.txIndex()); ncOut.writeLongScalar(nc.newNonce()); ncOut.endList(); }); @@ -73,7 +72,7 @@ public static void encode(final BlockAccessList bal, final RLPOutput out) { acct.codeChanges(), (cc, ccOut) -> { ccOut.startList(); - ccOut.writeUInt64Scalar(UInt64.valueOf(cc.txIndex())); + ccOut.writeUnsignedInt(cc.txIndex()); ccOut.writeBytes(cc.newCode()); ccOut.endList(); }); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockAccessListValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockAccessListValidator.java index 6df150a15cf..d70d0a27d2f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockAccessListValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockAccessListValidator.java @@ -116,7 +116,7 @@ public boolean validate( } } - final int maxIndex = nbTransactions + 1; + final long maxIndex = (long) nbTransactions + 1L; if (!validateConstraints(bal, blockHeader, maxIndex)) { return false; } @@ -130,7 +130,7 @@ public boolean validate( * overlap with storage_reads. */ private boolean validateConstraints( - final BlockAccessList bal, final BlockHeader blockHeader, final int maxIndex) { + final BlockAccessList bal, final BlockHeader blockHeader, final long maxIndex) { Address prevAddress = null; for (BlockAccessList.AccountChanges account : bal.accountChanges()) { @@ -145,7 +145,7 @@ private boolean validateConstraints( final Set changeSlots = new HashSet<>(account.storageChanges().size()); StorageSlotKey prevStorageSlot = null; - int prevStorageTxIndex = -1; + long prevStorageTxIndex = -1L; for (BlockAccessList.SlotChanges slotChanges : account.storageChanges()) { final StorageSlotKey slot = slotChanges.slot(); @@ -160,9 +160,9 @@ && compareSlotKeysByCanonicalOrder(prevStorageSlot, slot) >= 0) { prevStorageSlot = slot; changeSlots.add(slot); - prevStorageTxIndex = -1; + prevStorageTxIndex = -1L; for (BlockAccessList.StorageChange ch : slotChanges.changes()) { - final int txIndex = ch.txIndex(); + final long txIndex = ch.txIndex(); if (txIndex < 0) { LOG.warn( "Block access list has negative block_access_index for address {} block {}", @@ -209,9 +209,9 @@ && compareSlotKeysByCanonicalOrder(prevStorageSlot, slot) >= 0) { } } - int prevTxIndex = -1; + long prevTxIndex = -1L; for (BlockAccessList.BalanceChange ch : account.balanceChanges()) { - final int txIndex = ch.txIndex(); + final long txIndex = ch.txIndex(); if (txIndex < 0) { LOG.warn( "Block access list has negative block_access_index in balance_changes for address {} block {}", @@ -237,9 +237,9 @@ && compareSlotKeysByCanonicalOrder(prevStorageSlot, slot) >= 0) { prevTxIndex = txIndex; } - prevTxIndex = -1; + prevTxIndex = -1L; for (BlockAccessList.NonceChange ch : account.nonceChanges()) { - final int txIndex = ch.txIndex(); + final long txIndex = ch.txIndex(); if (txIndex < 0) { LOG.warn( "Block access list has negative block_access_index in nonce_changes for address {} block {}", @@ -265,9 +265,9 @@ && compareSlotKeysByCanonicalOrder(prevStorageSlot, slot) >= 0) { prevTxIndex = txIndex; } - prevTxIndex = -1; + prevTxIndex = -1L; for (BlockAccessList.CodeChange ch : account.codeChanges()) { - final int txIndex = ch.txIndex(); + final long txIndex = ch.txIndex(); if (txIndex < 0) { LOG.warn( "Block access list has negative block_access_index in code_changes for address {} block {}", diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/AccessLocationTracker.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/AccessLocationTracker.java index 6d76cb2fbdc..59fbd713887 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/AccessLocationTracker.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/AccessLocationTracker.java @@ -37,10 +37,10 @@ public class AccessLocationTracker implements Eip7928AccessList { - private final int blockAccessIndex; + private final long blockAccessIndex; private final Map touchedAccounts = new ConcurrentHashMap<>(); - public AccessLocationTracker(final int blockAccessIndex) { + public AccessLocationTracker(final long blockAccessIndex) { this.blockAccessIndex = blockAccessIndex; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/BlockAccessList.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/BlockAccessList.java index fa6dc945987..97d776453f9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/BlockAccessList.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/BlockAccessList.java @@ -72,28 +72,28 @@ public String toString() { return "BlockAccessList{" + "accountChanges=" + accountChanges + '}'; } - public record StorageChange(int txIndex, UInt256 newValue) { + public record StorageChange(long txIndex, UInt256 newValue) { @Override public String toString() { return "StorageChange{txIndex=" + txIndex + ", newValue=" + newValue + '}'; } } - public record BalanceChange(int txIndex, Wei postBalance) { + public record BalanceChange(long txIndex, Wei postBalance) { @Override public String toString() { return "BalanceChange{txIndex=" + txIndex + ", postBalance=" + postBalance + '}'; } } - public record NonceChange(int txIndex, long newNonce) { + public record NonceChange(long txIndex, long newNonce) { @Override public String toString() { return "NonceChange{txIndex=" + txIndex + ", newNonce=" + newNonce + '}'; } } - public record CodeChange(int txIndex, Bytes newCode) { + public record CodeChange(long txIndex, Bytes newCode) { @Override public String toString() { return "CodeChange{txIndex=" + txIndex + ", newCode=" + newCode + '}'; @@ -157,12 +157,12 @@ public static AccessLocationTracker createPreExecutionAccessLocationTracker() { public static AccessLocationTracker createPostExecutionAccessLocationTracker( final int numberOfTransactions) { - return new AccessLocationTracker(numberOfTransactions + 1); + return new AccessLocationTracker((long) numberOfTransactions + 1L); } public static AccessLocationTracker createTransactionAccessLocationTracker( final int transactionLocation) { - return new AccessLocationTracker(transactionLocation + 1); + return new AccessLocationTracker((long) transactionLocation + 1L); } public AccountBuilder getOrCreateAccountBuilder(final Address address) { @@ -281,7 +281,7 @@ Optional getLastCode() { } } - void addStorageWrite(final StorageSlotKey slot, final int txIndex, final UInt256 value) { + void addStorageWrite(final StorageSlotKey slot, final long txIndex, final UInt256 value) { final List changes = slotWrites.computeIfAbsent(slot, __ -> new ArrayList<>()); slotReads.remove(slot); @@ -294,15 +294,15 @@ void addStorageRead(final StorageSlotKey slot) { } } - void addBalanceChange(final int txIndex, final Wei postBalance) { + void addBalanceChange(final long txIndex, final Wei postBalance) { balances.add(new BalanceChange(txIndex, postBalance)); } - void addNonceChange(final int txIndex, final long newNonce) { + void addNonceChange(final long txIndex, final long newNonce) { nonces.add(new NonceChange(txIndex, newNonce)); } - void addCodeChange(final int txIndex, final Bytes code) { + void addCodeChange(final long txIndex, final Bytes code) { codes.add(new CodeChange(txIndex, code)); } @@ -315,7 +315,7 @@ AccountChanges build() { new SlotChanges( e.getKey(), e.getValue().stream() - .sorted(Comparator.comparingInt(StorageChange::txIndex)) + .sorted(Comparator.comparingLong(StorageChange::txIndex)) .collect(Collectors.toList()))) .collect(Collectors.toList()); @@ -330,7 +330,7 @@ AccountChanges build() { slotChanges, reads, balances.stream().sorted(Comparator.comparingLong(BalanceChange::txIndex)).toList(), - nonces.stream().sorted(Comparator.comparingDouble(NonceChange::txIndex)).toList(), + nonces.stream().sorted(Comparator.comparingLong(NonceChange::txIndex)).toList(), codes.stream().sorted(Comparator.comparingLong(CodeChange::txIndex)).toList()); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/PartialBlockAccessView.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/PartialBlockAccessView.java index 4520d514e14..7932510fe08 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/PartialBlockAccessView.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/PartialBlockAccessView.java @@ -48,10 +48,10 @@ */ public final class PartialBlockAccessView { - private final int txIndex; + private final long txIndex; private final List accountChanges; - public PartialBlockAccessView(final List accountChanges, final int txIndex) { + public PartialBlockAccessView(final List accountChanges, final long txIndex) { this.accountChanges = accountChanges; this.txIndex = txIndex; } @@ -66,7 +66,7 @@ public String toString() { + '}'; } - public int getTxIndex() { + public long getTxIndex() { return txIndex; } @@ -166,10 +166,10 @@ public String toString() { /** Builder for PartialBlockAccessView. */ public static class PartialBlockAccessViewBuilder { - private int txIndex; + private long txIndex; private final Map accountBuilders = new HashMap<>(); - public PartialBlockAccessViewBuilder withTxIndex(final int txIndex) { + public PartialBlockAccessViewBuilder withTxIndex(final long txIndex) { this.txIndex = txIndex; return this; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/BalConcurrentTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/BalConcurrentTransactionProcessor.java index afcfa1a30e9..50d91824e6a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/BalConcurrentTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/BalConcurrentTransactionProcessor.java @@ -95,7 +95,8 @@ protected ParallelizedTransactionContext runTransaction( final PathBasedWorldStateUpdateAccumulator blockUpdater = (PathBasedWorldStateUpdateAccumulator) ws.updater(); - applyWritesFromPriorTransactions(blockAccessList, transactionLocation + 1, blockUpdater); + applyWritesFromPriorTransactions( + blockAccessList, (long) transactionLocation + 1L, blockUpdater); blockUpdater.commit(); final WorldUpdater txUpdater = blockUpdater.updater(); @@ -185,7 +186,7 @@ public Optional getProcessingResult( private void applyWritesFromPriorTransactions( final BlockAccessList blockAccessList, - final int balIndex, + final long balIndex, final PathBasedWorldStateUpdateAccumulator worldStateUpdater) { for (var accountChanges : blockAccessList.accountChanges()) { final Address address = accountChanges.address(); @@ -232,11 +233,11 @@ private void applyWritesFromPriorTransactions( } private BlockAccessList.BalanceChange findLatestBalanceChange( - final Collection changes, final int maxIndex) { + final Collection changes, final long maxIndex) { BlockAccessList.BalanceChange latest = null; - int latestIndex = -1; + long latestIndex = -1L; for (var change : changes) { - final int txIndex = change.txIndex(); + final long txIndex = change.txIndex(); if (txIndex < maxIndex && txIndex > latestIndex) { latest = change; latestIndex = txIndex; @@ -246,11 +247,11 @@ private BlockAccessList.BalanceChange findLatestBalanceChange( } private BlockAccessList.NonceChange findLatestNonceChange( - final Collection changes, final int maxIndex) { + final Collection changes, final long maxIndex) { BlockAccessList.NonceChange latest = null; - int latestIndex = -1; + long latestIndex = -1L; for (var change : changes) { - final int txIndex = change.txIndex(); + final long txIndex = change.txIndex(); if (txIndex < maxIndex && txIndex > latestIndex) { latest = change; latestIndex = txIndex; @@ -260,11 +261,11 @@ private BlockAccessList.NonceChange findLatestNonceChange( } private BlockAccessList.CodeChange findLatestCodeChange( - final Collection changes, final int maxIndex) { + final Collection changes, final long maxIndex) { BlockAccessList.CodeChange latest = null; - int latestIndex = -1; + long latestIndex = -1L; for (var change : changes) { - final int txIndex = change.txIndex(); + final long txIndex = change.txIndex(); if (txIndex < maxIndex && txIndex > latestIndex) { latest = change; latestIndex = txIndex; @@ -274,11 +275,11 @@ private BlockAccessList.CodeChange findLatestCodeChange( } private BlockAccessList.StorageChange findLatestStorageChange( - final Collection changes, final int maxIndex) { + final Collection changes, final long maxIndex) { BlockAccessList.StorageChange latest = null; - int latestIndex = -1; + long latestIndex = -1L; for (var change : changes) { - final int txIndex = change.txIndex(); + final long txIndex = change.txIndex(); if (txIndex < maxIndex && txIndex > latestIndex) { latest = change; latestIndex = txIndex; diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java index 25b1f2d5f2b..f49fa81a185 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java @@ -860,7 +860,7 @@ private BlockAccessList.SlotChanges slotChanges(final int txIndex) { final List changes = new ArrayList<>(); for (int i = 0; i < changeCount; i++) { - changes.add(new BlockAccessList.StorageChange(txIndex + i, uint256())); + changes.add(new BlockAccessList.StorageChange((long) txIndex + i, uint256())); } return new BlockAccessList.SlotChanges(slot, changes); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionEncoderTest.java index 754004811a0..ed3bdf3c0bd 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionEncoderTest.java @@ -33,10 +33,13 @@ import java.util.List; import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; import org.junit.jupiter.api.Test; public class AccessListTransactionEncoderTest { + private static final long UINT32_MAX = 0xFFFF_FFFFL; + @Test void shouldEncodeAndDecodeAccessListWithAllFields() { final Address address = Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); @@ -100,4 +103,33 @@ void shouldEncodeAndDecodeAccessListWithEmptyAccountChanges() { assertThat(decoded.accountChanges()).isEmpty(); } + + @Test + void shouldRoundTripMaxUint32BlockAccessIndex() { + final Address address = Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); + final StorageSlotKey slotKey = new StorageSlotKey(Wei.ONE.toUInt256()); + final AccountChanges accountChanges = + new AccountChanges( + address, + List.of( + new SlotChanges( + slotKey, List.of(new StorageChange(UINT32_MAX, UInt256.valueOf(1))))), + List.of(), + List.of(new BalanceChange(UINT32_MAX, Wei.ONE)), + List.of(new NonceChange(UINT32_MAX, 1L)), + List.of(new CodeChange(UINT32_MAX, Bytes.EMPTY))); + + final BlockAccessList original = new BlockAccessList(List.of(accountChanges)); + final BytesValueRLPOutput output = new BytesValueRLPOutput(); + BlockAccessListEncoder.encode(original, output); + final BlockAccessList decoded = + BlockAccessListDecoder.decode(new BytesValueRLPInput(output.encoded(), false)); + + final AccountChanges decodedAcct = decoded.accountChanges().get(0); + assertThat(decodedAcct.storageChanges().getFirst().changes().getFirst().txIndex()) + .isEqualTo(UINT32_MAX); + assertThat(decodedAcct.balanceChanges().getFirst().txIndex()).isEqualTo(UINT32_MAX); + assertThat(decodedAcct.nonceChanges().getFirst().txIndex()).isEqualTo(UINT32_MAX); + assertThat(decodedAcct.codeChanges().getFirst().txIndex()).isEqualTo(UINT32_MAX); + } } diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/AccountChangesJson.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/AccountChangesJson.java index 4c3fd8f42b0..992143f27d5 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/AccountChangesJson.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/AccountChangesJson.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.List; +import java.util.Locale; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -179,7 +180,14 @@ public CodeChange toCodeChange() { } } - private static int decodeIndex(final String index) { - return index != null ? Integer.decode(index) : 0; + private static long decodeIndex(final String index) { + if (index == null) { + return 0L; + } + final String s = index.toLowerCase(Locale.ROOT); + if (s.startsWith("0x")) { + return Long.parseUnsignedLong(s.substring(2), 16); + } + return Long.parseUnsignedLong(index, 10); } }