diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationResult.java index 01395d37c1b..fa7115065bc 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationResult.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationResult.java @@ -14,13 +14,13 @@ */ package org.hyperledger.besu.ethereum.mainnet; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.Address; +import java.util.HashSet; import java.util.Set; public class CodeDelegationResult { - private final Set
accessedDelegatorAddresses = new BytesTrieSet<>(Address.SIZE); + private final Set
accessedDelegatorAddresses = new HashSet<>(Address.SIZE); private long alreadyExistingDelegators = 0L; public void addAccessedDelegatorAddress(final Address address) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 36adcd9d117..a0a46df4a0d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -18,7 +18,6 @@ import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.getTarget; import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -49,6 +48,7 @@ import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Deque; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -232,7 +232,7 @@ public TransactionProcessingResult processTransaction( operationTracer.tracePrepareTransaction(worldState, transaction); - final Set
eip2930WarmAddressList = new BytesTrieSet<>(Address.SIZE); + final Set
eip2930WarmAddressList = new HashSet<>(Address.SIZE); final long previousNonce = sender.incrementNonce(); LOG.trace( diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index 1e372194aff..ae583456115 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -19,7 +19,6 @@ import static picocli.CommandLine.ScopeType.INHERIT; import org.hyperledger.besu.cli.config.NetworkName; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -54,6 +53,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Deque; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -465,7 +465,7 @@ public void run() { var contractAccount = updater.getOrCreate(contract); contractAccount.setCode(codeBytes); - final Set
addressList = new BytesTrieSet<>(Address.SIZE); + final Set
addressList = new HashSet<>(Address.SIZE); addressList.add(sender); addressList.add(contract); if (EvmSpecVersion.SHANGHAI.compareTo(evm.getEvmVersion()) <= 0) { diff --git a/evm/src/main/java/org/hyperledger/besu/collections/trie/BytesTrieSet.java b/evm/src/main/java/org/hyperledger/besu/collections/trie/BytesTrieSet.java deleted file mode 100644 index ffcdd763713..00000000000 --- a/evm/src/main/java/org/hyperledger/besu/collections/trie/BytesTrieSet.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.collections.trie; - -import java.util.AbstractSet; -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; - -import org.apache.tuweni.bytes.Bytes; - -/** - * A Bytes optimized set that stores values in a trie by byte - * - * @param Type of trie - */ -public class BytesTrieSet extends AbstractSet { - - record Node(byte[] leafArray, E leafObject, Node[] children) { - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (!(o instanceof Node node)) return false; - return Arrays.equals(leafArray, node.leafArray) - && Objects.equals(leafObject, node.leafObject) - && Arrays.equals(children, node.children); - } - - @Override - public int hashCode() { - int result = Objects.hash(leafObject); - result = 31 * result + Arrays.hashCode(leafArray); - result = 31 * result + Arrays.hashCode(children); - return result; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("Node{"); - sb.append("leaf="); - if (leafObject == null) sb.append("null"); - else { - sb.append('['); - sb.append(leafObject.toHexString()); - sb.append(']'); - } - sb.append(", children="); - if (children == null) sb.append("null"); - else { - sb.append('['); - for (int i = 0; i < children.length; ++i) { - if (children[i] == null) { - continue; - } - sb.append(i == 0 ? "" : ", ").append(i).append("=").append(children[i]); - } - sb.append(']'); - } - sb.append('}'); - return sb.toString(); - } - } - - Node root; - - int size = 0; - final int byteLength; - - /** - * Create a BytesTrieSet with a fixed length - * - * @param byteLength length in bytes of the stored types - */ - public BytesTrieSet(final int byteLength) { - this.byteLength = byteLength; - } - - static class NodeWalker { - final Node node; - int lastRead; - - NodeWalker(final Node node) { - this.node = node; - this.lastRead = -1; - } - - NodeWalker nextNodeWalker() { - if (node.children == null) { - return null; - } - while (lastRead < 255) { - lastRead++; - Node child = node.children[lastRead]; - if (child != null) { - return new NodeWalker<>(child); - } - } - return null; - } - - E thisNode() { - return node.leafObject; - } - } - - @Override - public Iterator iterator() { - var result = - new Iterator() { - final Deque> stack = new ArrayDeque<>(); - E next; - E last; - - @Override - public boolean hasNext() { - return next != null; - } - - @Override - public E next() { - if (next == null) { - throw new NoSuchElementException(); - } - last = next; - advance(); - return last; - } - - @Override - public void remove() { - BytesTrieSet.this.remove(last); - } - - void advance() { - while (!stack.isEmpty()) { - NodeWalker thisStep = stack.peek(); - var nextStep = thisStep.nextNodeWalker(); - if (nextStep == null) { - stack.pop(); - if (thisStep.thisNode() != null) { - next = thisStep.thisNode(); - return; - } - } else { - stack.push(nextStep); - } - } - next = null; - } - }; - if (root != null) { - result.stack.add(new NodeWalker<>(root)); - } - result.advance(); - return result; - } - - @Override - public int size() { - return size; - } - - @Override - public boolean contains(final Object o) { - if (!(o instanceof Bytes bytes)) { - throw new IllegalArgumentException( - "Expected Bytes, got " + (o == null ? "null" : o.getClass().getName())); - } - byte[] array = bytes.toArrayUnsafe(); - if (array.length != byteLength) { - throw new IllegalArgumentException( - "Byte array is size " + array.length + " but set is size " + byteLength); - } - if (root == null) { - return false; - } - int level = 0; - Node current = root; - while (current != null) { - if (current.leafObject != null) { - return Arrays.compare(current.leafArray, array) == 0; - } - current = current.children[array[level] & 0xff]; - level++; - } - return false; - } - - @Override - public boolean remove(final Object o) { - // Two base cases, size==0 and size==1; - if (!(o instanceof Bytes bytes)) { - throw new IllegalArgumentException( - "Expected Bytes, got " + (o == null ? "null" : o.getClass().getName())); - } - byte[] array = bytes.toArrayUnsafe(); - if (array.length != byteLength) { - throw new IllegalArgumentException( - "Byte array is size " + array.length + " but set is size " + byteLength); - } - // Two base cases, size==0 and size==1; - if (root == null) { - // size==0 is easy, empty - return false; - } - if (root.leafObject != null) { - // size==1 just check and possibly remove the root - if (Arrays.compare(array, root.leafArray) == 0) { - root = null; - size--; - return true; - } else { - return false; - } - } - int level = 0; - Node current = root; - do { - int index = array[level] & 0xff; - Node next = current.children[index]; - if (next == null) { - return false; - } - if (next.leafObject != null) { - if (Arrays.compare(array, next.leafArray) == 0) { - // TODO there is no cleanup of empty branches - current.children[index] = null; - size--; - return true; - } else { - return false; - } - } - current = next; - - level++; - } while (true); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - @Override - public boolean add(final E bytes) { - byte[] array = bytes.toArrayUnsafe(); - if (array.length != byteLength) { - throw new IllegalArgumentException( - "Byte array is size " + array.length + " but set is size " + byteLength); - } - // Two base cases, size==0 and size==1; - if (root == null) { - // size==0 is easy, just add - root = new Node<>(array, bytes, null); - size++; - return true; - } - if (root.leafObject != null) { - // size==1 first check then if no match make it look like n>1 - if (Arrays.compare(array, root.leafArray) == 0) { - return false; - } - Node oldRoot = root; - root = new Node<>(null, null, new Node[256]); - root.children[oldRoot.leafArray[0] & 0xff] = oldRoot; - } - int level = 0; - Node current = root; - do { - int index = array[level] & 0xff; - Node next = current.children[index]; - if (next == null) { - next = new Node<>(array, bytes, null); - current.children[index] = next; - size++; - return true; - } - if (next.leafObject != null) { - if (Arrays.compare(array, next.leafArray) == 0) { - return false; - } - Node newLeaf = new Node<>(null, null, new Node[256]); - newLeaf.children[next.leafArray[level + 1] & 0xff] = next; - current.children[index] = newLeaf; - next = newLeaf; - } - level++; - - current = next; - - } while (true); - } - - @Override - public void clear() { - root = null; - } -} diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index 18391543bd0..e7c8a95ff46 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -16,7 +16,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; @@ -32,6 +31,7 @@ import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Deque; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -61,7 +61,7 @@ public class EVMExecutor { private BlockHashLookup blockHashLookup = (__, ___) -> null; private Optional> versionedHashes = Optional.empty(); private OperationTracer tracer = OperationTracer.NO_TRACING; - private Set
accessListWarmAddresses = new BytesTrieSet<>(Address.SIZE); + private Set
accessListWarmAddresses = new HashSet<>(Address.SIZE); private Multimap accessListWarmStorage = HashMultimap.create(); private MessageCallProcessor messageCallProcessor = null; private ContractCreationProcessor contractCreationProcessor = null; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java index 8f0b86eeb26..964739bd90f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java @@ -17,7 +17,6 @@ import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.emptySet; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.collections.undo.UndoScalar; import org.hyperledger.besu.collections.undo.UndoSet; import org.hyperledger.besu.collections.undo.UndoTable; @@ -39,6 +38,7 @@ import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -1695,7 +1695,7 @@ public MessageFrame build() { new TxValues( blockHashLookup, maxStackSize, - UndoSet.of(new BytesTrieSet<>(Address.SIZE)), + UndoSet.of(new HashSet<>(Address.SIZE)), UndoTable.of(HashBasedTable.create()), originator, gasPrice, @@ -1705,8 +1705,8 @@ public MessageFrame build() { miningBeneficiary, versionedHashes, UndoTable.of(HashBasedTable.create()), - UndoSet.of(new BytesTrieSet<>(Address.SIZE)), - UndoSet.of(new BytesTrieSet<>(Address.SIZE)), + UndoSet.of(new HashSet<>(Address.SIZE)), + UndoSet.of(new HashSet<>(Address.SIZE)), new UndoScalar<>(0L)); updater = worldUpdater; newStatic = isStatic; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/AbstractWorldUpdater.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/AbstractWorldUpdater.java index 6e9c8d5ec41..efb97e81a3a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/AbstractWorldUpdater.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/AbstractWorldUpdater.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.evm.worldstate; -import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.account.Account; @@ -23,6 +22,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -47,8 +47,7 @@ public abstract class AbstractWorldUpdater> updatedAccounts = new ConcurrentHashMap<>(); /** The Deleted accounts. */ - protected Set
deletedAccounts = - Collections.synchronizedSet(new BytesTrieSet<>(Address.SIZE)); + protected Set
deletedAccounts = Collections.synchronizedSet(new HashSet<>(Address.SIZE)); /** * Instantiates a new Abstract world updater. diff --git a/evm/src/test/java/org/hyperledger/besu/collections/trie/BytesTrieSetTest.java b/evm/src/test/java/org/hyperledger/besu/collections/trie/BytesTrieSetTest.java deleted file mode 100644 index 54efb9d685b..00000000000 --- a/evm/src/test/java/org/hyperledger/besu/collections/trie/BytesTrieSetTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.collections.trie; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.jupiter.api.Test; - -class BytesTrieSetTest { - - private static final Bytes BYTES_1234 = Bytes.of(1, 2, 3, 4); - private static final Bytes BYTES_4321 = Bytes.of(4, 3, 2, 1); - private static final Bytes BYTES_4567 = Bytes.of(4, 5, 6, 7); - private static final Bytes BYTES_4568 = Bytes.of(4, 5, 6, 8); - private static final Bytes BYTES_4556 = Bytes.of(4, 5, 5, 6); - private static final Bytes BYTES_123 = Bytes.of(1, 2, 3); - - @Test - void testInserts() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThat(trieSet).isEmpty(); - System.out.println(trieSet); - - assertThat(trieSet.add(BYTES_1234)).isTrue(); - assertThat(trieSet).hasSize(1); - - assertThat(trieSet.add(BYTES_1234)).isFalse(); - assertThat(trieSet).hasSize(1); - - assertThat(trieSet.add(BYTES_4321)).isTrue(); - assertThat(trieSet).hasSize(2); - - assertThat(trieSet.add(BYTES_4567)).isTrue(); - assertThat(trieSet).hasSize(3); - - assertThat(trieSet.add(BYTES_4567)).isFalse(); - assertThat(trieSet).hasSize(3); - - System.out.println(trieSet); - } - - @Test - void testRemoves() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - - assertThat(trieSet.remove(BYTES_1234)).isFalse(); - - trieSet.add(BYTES_1234); - assertThat(trieSet.remove(BYTES_4321)).isFalse(); - assertThat(trieSet.remove(BYTES_1234)).isTrue(); - assertThat(trieSet).isEmpty(); - - trieSet.add(BYTES_1234); - trieSet.add(BYTES_4321); - assertThat(trieSet.remove(BYTES_4567)).isFalse(); - assertThat(trieSet.remove(BYTES_4568)).isFalse(); - - trieSet.add(BYTES_4567); - trieSet.add(BYTES_4568); - assertThat(trieSet).hasSize(4); - - assertThat(trieSet.remove(BYTES_4556)).isFalse(); - assertThat(trieSet.remove(BYTES_4568)).isTrue(); - assertThat(trieSet.remove(BYTES_4568)).isFalse(); - assertThat(trieSet).hasSize(3); - assertThat(trieSet.remove(BYTES_4567)).isTrue(); - assertThat(trieSet).hasSize(2); - - assertThat(trieSet.remove(BYTES_4321)).isTrue(); - assertThat(trieSet).hasSize(1); - - assertThat(trieSet.remove(BYTES_1234)).isTrue(); - assertThat(trieSet).isEmpty(); - } - - @Test - @SuppressWarnings( - "squid:S5838") // contains and doesNotContains uses iterables, not the contains method - void testContains() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - - assertThat(trieSet.contains(BYTES_1234)).isFalse(); - - trieSet.add(BYTES_1234); - assertThat(trieSet.contains(BYTES_4321)).isFalse(); - assertThat(trieSet.contains(BYTES_1234)).isTrue(); - assertThat(trieSet).hasSize(1); - - trieSet.add(BYTES_1234); - trieSet.add(BYTES_4321); - assertThat(trieSet.contains(BYTES_4567)).isFalse(); - assertThat(trieSet.contains(BYTES_4568)).isFalse(); - - trieSet.add(BYTES_4567); - trieSet.add(BYTES_4568); - assertThat(trieSet).hasSize(4); - - assertThat(trieSet.contains(BYTES_4556)).isFalse(); - assertThat(trieSet.contains(BYTES_4568)).isTrue(); - trieSet.remove(BYTES_4568); - assertThat(trieSet).hasSize(3); - assertThat(trieSet.contains(BYTES_4567)).isTrue(); - trieSet.remove(BYTES_4567); - assertThat(trieSet).hasSize(2); - assertThat(trieSet.contains(BYTES_4567)).isFalse(); - - assertThat(trieSet.contains(BYTES_4321)).isTrue(); - trieSet.remove(BYTES_4321); - assertThat(trieSet.contains(BYTES_4321)).isFalse(); - assertThat(trieSet).hasSize(1); - - assertThat(trieSet.contains(BYTES_1234)).isTrue(); - trieSet.remove(BYTES_1234); - assertThat(trieSet.contains(BYTES_4321)).isFalse(); - - assertThat(trieSet).isEmpty(); - } - - @Test - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - void checkLengthAdd() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThatThrownBy(() -> trieSet.add(BYTES_123)).isInstanceOf(IllegalArgumentException.class); - } - - @Test - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - void checkLengthRemove() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThatThrownBy(() -> trieSet.remove(BYTES_123)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("4"); - } - - @Test - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - void checkLengthContains() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThatThrownBy(() -> trieSet.contains(BYTES_123)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("4"); - } - - @Test - @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "SuspiciousMethodCalls"}) - void checkWrongClassRemove() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThatThrownBy(() -> trieSet.remove(this)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Bytes"); - } - - @Test - @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "SuspiciousMethodCalls"}) - void checkWrongClassContains() { - BytesTrieSet trieSet = new BytesTrieSet<>(4); - assertThatThrownBy(() -> trieSet.contains(this)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Bytes"); - } -}