From 68f2d3699e1739ea31218a50b0919978a4423f8d Mon Sep 17 00:00:00 2001 From: Karim T Date: Wed, 10 Mar 2021 15:02:57 +0100 Subject: [PATCH 1/8] update BonsaiLayeredWorldState implementation Signed-off-by: Karim TAAM --- .../internal/processor/BlockReplay.java | 2 +- .../processor/TransactionTracerTest.java | 3 +- .../bonsai/BonsaiLayeredWorldState.java | 88 ++++++++++--------- .../bonsai/BonsaiPersistedWorldState.java | 15 +--- .../bonsai/BonsaiWorldStateArchive.java | 49 ++++++----- .../bonsai/BonsaiWorldStateUpdater.java | 5 +- .../besu/ethereum/bonsai/TrieLogLayer.java | 43 +++------ .../transaction/TransactionSimulator.java | 4 +- 8 files changed, 98 insertions(+), 111 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java index ae8278d3a7b..c22d6a62c37 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java @@ -146,7 +146,7 @@ private Optional performActionWithBlock( return Optional.empty(); } final MutableWorldState mutableWorldState = - worldStateArchive.getMutable(previous.getStateRoot(), previous.getHash()).orElse(null); + worldStateArchive.getWorldState(previous.getStateRoot(), previous.getHash()).orElse(null); if (mutableWorldState == null) { return Optional.empty(); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java index 67f50e9fcfb..7b87fbe5b35 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java @@ -110,7 +110,8 @@ public void setUp() throws Exception { when(blockHeader.getHash()).thenReturn(blockHash); when(blockHeader.getParentHash()).thenReturn(previousBlockHash); when(previousBlockHeader.getStateRoot()).thenReturn(Hash.ZERO); - when(worldStateArchive.getMutable(Hash.ZERO, null)).thenReturn(Optional.of(mutableWorldState)); + when(worldStateArchive.getWorldState(Hash.ZERO, null)) + .thenReturn(Optional.of(mutableWorldState)); when(protocolSchedule.getByBlockNumber(12)).thenReturn(protocolSpec); when(protocolSpec.getTransactionProcessor()).thenReturn(transactionProcessor); when(protocolSpec.getMiningBeneficiaryCalculator()).thenReturn(BlockHeader::getCoinbase); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java index 84d5e692144..ed5238b4959 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java @@ -37,30 +37,31 @@ /** A World State backed first by trie log layer and then by another world state. */ public class BonsaiLayeredWorldState implements MutableWorldState, BonsaiWorldView, WorldState { - private final BonsaiWorldStateArchive worldStateArchive; - private final BonsaiWorldView parent; + private Optional parent; protected final long height; protected final TrieLogLayer trieLog; private final Hash worldStateRootHash; BonsaiLayeredWorldState( - final BonsaiWorldStateArchive worldStateArchive, - final BonsaiWorldView parent, + final Optional parent, final long height, final Hash worldStateRootHash, final TrieLogLayer trieLog) { - this.worldStateArchive = worldStateArchive; this.parent = parent; this.height = height; this.worldStateRootHash = worldStateRootHash; this.trieLog = trieLog; } - public BonsaiWorldView getParent() { + public Optional getParent() { return parent; } + public void setParent(final Optional parent) { + this.parent = parent; + } + public TrieLogLayer getTrieLog() { return trieLog; } @@ -71,29 +72,23 @@ public long getHeight() { @Override public Optional getCode(final Address address) { - // this must be iterative and lambda light because the stack may blow up - // mainly because we don't have tail calls. BonsaiLayeredWorldState currentLayer = this; while (currentLayer != null) { final Optional maybeCode = currentLayer.trieLog.getCode(address); - if (maybeCode.isPresent()) { + final Optional maybeOriginalCode = currentLayer.trieLog.getOriginalCode(address); + if (currentLayer == this && maybeCode.isPresent()) { return maybeCode; + } else if (maybeOriginalCode.isPresent()) { + return maybeOriginalCode; + } else if (maybeCode.isPresent()) { + return Optional.empty(); } - final Optional maybeLastChangedCodeLocation = - currentLayer.trieLog.getLastChangedCodeLocation(address); - if (maybeLastChangedCodeLocation.isPresent()) { - final Optional maybeTrieLogLayer = - worldStateArchive.getTrieLogLayer(maybeLastChangedCodeLocation.get()); - if (maybeTrieLogLayer.isPresent()) { - return maybeTrieLogLayer.get().getCode(address); - } - } - if (currentLayer.parent == null) { + if (currentLayer.parent.isEmpty()) { currentLayer = null; - } else if (currentLayer.parent instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent; + } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); } else { - return currentLayer.parent.getCode(address); + return currentLayer.parent.get().getCode(address); } } return Optional.empty(); @@ -105,12 +100,12 @@ public Optional getStateTrieNode(final Bytes location) { // mainly because we don't have tail calls. BonsaiLayeredWorldState currentLayer = this; while (currentLayer != null) { - if (currentLayer.parent == null) { + if (currentLayer.parent.isEmpty()) { currentLayer = null; - } else if (currentLayer.parent instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent; + } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); } else { - return currentLayer.parent.getStateTrieNode(location); + return currentLayer.parent.get().getStateTrieNode(location); } } return Optional.empty(); @@ -129,15 +124,21 @@ public Optional getStorageValueBySlotHash(final Address address, final while (currentLayer != null) { final Optional maybeValue = currentLayer.trieLog.getStorageBySlotHash(address, slotHash); - if (maybeValue.isPresent()) { + final Optional maybeOriginalValue = + currentLayer.trieLog.getOriginalStorageBySlotHash(address, slotHash); + if (currentLayer == this && maybeValue.isPresent()) { return maybeValue; + } else if (maybeOriginalValue.isPresent()) { + return maybeOriginalValue; + } else if (maybeValue.isPresent()) { + return Optional.empty(); } - if (currentLayer.parent == null) { + if (currentLayer.parent.isEmpty()) { currentLayer = null; - } else if (currentLayer.parent instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent; + } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); } else { - return currentLayer.parent.getStorageValueBySlotHash(address, slotHash); + return currentLayer.parent.get().getStorageValueBySlotHash(address, slotHash); } } return Optional.empty(); @@ -169,12 +170,12 @@ public Map getAllAccountStorage(final Address address, final Has } }); } - if (currentLayer.parent == null) { + if (currentLayer.parent.isEmpty()) { currentLayer = null; - } else if (currentLayer.parent instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent; + } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); } else { - final Account account = currentLayer.parent.get(address); + final Account account = currentLayer.parent.get().get(address); if (account != null) { account .storageEntriesFrom(Hash.ZERO, Integer.MAX_VALUE) @@ -199,16 +200,23 @@ public Account get(final Address address) { while (currentLayer != null) { final Optional maybeStateTrieAccount = currentLayer.trieLog.getAccount(address); - if (maybeStateTrieAccount.isPresent()) { + final Optional maybeOriginalStateTrieAccount = + currentLayer.trieLog.getOriginalAccount(address); + if (currentLayer == this && maybeStateTrieAccount.isPresent()) { return new BonsaiAccount( BonsaiLayeredWorldState.this, address, maybeStateTrieAccount.get(), false); + } else if (maybeOriginalStateTrieAccount.isPresent()) { + return new BonsaiAccount( + BonsaiLayeredWorldState.this, address, maybeOriginalStateTrieAccount.get(), false); + } else if (maybeStateTrieAccount.isPresent()) { + return null; } - if (currentLayer.parent == null) { + if (currentLayer.parent.isEmpty()) { currentLayer = null; - } else if (currentLayer.parent instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent; + } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); } else { - return currentLayer.parent.get(address); + return currentLayer.parent.get().get(address); } } return null; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java index 9194193cb45..697afe3eb56 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java @@ -32,7 +32,6 @@ import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; -import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -57,8 +56,6 @@ public class BonsaiPersistedWorldState implements MutableWorldState, BonsaiWorld private Hash worldStateRootHash; private Hash worldStateBlockHash; - private final Map contractCodeChangesHistory; - public BonsaiPersistedWorldState( final BonsaiWorldStateArchive archive, final BonsaiWorldStateKeyValueStorage worldStateStorage) { @@ -70,12 +67,6 @@ public BonsaiPersistedWorldState( worldStateBlockHash = Hash.wrap(Bytes32.wrap(worldStateStorage.getWorldStateBlockHash().orElse(Hash.ZERO))); updater = new BonsaiWorldStateUpdater(this); - contractCodeChangesHistory = - worldStateStorage - .getTrieLog(worldStateBlockHash) - .map(TrieLogLayer::fromBytes) - .map(TrieLogLayer::getContractCodeChangesHistory) - .orElse(new HashMap<>()); } public BonsaiWorldStateArchive getArchive() { @@ -258,12 +249,10 @@ public void persist(final BlockHeader blockHeader) { .put(WORLD_BLOCK_HASH_KEY, worldStateBlockHash.toArrayUnsafe()); if (originalBlockHash.equals(blockHeader.getParentHash())) { LOG.debug("Writing Trie Log for {}", worldStateBlockHash); - final TrieLogLayer trieLog = - updater.generateTrieLog(worldStateBlockHash, contractCodeChangesHistory); + final TrieLogLayer trieLog = updater.generateTrieLog(worldStateBlockHash); trieLog.freeze(); archive.addLayeredWorldState( - new BonsaiLayeredWorldState( - getArchive(), this, blockHeader.getNumber(), worldStateRootHash, trieLog)); + getArchive(), this, blockHeader.getNumber(), worldStateRootHash, trieLog); final BytesValueRLPOutput rlpLog = new BytesValueRLPOutput(); trieLog.writeTo(rlpLog); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java index 7f1638e845e..aee487df5cd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java @@ -47,7 +47,7 @@ public class BonsaiWorldStateArchive implements WorldStateArchive { private final Blockchain blockchain; private final BonsaiPersistedWorldState persistedState; - private final Map layeredWorldStates; + private final Map layeredWorldStatesByHash; private final BonsaiWorldStateKeyValueStorage worldStateStorage; public BonsaiWorldStateArchive(final StorageProvider provider, final Blockchain blockchain) { @@ -55,13 +55,13 @@ public BonsaiWorldStateArchive(final StorageProvider provider, final Blockchain worldStateStorage = new BonsaiWorldStateKeyValueStorage(provider); persistedState = new BonsaiPersistedWorldState(this, worldStateStorage); - layeredWorldStates = new HashMap<>(); + layeredWorldStatesByHash = new HashMap<>(); } @Override public Optional get(final Hash rootHash, final Hash blockHash) { - if (layeredWorldStates.containsKey(rootHash)) { - return Optional.of(layeredWorldStates.get(blockHash)); + if (layeredWorldStatesByHash.containsKey(rootHash)) { + return Optional.of(layeredWorldStatesByHash.get(blockHash)); } else if (rootHash.equals(persistedState.blockHash())) { return Optional.of(persistedState); } else { @@ -69,13 +69,30 @@ public Optional get(final Hash rootHash, final Hash blockHash) { } } - void addLayeredWorldState(final BonsaiLayeredWorldState worldState) { - layeredWorldStates.put(worldState.blockHash(), worldState); + public void addLayeredWorldState( + final BonsaiWorldStateArchive archive, + final BonsaiWorldView persistedWorldState, + final long blockNumber, + final Hash worldStateRootHash, + final TrieLogLayer trieLog) { + final BonsaiLayeredWorldState bonsaiLayeredWorldState = + new BonsaiLayeredWorldState( + Optional.of(persistedWorldState), blockNumber, worldStateRootHash, trieLog); + layeredWorldStatesByHash.put(bonsaiLayeredWorldState.blockHash(), bonsaiLayeredWorldState); + if (blockNumber > 0) { + final Optional blockHashByNumber = blockchain.getBlockHashByNumber(blockNumber - 1); + if (blockHashByNumber.isPresent() + && layeredWorldStatesByHash.containsKey(blockHashByNumber.get())) { + layeredWorldStatesByHash + .get(blockHashByNumber.get()) + .setParent(Optional.of(bonsaiLayeredWorldState)); + } + } } public Optional getTrieLogLayer(final Hash blockHash) { - if (layeredWorldStates.containsKey(blockHash)) { - return Optional.of(layeredWorldStates.get(blockHash).getTrieLog()); + if (layeredWorldStatesByHash.containsKey(blockHash)) { + return Optional.of(layeredWorldStatesByHash.get(blockHash).getTrieLog()); } else { return worldStateStorage.getTrieLog(blockHash).map(TrieLogLayer::fromBytes); } @@ -83,23 +100,15 @@ public Optional getTrieLogLayer(final Hash blockHash) { @Override public boolean isWorldStateAvailable(final Hash rootHash, final Hash blockHash) { - return layeredWorldStates.containsKey(blockHash) + return layeredWorldStatesByHash.containsKey(blockHash) || persistedState.blockHash().equals(blockHash) || worldStateStorage.isWorldStateAvailable(rootHash, blockHash); } @Override public Optional getWorldState(final Hash rootHash, final Hash blockHash) { - if (layeredWorldStates.containsKey(blockHash)) { - return Optional.of(layeredWorldStates.get(blockHash)); - } else { - final Optional trieLogLayer = getTrieLogLayer(blockHash); - if (trieLogLayer.isPresent()) { - final BlockHeader header = blockchain.getBlockHeader(persistedState.blockHash()).get(); - return Optional.of( - new BonsaiLayeredWorldState( - this, persistedState, header.getNumber(), blockHash, trieLogLayer.get())); - } + if (layeredWorldStatesByHash.containsKey(blockHash)) { + return Optional.of(layeredWorldStatesByHash.get(blockHash)); } return Optional.empty(); } @@ -194,6 +203,6 @@ public Optional getAccountProof( void scrubLayeredCache(final long newMaxHeight) { final long waterline = newMaxHeight - RETAINED_LAYERS; - layeredWorldStates.entrySet().removeIf(entry -> entry.getValue().getHeight() < waterline); + layeredWorldStatesByHash.entrySet().removeIf(entry -> entry.getValue().getHeight() < waterline); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java index 0a0623278dd..53e1652669d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java @@ -335,9 +335,8 @@ public Map getAllAccountStorage(final Address address, final Has return results; } - public TrieLogLayer generateTrieLog( - final Hash blockHash, final Map contractCodeChangesHistory) { - final TrieLogLayer layer = new TrieLogLayer(contractCodeChangesHistory); + public TrieLogLayer generateTrieLog(final Hash blockHash) { + final TrieLogLayer layer = new TrieLogLayer(); importIntoTrieLog(layer, blockHash); return layer; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java index 2a92ebd03c3..cf76b29f960 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java @@ -51,19 +51,13 @@ public class TrieLogLayer { private final Map> accounts; private final Map> code; private final Map>> storage; - private final Map contractCodeChangesHistory; private boolean frozen = false; TrieLogLayer() { // TODO when tuweni fixes zero length byte comparison consider TreeMap - this(new HashMap<>()); - } - - public TrieLogLayer(final Map contractCodeChangesHistory) { this.accounts = new HashMap<>(); this.code = new HashMap<>(); this.storage = new HashMap<>(); - this.contractCodeChangesHistory = contractCodeChangesHistory; } /** Locks the layer so no new changes can be added; */ @@ -95,7 +89,6 @@ void addCodeChange( address, new BonsaiValue<>( oldValue == null ? Bytes.EMPTY : oldValue, newValue == null ? Bytes.EMPTY : newValue)); - contractCodeChangesHistory.put(address, blockHash); } void addStorageChange( @@ -157,12 +150,6 @@ static TrieLogLayer readFrom(final RLPInput input) { newLayer.storage.put(address, storageChanges); } - if (input.nextIsNull()) { - input.skipNext(); - } else { - newLayer.contractCodeChangesHistory.put(address, Hash.wrap(input.readBytes32())); - } - // TODO add trie nodes // lenient leave list for forward compatible additions. @@ -181,7 +168,6 @@ void writeTo(final RLPOutput output) { addresses.addAll(accounts.keySet()); addresses.addAll(code.keySet()); addresses.addAll(storage.keySet()); - addresses.addAll(contractCodeChangesHistory.keySet()); output.startList(); // container output.writeBytes(blockHash); @@ -219,13 +205,6 @@ void writeTo(final RLPOutput output) { output.endList(); } - final Hash blockHash = contractCodeChangesHistory.get(address); - if (blockHash == null) { - output.writeNull(); - } else { - output.writeBytes(blockHash); - } - // TODO write trie nodes output.endList(); // this change @@ -245,10 +224,6 @@ Stream>>> streamStorageChanges return storage.entrySet().stream(); } - public Map getContractCodeChangesHistory() { - return contractCodeChangesHistory; - } - boolean hasStorageChanges(final Address address) { return storage.containsKey(address); } @@ -266,16 +241,18 @@ private static T nullOrValue(final RLPInput input, final Function getOriginalCode(final Address address) { + return Optional.ofNullable(code.get(address)).map(BonsaiValue::getOriginal); + } + public Optional getCode(final Address address) { return Optional.ofNullable(code.get(address)).map(BonsaiValue::getUpdated); } - public Optional getLastChangedCodeLocation(final Address address) { - if (contractCodeChangesHistory.containsKey(address) - && !contractCodeChangesHistory.get(address).isEmpty()) { - return Optional.of(contractCodeChangesHistory.get(address)); - } - return Optional.empty(); + Optional getOriginalStorageBySlotHash(final Address address, final Hash slotHash) { + return Optional.ofNullable(storage.get(address)) + .map(i -> i.get(slotHash)) + .map(BonsaiValue::getOriginal); } Optional getStorageBySlotHash(final Address address, final Hash slotHash) { @@ -284,6 +261,10 @@ Optional getStorageBySlotHash(final Address address, final Hash slotHas .map(BonsaiValue::getUpdated); } + public Optional getOriginalAccount(final Address address) { + return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getOriginal); + } + public Optional getAccount(final Address address) { return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getUpdated); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index f12f8f309e6..85cf387f3dd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -142,7 +142,7 @@ public Optional process( return Optional.empty(); } final MutableWorldState publicWorldState = - worldStateArchive.getMutable(header.getStateRoot(), header.getHash()).orElse(null); + worldStateArchive.getWorldState(header.getStateRoot(), header.getHash()).orElse(null); if (publicWorldState == null) { return Optional.empty(); @@ -216,7 +216,7 @@ private WorldUpdater getEffectiveWorldStateUpdater( public Optional doesAddressExistAtHead(final Address address) { final BlockHeader header = blockchain.getChainHeadHeader(); final MutableWorldState worldState = - worldStateArchive.getMutable(header.getStateRoot(), header.getHash()).orElse(null); + worldStateArchive.getWorldState(header.getStateRoot(), header.getHash()).orElse(null); return doesAddressExist(worldState, address, header); } From 49c3f9b255194404c6eb431d32334ee14a97acbe Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Wed, 10 Mar 2021 17:41:26 +0100 Subject: [PATCH 2/8] fix unit test Signed-off-by: Karim TAAM --- .../besu/ethereum/bonsai/BonsaiPersistedWorldState.java | 3 +-- .../besu/ethereum/bonsai/BonsaiWorldStateArchive.java | 1 - .../hyperledger/besu/ethereum/bonsai/LogRollingTests.java | 7 +++++-- .../ethereum/transaction/TransactionSimulatorTest.java | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java index 697afe3eb56..8badf958dcd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java @@ -251,8 +251,7 @@ public void persist(final BlockHeader blockHeader) { LOG.debug("Writing Trie Log for {}", worldStateBlockHash); final TrieLogLayer trieLog = updater.generateTrieLog(worldStateBlockHash); trieLog.freeze(); - archive.addLayeredWorldState( - getArchive(), this, blockHeader.getNumber(), worldStateRootHash, trieLog); + archive.addLayeredWorldState(this, blockHeader.getNumber(), worldStateRootHash, trieLog); final BytesValueRLPOutput rlpLog = new BytesValueRLPOutput(); trieLog.writeTo(rlpLog); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java index aee487df5cd..c29969c28fe 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java @@ -70,7 +70,6 @@ public Optional get(final Hash rootHash, final Hash blockHash) { } public void addLayeredWorldState( - final BonsaiWorldStateArchive archive, final BonsaiWorldView persistedWorldState, final long blockNumber, final Hash worldStateRootHash, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java index fefc528f90a..46e9eba7f9e 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java @@ -17,7 +17,9 @@ package org.hyperledger.besu.ethereum.bonsai; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; @@ -57,6 +59,7 @@ public class LogRollingTests { private InMemoryKeyValueStorage secondStorageStorage; private InMemoryKeyValueStorage secondTrieBranchStorage; private InMemoryKeyValueStorage secondTrieLogStorage; + private Blockchain blockchain = mock(Blockchain.class); private static final Address addressOne = Address.fromHexString("0x1111111111111111111111111111111111111111"); @@ -103,7 +106,7 @@ public class LogRollingTests { @Before public void createStorage() { final InMemoryKeyValueStorageProvider provider = new InMemoryKeyValueStorageProvider(); - archive = new BonsaiWorldStateArchive(provider, null); + archive = new BonsaiWorldStateArchive(provider, blockchain); accountStorage = (InMemoryKeyValueStorage) provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE); @@ -122,7 +125,7 @@ public void createStorage() { provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE); final InMemoryKeyValueStorageProvider secondProvider = new InMemoryKeyValueStorageProvider(); - secondArchive = new BonsaiWorldStateArchive(secondProvider, null); + secondArchive = new BonsaiWorldStateArchive(secondProvider, blockchain); secondAccountStorage = (InMemoryKeyValueStorage) secondProvider.getStorageBySegmentIdentifier( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index 3861b1d9d22..f56b161fd5d 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -418,19 +418,19 @@ private void mockWorldStateForAccount( final Hash stateRoot, final Address address, final long nonce) { final Account account = mock(Account.class); when(account.getNonce()).thenReturn(nonce); - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.get(eq(address))).thenReturn(account); } private void mockWorldStateForAbsentAccount(final Hash stateRoot) { - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.get(any())).thenReturn(null); } private MutableAccount mockWorldUpdaterForAccount(final Hash stateRoot, final Address address) { final EvmAccount account = mock(EvmAccount.class); final MutableAccount mutableAccount = mock(MutableAccount.class); - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.updater()).thenReturn(worldUpdater); when(worldUpdater.getOrCreate(eq(address))).thenReturn(account); when(account.getMutable()).thenReturn(mutableAccount); From 2bbe03225fe1c627fac1109992581e63e56f4498 Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Wed, 10 Mar 2021 18:02:56 +0100 Subject: [PATCH 3/8] fix pipeline Signed-off-by: Karim TAAM --- .../org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java index 46e9eba7f9e..96b6f4bb413 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java @@ -59,7 +59,7 @@ public class LogRollingTests { private InMemoryKeyValueStorage secondStorageStorage; private InMemoryKeyValueStorage secondTrieBranchStorage; private InMemoryKeyValueStorage secondTrieLogStorage; - private Blockchain blockchain = mock(Blockchain.class); + private final Blockchain blockchain = mock(Blockchain.class); private static final Address addressOne = Address.fromHexString("0x1111111111111111111111111111111111111111"); From 189a52303d8619b44185fa0348d06666c564428f Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Thu, 11 Mar 2021 15:21:14 +0100 Subject: [PATCH 4/8] fix review issues Signed-off-by: Karim TAAM --- .../internal/processor/BlockReplay.java | 4 +- .../processor/TransactionTracerTest.java | 2 +- .../besu/ethereum/bonsai/BonsaiAccount.java | 2 +- .../bonsai/BonsaiLayeredWorldState.java | 77 +++++++++++-------- .../bonsai/BonsaiPersistedWorldState.java | 4 +- .../besu/ethereum/bonsai/BonsaiValue.java | 22 +++--- .../bonsai/BonsaiWorldStateArchive.java | 43 +++++++++-- .../bonsai/BonsaiWorldStateUpdater.java | 35 ++++----- .../besu/ethereum/bonsai/BonsaiWorldView.java | 2 +- .../besu/ethereum/bonsai/TrieLogLayer.java | 24 +++--- .../transaction/TransactionSimulator.java | 4 +- .../worldstate/DefaultWorldStateArchive.java | 10 ++- .../worldstate/WorldStateArchive.java | 4 +- .../transaction/TransactionSimulatorTest.java | 6 +- 14 files changed, 147 insertions(+), 92 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java index c22d6a62c37..f6a266c2036 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java @@ -146,7 +146,9 @@ private Optional performActionWithBlock( return Optional.empty(); } final MutableWorldState mutableWorldState = - worldStateArchive.getWorldState(previous.getStateRoot(), previous.getHash()).orElse(null); + worldStateArchive + .getMutable(previous.getStateRoot(), previous.getHash(), false) + .orElse(null); if (mutableWorldState == null) { return Optional.empty(); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java index 7b87fbe5b35..1a7e9c3ce56 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java @@ -110,7 +110,7 @@ public void setUp() throws Exception { when(blockHeader.getHash()).thenReturn(blockHash); when(blockHeader.getParentHash()).thenReturn(previousBlockHash); when(previousBlockHeader.getStateRoot()).thenReturn(Hash.ZERO); - when(worldStateArchive.getWorldState(Hash.ZERO, null)) + when(worldStateArchive.getMutable(Hash.ZERO, null, false)) .thenReturn(Optional.of(mutableWorldState)); when(protocolSchedule.getByBlockNumber(12)).thenReturn(protocolSpec); when(protocolSpec.getTransactionProcessor()).thenReturn(transactionProcessor); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiAccount.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiAccount.java index 41131b503f2..5fd6b3f4424 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiAccount.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiAccount.java @@ -244,7 +244,7 @@ public UInt256 getStorageValue(final UInt256 key) { @Override public UInt256 getOriginalStorageValue(final UInt256 key) { - return context.getOriginalStorageValue(address, key); + return context.getPriorStorageValue(address, key); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java index ed5238b4959..c42cf8cebd8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java @@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.bonsai; +import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Account; import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -37,29 +38,41 @@ /** A World State backed first by trie log layer and then by another world state. */ public class BonsaiLayeredWorldState implements MutableWorldState, BonsaiWorldView, WorldState { - private Optional parent; + private Optional nextWorldView; protected final long height; protected final TrieLogLayer trieLog; - private final Hash worldStateRootHash; + private final Blockchain blockchain; + private final BonsaiWorldStateArchive archive; + BonsaiLayeredWorldState( - final Optional parent, + final Blockchain blockchain, + final BonsaiWorldStateArchive archive, + final Optional nextWorldView, final long height, final Hash worldStateRootHash, final TrieLogLayer trieLog) { - this.parent = parent; + this.blockchain = blockchain; + this.archive = archive; + this.nextWorldView = nextWorldView; this.height = height; this.worldStateRootHash = worldStateRootHash; this.trieLog = trieLog; } - public Optional getParent() { - return parent; + public Optional getNextWorldView() { + if (nextWorldView.isEmpty()) { + final Optional blockHashByNumber = blockchain.getBlockHashByNumber(height + 1); + blockHashByNumber + .map(hash -> archive.getMutable(null, hash, false).map(BonsaiWorldView.class::cast)) + .orElseGet(() -> Optional.of(archive.getMutable()).map(BonsaiWorldView.class::cast)); + } + return nextWorldView; } - public void setParent(final Optional parent) { - this.parent = parent; + public void setNextWorldView(final Optional nextWorldView) { + this.nextWorldView = nextWorldView; } public TrieLogLayer getTrieLog() { @@ -75,7 +88,7 @@ public Optional getCode(final Address address) { BonsaiLayeredWorldState currentLayer = this; while (currentLayer != null) { final Optional maybeCode = currentLayer.trieLog.getCode(address); - final Optional maybeOriginalCode = currentLayer.trieLog.getOriginalCode(address); + final Optional maybeOriginalCode = currentLayer.trieLog.getPriorCode(address); if (currentLayer == this && maybeCode.isPresent()) { return maybeCode; } else if (maybeOriginalCode.isPresent()) { @@ -83,12 +96,12 @@ public Optional getCode(final Address address) { } else if (maybeCode.isPresent()) { return Optional.empty(); } - if (currentLayer.parent.isEmpty()) { + if (currentLayer.getNextWorldView().isEmpty()) { currentLayer = null; - } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); + } else if (currentLayer.getNextWorldView().get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.getNextWorldView().get(); } else { - return currentLayer.parent.get().getCode(address); + return currentLayer.getNextWorldView().get().getCode(address); } } return Optional.empty(); @@ -100,12 +113,12 @@ public Optional getStateTrieNode(final Bytes location) { // mainly because we don't have tail calls. BonsaiLayeredWorldState currentLayer = this; while (currentLayer != null) { - if (currentLayer.parent.isEmpty()) { + if (currentLayer.getNextWorldView().isEmpty()) { currentLayer = null; - } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); + } else if (currentLayer.getNextWorldView().get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.getNextWorldView().get(); } else { - return currentLayer.parent.get().getStateTrieNode(location); + return currentLayer.getNextWorldView().get().getStateTrieNode(location); } } return Optional.empty(); @@ -125,7 +138,7 @@ public Optional getStorageValueBySlotHash(final Address address, final final Optional maybeValue = currentLayer.trieLog.getStorageBySlotHash(address, slotHash); final Optional maybeOriginalValue = - currentLayer.trieLog.getOriginalStorageBySlotHash(address, slotHash); + currentLayer.trieLog.getPriorStorageBySlotHash(address, slotHash); if (currentLayer == this && maybeValue.isPresent()) { return maybeValue; } else if (maybeOriginalValue.isPresent()) { @@ -133,19 +146,19 @@ public Optional getStorageValueBySlotHash(final Address address, final } else if (maybeValue.isPresent()) { return Optional.empty(); } - if (currentLayer.parent.isEmpty()) { + if (currentLayer.getNextWorldView().isEmpty()) { currentLayer = null; - } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); + } else if (currentLayer.getNextWorldView().get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.getNextWorldView().get(); } else { - return currentLayer.parent.get().getStorageValueBySlotHash(address, slotHash); + return currentLayer.getNextWorldView().get().getStorageValueBySlotHash(address, slotHash); } } return Optional.empty(); } @Override - public UInt256 getOriginalStorageValue(final Address address, final UInt256 key) { + public UInt256 getPriorStorageValue(final Address address, final UInt256 key) { // This is the base layer for a block, all values are original. return getStorageValue(address, key); } @@ -170,12 +183,12 @@ public Map getAllAccountStorage(final Address address, final Has } }); } - if (currentLayer.parent.isEmpty()) { + if (currentLayer.getNextWorldView().isEmpty()) { currentLayer = null; - } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); + } else if (currentLayer.getNextWorldView().get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.getNextWorldView().get(); } else { - final Account account = currentLayer.parent.get().get(address); + final Account account = currentLayer.getNextWorldView().get().get(address); if (account != null) { account .storageEntriesFrom(Hash.ZERO, Integer.MAX_VALUE) @@ -201,7 +214,7 @@ public Account get(final Address address) { final Optional maybeStateTrieAccount = currentLayer.trieLog.getAccount(address); final Optional maybeOriginalStateTrieAccount = - currentLayer.trieLog.getOriginalAccount(address); + currentLayer.trieLog.getPriorAccount(address); if (currentLayer == this && maybeStateTrieAccount.isPresent()) { return new BonsaiAccount( BonsaiLayeredWorldState.this, address, maybeStateTrieAccount.get(), false); @@ -211,12 +224,12 @@ public Account get(final Address address) { } else if (maybeStateTrieAccount.isPresent()) { return null; } - if (currentLayer.parent.isEmpty()) { + if (currentLayer.getNextWorldView().isEmpty()) { currentLayer = null; - } else if (currentLayer.parent.get() instanceof BonsaiLayeredWorldState) { - currentLayer = (BonsaiLayeredWorldState) currentLayer.parent.get(); + } else if (currentLayer.getNextWorldView().get() instanceof BonsaiLayeredWorldState) { + currentLayer = (BonsaiLayeredWorldState) currentLayer.getNextWorldView().get(); } else { - return currentLayer.parent.get().get(address); + return currentLayer.getNextWorldView().get().get(address); } } return null; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java index 8badf958dcd..f8b5b514515 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiPersistedWorldState.java @@ -133,7 +133,7 @@ private Hash calculateRootHash(final BonsaiWorldStateKeyValueStorage.Updater sta final Hash updatedAddressHash = Hash.hash(updatedAddress); final BonsaiValue accountValue = updater.getAccountsToUpdate().get(updatedAddress); - final BonsaiAccount accountOriginal = accountValue.getOriginal(); + final BonsaiAccount accountOriginal = accountValue.getPrior(); final Hash storageRoot = (accountOriginal == null) ? Hash.EMPTY_TRIE_HASH : accountOriginal.getStorageRoot(); final StoredMerklePatriciaTrie storageTrie = @@ -378,7 +378,7 @@ public Optional getStorageValueBySlotHash(final Address address, final } @Override - public UInt256 getOriginalStorageValue(final Address address, final UInt256 storageKey) { + public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) { return getStorageValue(address, storageKey); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiValue.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiValue.java index cc1e885051c..8130955c786 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiValue.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiValue.java @@ -22,24 +22,24 @@ import java.util.function.BiConsumer; public class BonsaiValue { - private T original; + private T prior; private T updated; - BonsaiValue(final T original, final T updated) { - this.original = original; + BonsaiValue(final T prior, final T updated) { + this.prior = prior; this.updated = updated; } - public T getOriginal() { - return original; + public T getPrior() { + return prior; } public T getUpdated() { return updated; } - public void setOriginal(final T original) { - this.original = original; + public void setPrior(final T prior) { + this.prior = prior; } public void setUpdated(final T updated) { @@ -53,10 +53,10 @@ void writeRlp(final RLPOutput output, final BiConsumer writer) { } void writeInnerRlp(final RLPOutput output, final BiConsumer writer) { - if (original == null) { + if (prior == null) { output.writeNull(); } else { - writer.accept(output, original); + writer.accept(output, prior); } if (updated == null) { output.writeNull(); @@ -66,11 +66,11 @@ void writeInnerRlp(final RLPOutput output, final BiConsumer writer } boolean isUnchanged() { - return Objects.equals(updated, original); + return Objects.equals(updated, prior); } @Override public String toString() { - return "BonsaiValue{" + "original=" + original + ", updated=" + updated + '}'; + return "BonsaiValue{" + "prior=" + prior + ", updated=" + updated + '}'; } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java index c29969c28fe..20d80ccc004 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateArchive.java @@ -76,7 +76,12 @@ public void addLayeredWorldState( final TrieLogLayer trieLog) { final BonsaiLayeredWorldState bonsaiLayeredWorldState = new BonsaiLayeredWorldState( - Optional.of(persistedWorldState), blockNumber, worldStateRootHash, trieLog); + blockchain, + this, + Optional.of(persistedWorldState), + blockNumber, + worldStateRootHash, + trieLog); layeredWorldStatesByHash.put(bonsaiLayeredWorldState.blockHash(), bonsaiLayeredWorldState); if (blockNumber > 0) { final Optional blockHashByNumber = blockchain.getBlockHashByNumber(blockNumber - 1); @@ -84,7 +89,7 @@ public void addLayeredWorldState( && layeredWorldStatesByHash.containsKey(blockHashByNumber.get())) { layeredWorldStatesByHash .get(blockHashByNumber.get()) - .setParent(Optional.of(bonsaiLayeredWorldState)); + .setNextWorldView(Optional.of(bonsaiLayeredWorldState)); } } } @@ -105,9 +110,37 @@ public boolean isWorldStateAvailable(final Hash rootHash, final Hash blockHash) } @Override - public Optional getWorldState(final Hash rootHash, final Hash blockHash) { - if (layeredWorldStatesByHash.containsKey(blockHash)) { - return Optional.of(layeredWorldStatesByHash.get(blockHash)); + public Optional getMutable( + final long blockNumber, final boolean isPersistingState) { + final Optional blockHashByNumber = blockchain.getBlockHashByNumber(blockNumber); + if (blockHashByNumber.isPresent()) { + return getMutable(null, blockHashByNumber.get(), isPersistingState); + } + return Optional.empty(); + } + + @Override + public Optional getMutable( + final Hash rootHash, final Hash blockHash, final boolean isPersistingState) { + if (!isPersistingState) { + if (layeredWorldStatesByHash.containsKey(blockHash)) { + return Optional.of(layeredWorldStatesByHash.get(blockHash)); + } else { + final Optional trieLogLayer = getTrieLogLayer(blockHash); + if (trieLogLayer.isPresent()) { + final BlockHeader header = blockchain.getBlockHeader(blockHash).get(); + return Optional.of( + new BonsaiLayeredWorldState( + blockchain, + this, + Optional.empty(), + header.getNumber(), + blockHash, + trieLogLayer.get())); + } + } + } else { + return getMutable(rootHash, blockHash); } return Optional.empty(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java index 53e1652669d..b51f6d74cee 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java @@ -174,14 +174,14 @@ public void commit() { while (iter.hasNext()) { final Map.Entry> updateEntry = iter.next(); final BonsaiValue updatedSlot = updateEntry.getValue(); - if (updatedSlot.getOriginal() == null || updatedSlot.getOriginal().isZero()) { + if (updatedSlot.getPrior() == null || updatedSlot.getPrior().isZero()) { iter.remove(); } else { updatedSlot.setUpdated(null); } } - final BonsaiAccount originalValue = accountValue.getOriginal(); + final BonsaiAccount originalValue = accountValue.getPrior(); if (originalValue != null) { // Enumerate and delete addresses not updated wrappedWorldView() @@ -304,7 +304,7 @@ public Optional getStorageValueBySlotHash(final Address address, final } @Override - public UInt256 getOriginalStorageValue(final Address address, final UInt256 storageKey) { + public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) { // TODO maybe log the read into the trie layer? if (storageToClear.contains(address)) { return UInt256.ZERO; @@ -318,7 +318,7 @@ public UInt256 getOriginalStorageValue(final Address address, final UInt256 stor if (updated != null) { return updated; } - final UInt256 original = value.getOriginal(); + final UInt256 original = value.getPrior(); if (original != null) { return original; } @@ -346,7 +346,7 @@ private void importIntoTrieLog(final TrieLogLayer layer, final Hash blockHash) { for (final Map.Entry> updatedAccount : accountsToUpdate.entrySet()) { final BonsaiValue bonsaiValue = updatedAccount.getValue(); - final BonsaiAccount oldValue = bonsaiValue.getOriginal(); + final BonsaiAccount oldValue = bonsaiValue.getPrior(); final StateTrieAccountValue oldAccount = oldValue == null ? null @@ -372,7 +372,7 @@ private void importIntoTrieLog(final TrieLogLayer layer, final Hash blockHash) { for (final Map.Entry> updatedCode : codeToUpdate.entrySet()) { layer.addCodeChange( updatedCode.getKey(), - updatedCode.getValue().getOriginal(), + updatedCode.getValue().getPrior(), updatedCode.getValue().getUpdated(), blockHash); } @@ -385,7 +385,7 @@ private void importIntoTrieLog(final TrieLogLayer layer, final Hash blockHash) { layer.addStorageChange( address, slotUpdate.getKey(), - slotUpdate.getValue().getOriginal(), + slotUpdate.getValue().getPrior(), slotUpdate.getValue().getUpdated()); } } @@ -397,13 +397,13 @@ public void rollForward(final TrieLogLayer layer) { .forEach( entry -> rollAccountChange( - entry.getKey(), entry.getValue().getOriginal(), entry.getValue().getUpdated())); + entry.getKey(), entry.getValue().getPrior(), entry.getValue().getUpdated())); layer .streamCodeChanges() .forEach( entry -> rollCodeChange( - entry.getKey(), entry.getValue().getOriginal(), entry.getValue().getUpdated())); + entry.getKey(), entry.getValue().getPrior(), entry.getValue().getUpdated())); layer .streamStorageChanges() .forEach( @@ -413,7 +413,7 @@ public void rollForward(final TrieLogLayer layer) { .forEach( (key, value) -> rollStorageChange( - entry.getKey(), key, value.getOriginal(), value.getUpdated()))); + entry.getKey(), key, value.getPrior(), value.getUpdated()))); } public void rollBack(final TrieLogLayer layer) { @@ -422,13 +422,13 @@ public void rollBack(final TrieLogLayer layer) { .forEach( entry -> rollAccountChange( - entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getOriginal())); + entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getPrior())); layer .streamCodeChanges() .forEach( entry -> rollCodeChange( - entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getOriginal())); + entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getPrior())); layer .streamStorageChanges() .forEach( @@ -438,10 +438,7 @@ public void rollBack(final TrieLogLayer layer) { .forEach( (slotHash, value) -> rollStorageChange( - entry.getKey(), - slotHash, - value.getUpdated(), - value.getOriginal()))); + entry.getKey(), slotHash, value.getUpdated(), value.getPrior()))); } private void rollAccountChange( @@ -480,7 +477,7 @@ private void rollAccountChange( "Address=" + address + " Prior Value in Rolling Change"); } if (replacementValue == null) { - if (accountValue.getOriginal() == null) { + if (accountValue.getPrior() == null) { accountsToUpdate.remove(address); } else { accountValue.setUpdated(null); @@ -545,7 +542,7 @@ private void rollCodeChange( expectedCode == null ? "null" : Hash.hash(expectedCode), Hash.hash(codeValue.getUpdated()))); } - if (replacementCode == null && codeValue.getOriginal() == null) { + if (replacementCode == null && codeValue.getPrior() == null) { codeToUpdate.remove(address); } else { codeValue.setUpdated(replacementCode); @@ -616,7 +613,7 @@ private void rollStorageChange( expectedValue == null ? "null" : expectedValue.toShortHexString(), existingSlotValue == null ? "null" : existingSlotValue.toShortHexString())); } - if (replacementValue == null && slotValue.getOriginal() == null) { + if (replacementValue == null && slotValue.getPrior() == null) { final Map> thisStorageUpdate = maybeCreateStorageMap(storageMap, address); thisStorageUpdate.remove(slotHash); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldView.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldView.java index 458f5c7d325..fa0ae6703df 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldView.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldView.java @@ -38,7 +38,7 @@ public interface BonsaiWorldView extends WorldView { Optional getStorageValueBySlotHash(Address address, Hash slotHash); - UInt256 getOriginalStorageValue(Address address, UInt256 key); + UInt256 getPriorStorageValue(Address address, UInt256 key); /** * Retrieve all the storage values of a account. diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java index cf76b29f960..b47d0c39d75 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/TrieLogLayer.java @@ -241,18 +241,18 @@ private static T nullOrValue(final RLPInput input, final Function getOriginalCode(final Address address) { - return Optional.ofNullable(code.get(address)).map(BonsaiValue::getOriginal); + public Optional getPriorCode(final Address address) { + return Optional.ofNullable(code.get(address)).map(BonsaiValue::getPrior); } public Optional getCode(final Address address) { return Optional.ofNullable(code.get(address)).map(BonsaiValue::getUpdated); } - Optional getOriginalStorageBySlotHash(final Address address, final Hash slotHash) { + Optional getPriorStorageBySlotHash(final Address address, final Hash slotHash) { return Optional.ofNullable(storage.get(address)) .map(i -> i.get(slotHash)) - .map(BonsaiValue::getOriginal); + .map(BonsaiValue::getPrior); } Optional getStorageBySlotHash(final Address address, final Hash slotHash) { @@ -261,8 +261,8 @@ Optional getStorageBySlotHash(final Address address, final Hash slotHas .map(BonsaiValue::getUpdated); } - public Optional getOriginalAccount(final Address address) { - return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getOriginal); + public Optional getPriorAccount(final Address address) { + return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getPrior); } public Optional getAccount(final Address address) { @@ -276,20 +276,20 @@ public String dump() { for (final Map.Entry> account : accounts.entrySet()) { sb.append(" : ").append(account.getKey()).append("\n"); - if (Objects.equals(account.getValue().getOriginal(), account.getValue().getUpdated())) { + if (Objects.equals(account.getValue().getPrior(), account.getValue().getUpdated())) { sb.append(" = ").append(account.getValue().getUpdated()).append("\n"); } else { - sb.append(" - ").append(account.getValue().getOriginal()).append("\n"); + sb.append(" - ").append(account.getValue().getPrior()).append("\n"); sb.append(" + ").append(account.getValue().getUpdated()).append("\n"); } } sb.append("code").append("\n"); for (final Map.Entry> code : code.entrySet()) { sb.append(" : ").append(code.getKey()).append("\n"); - if (Objects.equals(code.getValue().getOriginal(), code.getValue().getUpdated())) { - sb.append(" = ").append(code.getValue().getOriginal()).append("\n"); + if (Objects.equals(code.getValue().getPrior(), code.getValue().getUpdated())) { + sb.append(" = ").append(code.getValue().getPrior()).append("\n"); } else { - sb.append(" - ").append(code.getValue().getOriginal()).append("\n"); + sb.append(" - ").append(code.getValue().getPrior()).append("\n"); sb.append(" + ").append(code.getValue().getUpdated()).append("\n"); } } @@ -297,7 +297,7 @@ public String dump() { for (final Map.Entry>> storage : storage.entrySet()) { sb.append(" : ").append(storage.getKey()).append("\n"); for (final Map.Entry> slot : storage.getValue().entrySet()) { - final UInt256 originalValue = slot.getValue().getOriginal(); + final UInt256 originalValue = slot.getValue().getPrior(); final UInt256 updatedValue = slot.getValue().getUpdated(); sb.append(" : ").append(slot.getKey()).append("\n"); if (Objects.equals(originalValue, updatedValue)) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index 85cf387f3dd..1a92d2bb487 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -142,7 +142,7 @@ public Optional process( return Optional.empty(); } final MutableWorldState publicWorldState = - worldStateArchive.getWorldState(header.getStateRoot(), header.getHash()).orElse(null); + worldStateArchive.getMutable(header.getStateRoot(), header.getHash(), false).orElse(null); if (publicWorldState == null) { return Optional.empty(); @@ -216,7 +216,7 @@ private WorldUpdater getEffectiveWorldStateUpdater( public Optional doesAddressExistAtHead(final Address address) { final BlockHeader header = blockchain.getChainHeadHeader(); final MutableWorldState worldState = - worldStateArchive.getWorldState(header.getStateRoot(), header.getHash()).orElse(null); + worldStateArchive.getMutable(header.getStateRoot(), header.getHash(), false).orElse(null); return doesAddressExist(worldState, address, header); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultWorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultWorldStateArchive.java index 927a96f9a02..d0a4d378a3a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultWorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DefaultWorldStateArchive.java @@ -55,7 +55,15 @@ public boolean isWorldStateAvailable(final Hash rootHash, final Hash blockHash) } @Override - public Optional getWorldState(final Hash rootHash, final Hash blockHash) { + public Optional getMutable( + final long blockNumber, final boolean isPersistingState) { + throw new UnsupportedOperationException( + "Get mutable by block number is not available with the forest mode"); + } + + @Override + public Optional getMutable( + final Hash rootHash, final Hash blockHash, final boolean isPersistingState) { return getMutable(rootHash, blockHash); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java index 33dad01f80d..7b146f09041 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateArchive.java @@ -35,7 +35,9 @@ public interface WorldStateArchive { boolean isWorldStateAvailable(Hash rootHash, Hash blockHash); - Optional getWorldState(Hash rootHash, Hash blockHash); + Optional getMutable(long blockNumber, boolean isPersistingState); + + Optional getMutable(Hash rootHash, Hash blockHash, boolean isPersistingState); Optional getMutable(Hash rootHash, Hash blockHash); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index f56b161fd5d..3861b1d9d22 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -418,19 +418,19 @@ private void mockWorldStateForAccount( final Hash stateRoot, final Address address, final long nonce) { final Account account = mock(Account.class); when(account.getNonce()).thenReturn(nonce); - when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.get(eq(address))).thenReturn(account); } private void mockWorldStateForAbsentAccount(final Hash stateRoot) { - when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.get(any())).thenReturn(null); } private MutableAccount mockWorldUpdaterForAccount(final Hash stateRoot, final Address address) { final EvmAccount account = mock(EvmAccount.class); final MutableAccount mutableAccount = mock(MutableAccount.class); - when(worldStateArchive.getWorldState(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); when(worldState.updater()).thenReturn(worldUpdater); when(worldUpdater.getOrCreate(eq(address))).thenReturn(account); when(account.getMutable()).thenReturn(mutableAccount); From 2794427a3bff47301d8b0977daaa98285dda9e54 Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Thu, 11 Mar 2021 15:51:45 +0100 Subject: [PATCH 5/8] fix tests Signed-off-by: Karim TAAM --- .../ethereum/transaction/TransactionSimulatorTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index 3861b1d9d22..958d0391adb 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -418,19 +418,22 @@ private void mockWorldStateForAccount( final Hash stateRoot, final Address address, final long nonce) { final Account account = mock(Account.class); when(account.getNonce()).thenReturn(nonce); - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + .thenReturn(Optional.of(worldState)); when(worldState.get(eq(address))).thenReturn(account); } private void mockWorldStateForAbsentAccount(final Hash stateRoot) { - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + .thenReturn(Optional.of(worldState)); when(worldState.get(any())).thenReturn(null); } private MutableAccount mockWorldUpdaterForAccount(final Hash stateRoot, final Address address) { final EvmAccount account = mock(EvmAccount.class); final MutableAccount mutableAccount = mock(MutableAccount.class); - when(worldStateArchive.getMutable(eq(stateRoot), any())).thenReturn(Optional.of(worldState)); + when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + .thenReturn(Optional.of(worldState)); when(worldState.updater()).thenReturn(worldUpdater); when(worldUpdater.getOrCreate(eq(address))).thenReturn(account); when(account.getMutable()).thenReturn(mutableAccount); From 8c0c11bd1ffcda39591793e5c565ab606d50d85c Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Thu, 11 Mar 2021 16:59:16 +0100 Subject: [PATCH 6/8] fix tests Signed-off-by: Karim TAAM --- .../besu/ethereum/transaction/TransactionSimulatorTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index 958d0391adb..4756493afc1 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -418,13 +418,13 @@ private void mockWorldStateForAccount( final Hash stateRoot, final Address address, final long nonce) { final Account account = mock(Account.class); when(account.getNonce()).thenReturn(nonce); - when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + when(worldStateArchive.getMutable(eq(stateRoot), any(), anyBoolean())) .thenReturn(Optional.of(worldState)); when(worldState.get(eq(address))).thenReturn(account); } private void mockWorldStateForAbsentAccount(final Hash stateRoot) { - when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + when(worldStateArchive.getMutable(eq(stateRoot), any(), anyBoolean())) .thenReturn(Optional.of(worldState)); when(worldState.get(any())).thenReturn(null); } @@ -432,7 +432,7 @@ private void mockWorldStateForAbsentAccount(final Hash stateRoot) { private MutableAccount mockWorldUpdaterForAccount(final Hash stateRoot, final Address address) { final EvmAccount account = mock(EvmAccount.class); final MutableAccount mutableAccount = mock(MutableAccount.class); - when(worldStateArchive.getMutable(eq(stateRoot), any(), any())) + when(worldStateArchive.getMutable(eq(stateRoot), any(), anyBoolean())) .thenReturn(Optional.of(worldState)); when(worldState.updater()).thenReturn(worldUpdater); when(worldUpdater.getOrCreate(eq(address))).thenReturn(account); From 357dc966368c6b5ebd57abb4573ab6fc4fc54846 Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Thu, 11 Mar 2021 18:58:52 +0100 Subject: [PATCH 7/8] clean code Signed-off-by: Karim TAAM --- .../bonsai/BonsaiLayeredWorldState.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java index c42cf8cebd8..771c513d8d4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java @@ -88,11 +88,11 @@ public Optional getCode(final Address address) { BonsaiLayeredWorldState currentLayer = this; while (currentLayer != null) { final Optional maybeCode = currentLayer.trieLog.getCode(address); - final Optional maybeOriginalCode = currentLayer.trieLog.getPriorCode(address); + final Optional maybePriorCode = currentLayer.trieLog.getPriorCode(address); if (currentLayer == this && maybeCode.isPresent()) { return maybeCode; - } else if (maybeOriginalCode.isPresent()) { - return maybeOriginalCode; + } else if (maybePriorCode.isPresent()) { + return maybePriorCode; } else if (maybeCode.isPresent()) { return Optional.empty(); } @@ -137,12 +137,12 @@ public Optional getStorageValueBySlotHash(final Address address, final while (currentLayer != null) { final Optional maybeValue = currentLayer.trieLog.getStorageBySlotHash(address, slotHash); - final Optional maybeOriginalValue = + final Optional maybePriorValue = currentLayer.trieLog.getPriorStorageBySlotHash(address, slotHash); if (currentLayer == this && maybeValue.isPresent()) { return maybeValue; - } else if (maybeOriginalValue.isPresent()) { - return maybeOriginalValue; + } else if (maybePriorValue.isPresent()) { + return maybePriorValue; } else if (maybeValue.isPresent()) { return Optional.empty(); } @@ -213,14 +213,14 @@ public Account get(final Address address) { while (currentLayer != null) { final Optional maybeStateTrieAccount = currentLayer.trieLog.getAccount(address); - final Optional maybeOriginalStateTrieAccount = + final Optional maybePriorStateTrieAccount = currentLayer.trieLog.getPriorAccount(address); if (currentLayer == this && maybeStateTrieAccount.isPresent()) { return new BonsaiAccount( BonsaiLayeredWorldState.this, address, maybeStateTrieAccount.get(), false); - } else if (maybeOriginalStateTrieAccount.isPresent()) { + } else if (maybePriorStateTrieAccount.isPresent()) { return new BonsaiAccount( - BonsaiLayeredWorldState.this, address, maybeOriginalStateTrieAccount.get(), false); + BonsaiLayeredWorldState.this, address, maybePriorStateTrieAccount.get(), false); } else if (maybeStateTrieAccount.isPresent()) { return null; } From c69fc7d4ec9e1eff6c37e8a6da82d7043b94654f Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Thu, 11 Mar 2021 19:01:50 +0100 Subject: [PATCH 8/8] fix getNextWorldView Signed-off-by: Karim TAAM --- .../besu/ethereum/bonsai/BonsaiLayeredWorldState.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java index 771c513d8d4..56f83bffa29 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiLayeredWorldState.java @@ -64,9 +64,10 @@ public class BonsaiLayeredWorldState implements MutableWorldState, BonsaiWorldVi public Optional getNextWorldView() { if (nextWorldView.isEmpty()) { final Optional blockHashByNumber = blockchain.getBlockHashByNumber(height + 1); - blockHashByNumber - .map(hash -> archive.getMutable(null, hash, false).map(BonsaiWorldView.class::cast)) - .orElseGet(() -> Optional.of(archive.getMutable()).map(BonsaiWorldView.class::cast)); + nextWorldView = + blockHashByNumber + .map(hash -> archive.getMutable(null, hash, false).map(BonsaiWorldView.class::cast)) + .orElseGet(() -> Optional.of(archive.getMutable()).map(BonsaiWorldView.class::cast)); } return nextWorldView; }