From 4e6b1fbd25233b20474cb97078f06df92fba89ff Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 19 Sep 2023 17:07:09 -0600 Subject: [PATCH 01/10] Add updated storage to evmtool json trace (#5892) Add the EIP-3155 "storage" option to the standard tracer, with the caveat only updated storage is logged. Signed-off-by: Danno Ferrin --- .../internal/processor/TransactionTracer.java | 36 +++++----- .../besu/evmtool/EvmToolCommand.java | 14 +++- .../besu/evmtool/StateTestSubCommand.java | 3 +- .../besu/evmtool/T8nSubCommand.java | 3 +- .../besu/evm/tracing/StandardJsonTracer.java | 57 +++++++++++++--- .../besu/evm/StandardJsonTracerTest.java | 68 ++++++++++++++----- .../besu/evm/toy/EvmToyCommand.java | 9 ++- 7 files changed, 140 insertions(+), 50 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java index 71628c88969..2811a01135b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java @@ -69,24 +69,22 @@ public Optional traceTransaction( final Hash blockHash, final Hash transactionHash, final DebugOperationTracer tracer) { - Optional transactionTrace = - blockReplay.beforeTransactionInBlock( - mutableWorldState, - blockHash, - transactionHash, - (transaction, header, blockchain, transactionProcessor, blobGasPrice) -> { - final TransactionProcessingResult result = - processTransaction( - header, - blockchain, - mutableWorldState.updater(), - transaction, - transactionProcessor, - tracer, - blobGasPrice); - return new TransactionTrace(transaction, result, tracer.getTraceFrames()); - }); - return transactionTrace; + return blockReplay.beforeTransactionInBlock( + mutableWorldState, + blockHash, + transactionHash, + (transaction, header, blockchain, transactionProcessor, blobGasPrice) -> { + final TransactionProcessingResult result = + processTransaction( + header, + blockchain, + mutableWorldState.updater(), + transaction, + transactionProcessor, + tracer, + blobGasPrice); + return new TransactionTrace(transaction, result, tracer.getTraceFrames()); + }); } public List traceTransactionToFile( @@ -139,7 +137,7 @@ public List traceTransactionToFile( stackedUpdater, transaction, transactionProcessor, - new StandardJsonTracer(out, showMemory, true, true), + new StandardJsonTracer(out, showMemory, true, true, false), blobGasPrice); out.println( summaryTrace( 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 d41dd56093b..0e2daf96eb6 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 @@ -181,6 +181,14 @@ void setBytes(final String optionValue) { negatable = true) final Boolean showReturnData = false; + @Option( + names = {"--trace.storage"}, + description = + "Show the updated storage slots for the current account. Default is to not show updated storage.", + scope = INHERIT, + negatable = true) + final Boolean showStorage = false; + @Option( names = {"--notime"}, description = "Don't include time data in summary output.", @@ -365,7 +373,7 @@ public void run() { final OperationTracer tracer = // You should have picked Mercy. lastLoop && showJsonResults - ? new StandardJsonTracer(out, showMemory, !hideStack, showReturnData) + ? new StandardJsonTracer(out, showMemory, !hideStack, showReturnData, showStorage) : OperationTracer.NO_TRACING; WorldUpdater updater = component.getWorldUpdater(); @@ -466,10 +474,10 @@ public static void dumpWorldState(final WorldState worldState, final PrintWriter " \"" + accountStorageEntry .getKey() - .map(UInt256::toHexString) + .map(UInt256::toQuantityHexString) .orElse("-") + "\": \"" - + accountStorageEntry.getValue().toHexString() + + accountStorageEntry.getValue().toQuantityHexString() + "\"") .toList())); out.println(" },"); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index 2bc5f815309..a2d966f0675 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -182,7 +182,8 @@ private void traceTestSpecs(final String test, final List stack; @@ -52,6 +53,7 @@ public class StandardJsonTracer implements OperationTracer { private Bytes memory; private int memorySize; private int depth; + private String storageString; /** * Instantiates a new Standard json tracer. @@ -60,16 +62,19 @@ public class StandardJsonTracer implements OperationTracer { * @param showMemory show memory in trace lines * @param showStack show the stack in trace lines * @param showReturnData show return data in trace lines + * @param showStorage show the updated storage */ public StandardJsonTracer( final PrintWriter out, final boolean showMemory, final boolean showStack, - final boolean showReturnData) { + final boolean showReturnData, + final boolean showStorage) { this.out = out; this.showMemory = showMemory; this.showStack = showStack; this.showReturnData = showReturnData; + this.showStorage = showStorage; } /** @@ -79,13 +84,20 @@ public StandardJsonTracer( * @param showMemory show memory in trace lines * @param showStack show the stack in trace lines * @param showReturnData show return data in trace lines + * @param showStorage show updated storage */ public StandardJsonTracer( final PrintStream out, final boolean showMemory, final boolean showStack, - final boolean showReturnData) { - this(new PrintWriter(out, true, StandardCharsets.UTF_8), showMemory, showStack, showReturnData); + final boolean showReturnData, + final boolean showStorage) { + this( + new PrintWriter(out, true, StandardCharsets.UTF_8), + showMemory, + showStack, + showReturnData, + showStorage); } /** @@ -130,6 +142,33 @@ public void tracePreExecution(final MessageFrame messageFrame) { memory = null; } depth = messageFrame.getMessageStackSize(); + + StringBuilder sb = new StringBuilder(); + if (showStorage) { + var updater = messageFrame.getWorldUpdater(); + var account = updater.getAccount(messageFrame.getRecipientAddress()); + if (account != null && !account.getUpdatedStorage().isEmpty()) { + boolean[] shownEntry = {false}; + sb.append(",\"storage\":{"); + account + .getUpdatedStorage() + .forEach( + (k, v) -> { + if (shownEntry[0]) { + sb.append(","); + } else { + shownEntry[0] = true; + } + sb.append("\"") + .append(k.toQuantityHexString()) + .append("\":\"") + .append(v.toQuantityHexString()) + .append("\""); + }); + sb.append("}"); + } + } + storageString = sb.toString(); } @Override @@ -155,7 +194,7 @@ public void tracePostExecution( if (showStack) { sb.append("\"stack\":[").append(commaJoiner.join(stack)).append("],"); } - if (showReturnData && returnData.size() > 0) { + if (showReturnData && !returnData.isEmpty()) { sb.append("\"returnData\":\"").append(returnData.toHexString()).append("\","); } sb.append("\"depth\":").append(depth).append(","); @@ -164,14 +203,14 @@ public void tracePostExecution( if (executeResult.getHaltReason() != null) { sb.append(",\"error\":\"") .append(executeResult.getHaltReason().getDescription()) - .append("\"}"); + .append("\""); } else if (messageFrame.getRevertReason().isPresent()) { sb.append(",\"error\":\"") .append(quoteEscape(messageFrame.getRevertReason().orElse(Bytes.EMPTY))) - .append("\"}"); - } else { - sb.append("}"); + .append("\""); } + + sb.append(storageString).append("}"); out.println(sb); } @@ -229,7 +268,7 @@ public void traceEndTransaction( final long timeNs) { final StringBuilder sb = new StringBuilder(1024); sb.append("{"); - if (output.size() > 0) { + if (!output.isEmpty()) { sb.append("\"output\":\"").append(output.toShortHexString()).append("\","); } else { sb.append("\"output\":\"\","); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java index a65ab05d62a..9ba9ebf96ae 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java @@ -38,7 +38,7 @@ void eip3155ModifiedTestCase() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream out = new PrintStream(baos); var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); - StandardJsonTracer tracer = new StandardJsonTracer(out, true, true, true); + StandardJsonTracer tracer = new StandardJsonTracer(out, true, true, true, false); executor.tracer(tracer); executor.gas(10_000_000_000L); @@ -58,20 +58,56 @@ void eip3155ModifiedTestCase() { // (g) if error is zero length or null it is not included. assertThat(baos) .hasToString( - "{\"pc\":0,\"op\":96,\"gas\":\"0x2540be400\",\"gasCost\":\"0x3\",\"memSize\":0,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":2,\"op\":128,\"gas\":\"0x2540be3fd\",\"gasCost\":\"0x3\",\"memSize\":0,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"DUP1\"}\n" - + "{\"pc\":3,\"op\":83,\"gas\":\"0x2540be3fa\",\"gasCost\":\"0xc\",\"memSize\":0,\"stack\":[\"0x40\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"MSTORE8\"}\n" - + "{\"pc\":4,\"op\":96,\"gas\":\"0x2540be3ee\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":6,\"op\":96,\"gas\":\"0x2540be3eb\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":8,\"op\":85,\"gas\":\"0x2540be3e8\",\"gasCost\":\"0x4e20\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"SSTORE\"}\n" - + "{\"pc\":9,\"op\":96,\"gas\":\"0x2540b95c8\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":11,\"op\":96,\"gas\":\"0x2540b95c5\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":13,\"op\":96,\"gas\":\"0x2540b95c2\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":15,\"op\":96,\"gas\":\"0x2540b95bf\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":17,\"op\":96,\"gas\":\"0x2540b95bc\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":19,\"op\":90,\"gas\":\"0x2540b95b9\",\"gasCost\":\"0x2\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\",\"0x2\"],\"depth\":1,\"refund\":0,\"opName\":\"GAS\"}\n" - + "{\"pc\":20,\"op\":250,\"gas\":\"0x2540b95b7\",\"gasCost\":\"0x2bc\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\",\"0x2\",\"0x2540b95b7\"],\"depth\":1,\"refund\":0,\"opName\":\"STATICCALL\"}\n" - + "{\"pc\":21,\"op\":96,\"gas\":\"0x2540b92a7\",\"gasCost\":\"0x3\",\"memory\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x1\"],\"returnData\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b\",\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":23,\"op\":243,\"gas\":\"0x2540b92a4\",\"gasCost\":\"0x0\",\"memory\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x1\",\"0x40\"],\"returnData\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b\",\"depth\":1,\"refund\":0,\"opName\":\"RETURN\"}\n"); + """ + {"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":2,"op":128,"gas":"0x2540be3fd","gasCost":"0x3","memSize":0,"stack":["0x40"],"depth":1,"refund":0,"opName":"DUP1"} + {"pc":3,"op":83,"gas":"0x2540be3fa","gasCost":"0xc","memSize":0,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"MSTORE8"} + {"pc":4,"op":96,"gas":"0x2540be3ee","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":6,"op":96,"gas":"0x2540be3eb","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":8,"op":85,"gas":"0x2540be3e8","gasCost":"0x4e20","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"SSTORE"} + {"pc":9,"op":96,"gas":"0x2540b95c8","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":11,"op":96,"gas":"0x2540b95c5","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":13,"op":96,"gas":"0x2540b95c2","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":15,"op":96,"gas":"0x2540b95bf","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":17,"op":96,"gas":"0x2540b95bc","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":19,"op":90,"gas":"0x2540b95b9","gasCost":"0x2","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2"],"depth":1,"refund":0,"opName":"GAS"} + {"pc":20,"op":250,"gas":"0x2540b95b7","gasCost":"0x2bc","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2","0x2540b95b7"],"depth":1,"refund":0,"opName":"STATICCALL"} + {"pc":21,"op":96,"gas":"0x2540b92a7","gasCost":"0x3","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1"],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"PUSH1"} + {"pc":23,"op":243,"gas":"0x2540b92a4","gasCost":"0x0","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1","0x40"],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"RETURN"} + """); + } + + @Test + void updatedStorageTestCase() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(baos); + var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); + StandardJsonTracer tracer = new StandardJsonTracer(out, false, false, false, true); + executor.tracer(tracer); + executor.gas(10_000_000_000L); + + var codeBytes = Bytes.fromHexString("0x604080536040604055604060006040600060025afa6040f3"); + executor.execute(codeBytes, Bytes.EMPTY, Wei.ZERO, Address.ZERO); + + assertThat(baos) + .hasToString( + """ + {"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memSize":0,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":2,"op":128,"gas":"0x2540be3fd","gasCost":"0x3","memSize":0,"depth":1,"refund":0,"opName":"DUP1"} + {"pc":3,"op":83,"gas":"0x2540be3fa","gasCost":"0xc","memSize":0,"depth":1,"refund":0,"opName":"MSTORE8"} + {"pc":4,"op":96,"gas":"0x2540be3ee","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":6,"op":96,"gas":"0x2540be3eb","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":8,"op":85,"gas":"0x2540be3e8","gasCost":"0x4e20","memSize":96,"depth":1,"refund":0,"opName":"SSTORE"} + {"pc":9,"op":96,"gas":"0x2540b95c8","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":11,"op":96,"gas":"0x2540b95c5","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":13,"op":96,"gas":"0x2540b95c2","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":15,"op":96,"gas":"0x2540b95bf","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":17,"op":96,"gas":"0x2540b95bc","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":19,"op":90,"gas":"0x2540b95b9","gasCost":"0x2","memSize":96,"depth":1,"refund":0,"opName":"GAS","storage":{"0x40":"0x40"}} + {"pc":20,"op":250,"gas":"0x2540b95b7","gasCost":"0x2bc","memSize":96,"depth":1,"refund":0,"opName":"STATICCALL","storage":{"0x40":"0x40"}} + {"pc":21,"op":96,"gas":"0x2540b92a7","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":23,"op":243,"gas":"0x2540b92a4","gasCost":"0x0","memSize":96,"depth":1,"refund":0,"opName":"RETURN","storage":{"0x40":"0x40"}} + """); } } diff --git a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java index 76934e041f0..368dbffabd0 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java @@ -122,6 +122,12 @@ public class EvmToyCommand implements Runnable { scope = ScopeType.INHERIT) final Boolean showReturnData = false; + @CommandLine.Option( + names = {"--trace.storage"}, + description = "When tracing, show the updated storage contents.", + scope = ScopeType.INHERIT) + final Boolean showStorage = false; + @CommandLine.Option( names = {"--repeat"}, description = "Number of times to repeat for benchmarking.") @@ -164,7 +170,8 @@ public void run() { final OperationTracer tracer = // You should have picked Mercy. lastLoop && showJsonResults - ? new StandardJsonTracer(System.out, showMemory, showStack, showReturnData) + ? new StandardJsonTracer( + System.out, showMemory, showStack, showReturnData, showStorage) : OperationTracer.NO_TRACING; MessageFrame initialMessageFrame = From cedcb5c9bd684e8877d1b8ff7094f6998a93c5b8 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Wed, 20 Sep 2023 10:11:40 +1000 Subject: [PATCH 02/10] Update holesky with fixed extraData, genesis time, shanghaiTime (#5890) Signed-off-by: Simon Dudley --- CHANGELOG.md | 4 +- .../besu/ForkIdsNetworkConfigTest.java | 7 +- config/src/main/resources/holesky.json | 369 +++++++++--------- 3 files changed, 189 insertions(+), 191 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 669a819c586..552c104c398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ # Changelog ## 23.7.3 -### Additions and Improvements -- Add access to an immutable world view to start/end transaction hooks in the tracing API[#5836](https://github.com/hyperledger/besu/pull/5836) ### Breaking Changes - Removed support for Kotti network (ETC) [#5816](https://github.com/hyperledger/besu/pull/5816) @@ -11,8 +9,10 @@ - `--Xlayered-tx-pool-layer-max-capacity`, `--Xlayered-tx-pool-max-prioritized` and `--Xlayered-tx-pool-max-future-by-sender` just drop the `X` and keep the same behavior ### Additions and Improvements +- Add access to an immutable world view to start/end transaction hooks in the tracing API[#5836](https://github.com/hyperledger/besu/pull/5836) - Layered transaction pool implementation is now stable and enabled by default. If you want still to use the legacy implementation, use `--tx-pool=legacy` [#5772](https://github.com/hyperledger/besu) - Tune G1GC to reduce Besu memory footprint, and new `besu-untuned` start scripts to run without any specific G1GC flags [#5879](https://github.com/hyperledger/besu/pull/5879) +- Update Holesky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890) ### Bug Fixes - do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830) diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java index df5607120e5..bfa55c261aa 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java @@ -84,10 +84,9 @@ public static Collection parameters() { new Object[] { NetworkName.HOLESKY, List.of( - new ForkId(Bytes.ofUnsignedInt(0xa200f558L), 1694790240L), - new ForkId(Bytes.ofUnsignedInt(0x840a3b53L), 2000000000L), - new ForkId(Bytes.ofUnsignedInt(0x30771f90), 0L), - new ForkId(Bytes.ofUnsignedInt(0x30771f90), 0L)) + new ForkId(Bytes.ofUnsignedInt(0xc61a6098L), 1696000704L), + new ForkId(Bytes.ofUnsignedInt(0xfd4f016bL), 0L), + new ForkId(Bytes.ofUnsignedInt(0xfd4f016bL), 0L)) }, new Object[] { NetworkName.GOERLI, diff --git a/config/src/main/resources/holesky.json b/config/src/main/resources/holesky.json index 0b3c875fba2..a8ae193c856 100644 --- a/config/src/main/resources/holesky.json +++ b/config/src/main/resources/holesky.json @@ -13,9 +13,8 @@ "londonBlock": 0, "preMergeForkBlock": 0, "terminalTotalDifficulty": 0, - "shanghaiTime": 1694790240, + "shanghaiTime": 1696000704, "ethash": {}, - "cancunTime": 2000000000, "discovery": { "bootnodes": [ "enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303", @@ -827,196 +826,196 @@ "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" - }, - "0x0000006916a87b82333f4245046623b23794C65C": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x0be949928Ff199c9EBA9E110db210AA5C94EFAd0": { - "balance": "0x7c13bc4b2c133c56000000" - }, - "0x0C100000006d7b5e23a1eAEE637f28cA32Cd5b31": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x0C35317B7a96C454E2CB3d1A255D775Ab112cCc8": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x0d731cfabC5574329823F26d488416451d2ea376": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x0e79065B5F11b5BD1e62B935A600976ffF3754B9": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x105083929bF9bb22C26cB1777Ec92661170D4285": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x10F5d45854e038071485AC9e402308cF80D2d2fE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x1268AD189526AC0b386faF06eFfC46779c340eE6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x12Cba59f5A74DB81a12ff63C349Bd82CBF6007C2": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x1446D7f6dF00380F246d8211dE7f0FaBC4Fd248C": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x164e38a375247A784A81d420201AA8fe4E513921": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x1B7aA44088a0eA95bdc65fef6E5071E946Bf7d8f": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x222222222222cF64a76AE3d36859958c864fDA2c": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x2f14582947E292a2eCd20C430B46f2d27CFE213c": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x2f2c75B5Dd5D246194812b00eEb3B09c2c66e2eE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x341c40b94bf2afbfa42573cb78f16ee15a056238": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x34f845773D4364999f2fbC7AA26ABDeE902cBb46": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x3C75594181e03E8ECD8468A0037F058a9dAfad79": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x462396E69dBfa455F405f4DD82F3014Af8003B72": { - "balance": "0xa56fa5b99019a5c8000000" - }, - "0x49Df3CCa2670eB0D591146B16359fe336e476F29": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4D0b04b405c6b62C7cFC3aE54759747e2C0b4662": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4D496CcC28058B1D74B7a19541663E21154f9c84": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x509a7667aC8D0320e36172c192506a6188aA84f6": { - "balance": "0x7c13bc4b2c133c56000000" - }, - "0x5180db0237291A6449DdA9ed33aD90a38787621c": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x52730f347dEf6BA09adfF62EaC60D5fEe8205BC4": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x5EAC0fBd3dfef8aE3efa3c5dc1aa193bc6033dFd": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x6a7aA9b882d50Bb7bc5Da1a244719C99f12F06a3": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x6Cc9397c3B38739daCbfaA68EaD5F5D77Ba5F455": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x762cA62ca2549ad806763B3Aa1eA317c429bDBDa": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x778F5F13C4Be78A3a4d7141BCB26999702f407CF": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x875D25Ee4bC604C71BaF6236a8488F22399BED4b": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x8dF7878d3571BEF5e5a744F96287C8D20386d75A": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x9E415A096fF77650dc925dEA546585B4adB322B6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xA0766B65A4f7B1da79a1AF79aC695456eFa28644": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xA29B144A449E414A472c60C7AAf1aaFfE329021D": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xa55395566b0b54395B3246f96A0bDc4b8a483df9": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xAC9ba72fb61aA7c31A95df0A8b6ebA6f41EF875e": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xB0498C15879db2eE5471d4926c5fAA25C9a09683": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xB19Fb4c1f280327e60Ed37b1Dc6EE77533539314": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xC21cB9C99C316d1863142F7dD86dd5496D81A8D6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xc473d412dc52e349862209924c8981b2ee420768": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xC48E23C5F6e1eA0BaEf6530734edC3968f79Af2e": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xc6e2459991BfE27cca6d86722F35da23A1E4Cb97": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xD3994e4d3202dD23c8497d7F75bF1647d1DA1bb1": { - "balance": "0x19D971E4FE8401E74000000" - }, - "0xDCA6e9B48Ea86AeBFDf9929949124042296b6e34": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xe0a2Bd4258D2768837BAa26A28fE71Dc079f84c7": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xEA28d002042fd9898D0Db016be9758eeAFE35C1E": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xEfA7454f1116807975A4750B46695E967850de5D": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xFBFd6Fa9F73Ac6A058E01259034C28001BEf8247": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xe0991E844041bE6F11B99da5b114b6bCf84EBd57": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x15E719b6AcAf1E4411Bf0f9576CB1D0dB161DdFc": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x346D827a75F98F0A7a324Ff80b7C3F90252E8baC": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x73b2e0E54510239E22cC936F0b4a6dE1acf0AbdE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xBb977B2EE8a111D788B3477D242078d0B837E72b": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x834Dbf5A03e29c25bc55459cCe9c021EeBE676Ad": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xD1F77E4C1C45186e8653C489F90e008a73597296": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xb04aeF2a3d2D86B01006cCD4339A2e943d9c6480": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xC9CA2bA9A27De1Db589d8c33Ab8EDFa2111b31fb": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4BC656B34De23896fa6069C9862F355b740401aF": { - "balance": "0x084595161401484a000000" } + }, + "0x0000006916a87b82333f4245046623b23794C65C": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x0be949928Ff199c9EBA9E110db210AA5C94EFAd0": { + "balance": "0x7c13bc4b2c133c56000000" + }, + "0x0C100000006d7b5e23a1eAEE637f28cA32Cd5b31": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x0C35317B7a96C454E2CB3d1A255D775Ab112cCc8": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x0d731cfabC5574329823F26d488416451d2ea376": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x0e79065B5F11b5BD1e62B935A600976ffF3754B9": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x105083929bF9bb22C26cB1777Ec92661170D4285": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x10F5d45854e038071485AC9e402308cF80D2d2fE": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x1268AD189526AC0b386faF06eFfC46779c340eE6": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x12Cba59f5A74DB81a12ff63C349Bd82CBF6007C2": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x1446D7f6dF00380F246d8211dE7f0FaBC4Fd248C": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x164e38a375247A784A81d420201AA8fe4E513921": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x1B7aA44088a0eA95bdc65fef6E5071E946Bf7d8f": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x222222222222cF64a76AE3d36859958c864fDA2c": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x2f14582947E292a2eCd20C430B46f2d27CFE213c": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x2f2c75B5Dd5D246194812b00eEb3B09c2c66e2eE": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x341c40b94bf2afbfa42573cb78f16ee15a056238": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x34f845773D4364999f2fbC7AA26ABDeE902cBb46": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x3C75594181e03E8ECD8468A0037F058a9dAfad79": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x462396E69dBfa455F405f4DD82F3014Af8003B72": { + "balance": "0xa56fa5b99019a5c8000000" + }, + "0x49Df3CCa2670eB0D591146B16359fe336e476F29": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x4D0b04b405c6b62C7cFC3aE54759747e2C0b4662": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x4D496CcC28058B1D74B7a19541663E21154f9c84": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x509a7667aC8D0320e36172c192506a6188aA84f6": { + "balance": "0x7c13bc4b2c133c56000000" + }, + "0x5180db0237291A6449DdA9ed33aD90a38787621c": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x52730f347dEf6BA09adfF62EaC60D5fEe8205BC4": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x5EAC0fBd3dfef8aE3efa3c5dc1aa193bc6033dFd": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x6a7aA9b882d50Bb7bc5Da1a244719C99f12F06a3": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x6Cc9397c3B38739daCbfaA68EaD5F5D77Ba5F455": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x762cA62ca2549ad806763B3Aa1eA317c429bDBDa": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x778F5F13C4Be78A3a4d7141BCB26999702f407CF": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x875D25Ee4bC604C71BaF6236a8488F22399BED4b": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x8dF7878d3571BEF5e5a744F96287C8D20386d75A": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0x9E415A096fF77650dc925dEA546585B4adB322B6": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xA0766B65A4f7B1da79a1AF79aC695456eFa28644": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xA29B144A449E414A472c60C7AAf1aaFfE329021D": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xa55395566b0b54395B3246f96A0bDc4b8a483df9": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xAC9ba72fb61aA7c31A95df0A8b6ebA6f41EF875e": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xB0498C15879db2eE5471d4926c5fAA25C9a09683": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xB19Fb4c1f280327e60Ed37b1Dc6EE77533539314": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xC21cB9C99C316d1863142F7dD86dd5496D81A8D6": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xc473d412dc52e349862209924c8981b2ee420768": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xC48E23C5F6e1eA0BaEf6530734edC3968f79Af2e": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xc6e2459991BfE27cca6d86722F35da23A1E4Cb97": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xD3994e4d3202dD23c8497d7F75bF1647d1DA1bb1": { + "balance": "0x19D971E4FE8401E74000000" + }, + "0xDCA6e9B48Ea86AeBFDf9929949124042296b6e34": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xe0a2Bd4258D2768837BAa26A28fE71Dc079f84c7": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xEA28d002042fd9898D0Db016be9758eeAFE35C1E": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xEfA7454f1116807975A4750B46695E967850de5D": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xFBFd6Fa9F73Ac6A058E01259034C28001BEf8247": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xe0991E844041bE6F11B99da5b114b6bCf84EBd57": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x15E719b6AcAf1E4411Bf0f9576CB1D0dB161DdFc": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x346D827a75F98F0A7a324Ff80b7C3F90252E8baC": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x73b2e0E54510239E22cC936F0b4a6dE1acf0AbdE": { + "balance": "0x52b7d2dcc80cd2e4000000" + }, + "0xBb977B2EE8a111D788B3477D242078d0B837E72b": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x834Dbf5A03e29c25bc55459cCe9c021EeBE676Ad": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xD1F77E4C1C45186e8653C489F90e008a73597296": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xb04aeF2a3d2D86B01006cCD4339A2e943d9c6480": { + "balance": "0xd3c21bcecceda1000000" + }, + "0xC9CA2bA9A27De1Db589d8c33Ab8EDFa2111b31fb": { + "balance": "0xd3c21bcecceda1000000" + }, + "0x4BC656B34De23896fa6069C9862F355b740401aF": { + "balance": "0x084595161401484a000000" } }, "coinbase": "0x0000000000000000000000000000000000000000", "baseFeePerGas": "0x3B9ACA00", "difficulty": "0x01", - "extraData": "0x686f77206d7563682069732074686520666973683f", + "extraData": "", "gasLimit": "0x17D7840", "nonce": "0x1234", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "1694786100" -} + "timestamp": "1695902100" +} \ No newline at end of file From eef40bd530d8939b56f67c990a7cdf536b7521a7 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Wed, 20 Sep 2023 13:40:09 +1000 Subject: [PATCH 03/10] [CHANGELOG] removed duplicated line (#5904) * removed duplicated line [skip ci] Signed-off-by: Sally MacFarlane * fixed spelling on Holesky Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 552c104c398..bb5eb3ab885 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,11 @@ - Add access to an immutable world view to start/end transaction hooks in the tracing API[#5836](https://github.com/hyperledger/besu/pull/5836) - Layered transaction pool implementation is now stable and enabled by default. If you want still to use the legacy implementation, use `--tx-pool=legacy` [#5772](https://github.com/hyperledger/besu) - Tune G1GC to reduce Besu memory footprint, and new `besu-untuned` start scripts to run without any specific G1GC flags [#5879](https://github.com/hyperledger/besu/pull/5879) -- Update Holesky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890) +- Update Holešky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890) ### Bug Fixes - do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830) - fix duplicate key errors in EthScheduler-Transactions [#5857](https://github.com/hyperledger/besu/pull/5857) -- do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830) ### Download Links From 2dccfe7ce977cf5d7154f4c16f1cb21b93e8ea60 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Thu, 21 Sep 2023 06:34:27 +1000 Subject: [PATCH 04/10] Bump version to 23.7.4-SNAPSHOT (#5913) Signed-off-by: Simon Dudley --- CHANGELOG.md | 14 +++++++++++++- gradle.properties | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5eb3ab885..fa78e26a4eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## Next release + +### Breaking Changes + +### Additions and Improvements + +### Bug Fixes + +### Download Links + + ## 23.7.3 ### Breaking Changes @@ -44,7 +55,8 @@ - Fixing snapsync issue with forest during the heal step [#5776](https://github.com/hyperledger/besu/pull/5776) ### Download Links - +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.2/besu-23.7.2.tar.gz / sha256: f74b32c1a343cbad90a88aa59276b4c5eefea4643ee542aba2bbf898f85ae242 +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.2/besu-23.7.2.zip / sha256: a233c83591fc277e3d1530c84bb5ea896abad717d796b5e3b856c79199132b75 ## 23.7.1 diff --git a/gradle.properties b/gradle.properties index 32a11f7cc8c..4c525f654b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=23.7.3-SNAPSHOT +version=23.7.4-SNAPSHOT org.gradle.welcome=never # Set exports/opens flags required by Google Java Format and ErrorProne plugins. (JEP-396) From db8bd9d2af40a64c835240abb929a0e5b4046d68 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 20 Sep 2023 22:35:31 -0600 Subject: [PATCH 05/10] Update reference tests to 12.4 (#5899) * Update reference tests to 12.4 Update reference tests to 12.4 * Some in-memory storage changed to ConcurrentMap * exclude cancun from all EIP tests, EIP-4788 still in flux * Add new fields to ReferenceTestEnv, and re-order the reflected constructor for clarity and ease of development. Signed-off-by: Danno Ferrin * spotless Signed-off-by: Danno Ferrin --------- Signed-off-by: Danno Ferrin Co-authored-by: Sally MacFarlane --- ethereum/referencetests/build.gradle | 2 +- .../referencetests/ReferenceTestEnv.java | 45 ++++++++++--------- .../src/reference-test/external-resources | 2 +- .../vm/BlockchainReferenceTestTools.java | 3 ++ .../kvstore/InMemoryKeyValueStorage.java | 8 ++-- .../kvstore/LayeredKeyValueStorage.java | 3 +- .../SegmentedInMemoryKeyValueStorage.java | 16 ++++--- 7 files changed, 47 insertions(+), 32 deletions(-) diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index cf1a6e1f8a8..dc3e0165017 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -198,7 +198,7 @@ tasks.register('validateReferenceTestSubmodule') { description = "Checks that the reference tests submodule is not accidentally changed" doLast { def result = new ByteArrayOutputStream() - def expectedHash = '06e276776bc87817c38f6efb492bf6f4527fa904' + def expectedHash = '661356317ac6df52208d54187e692472a25a01f8' def submodulePath = java.nio.file.Path.of("${rootProject.projectDir}", "ethereum/referencetests/src/reference-test/external-resources").toAbsolutePath() try { exec { diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java index 5f7af60719a..bac137b2a58 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java @@ -97,33 +97,35 @@ Withdrawal asWithdrawal() { */ @JsonCreator public ReferenceTestEnv( + @JsonProperty("beaconRoot") final String beaconRoot, + @JsonProperty("blockHashes") final Map blockHashes, + @JsonProperty("ommers") final List _ommers, + @JsonProperty("previousHash") final String previousHash, + @JsonProperty("withdrawals") final List withdrawals, + @JsonProperty("currentBaseFee") final String baseFee, + @JsonProperty("currentBeaconRoot") final String currentBeaconRoot, + @JsonProperty("currentBlobGasUsed") final String currentBlobGasUsed, @JsonProperty("currentCoinbase") final String coinbase, + @JsonProperty("currentDataGasUsed") final String currentDataGasUsed, @JsonProperty("currentDifficulty") final String difficulty, + @JsonProperty("currentExcessBlobGas") final String currentExcessBlobGas, + @JsonProperty("currentExcessDataGas") final String currentExcessDataGas, @JsonProperty("currentGasLimit") final String gasLimit, @JsonProperty("currentNumber") final String number, - @JsonProperty("currentBaseFee") final String baseFee, - @JsonProperty("currentTimestamp") final String timestamp, @JsonProperty("currentRandom") final String random, @JsonProperty("currentStateRoot") final String stateRoot, - @JsonProperty("previousHash") final String previousHash, - @JsonProperty("parentDifficulty") final String parentDifficulty, + @JsonProperty("currentTimestamp") final String timestamp, + @JsonProperty("currentWithdrawalsRoot") final String currentWithdrawalsRoot, @JsonProperty("parentBaseFee") final String parentBaseFee, - @JsonProperty("parentGasUsed") final String parentGasUsed, - @JsonProperty("parentGasLimit") final String parentGasLimit, - @JsonProperty("parentTimestamp") final String parentTimestamp, - @JsonProperty("ommers") final List _ommers, - @JsonProperty("parentUncleHash") final String _parentUncleHash, - @JsonProperty("withdrawals") final List withdrawals, - @JsonProperty("blockHashes") final Map blockHashes, - @JsonProperty("currentExcessBlobGas") final String currentExcessBlobGas, - @JsonProperty("currentBlobGasUsed") final String currentBlobGasUsed, - @JsonProperty("currentExcessDataGas") final String currentExcessDataGas, - @JsonProperty("currentDataGasUsed") final String currentDataGasUsed, - @JsonProperty("parentExcessBlobGas") final String parentExcessBlobGas, @JsonProperty("parentBlobGasUsed") final String parentBlobGasUsed, - @JsonProperty("parentExcessDataGas") final String parentExcessDataGas, @JsonProperty("parentDataGasUsed") final String parentDataGasUsed, - @JsonProperty("beaconRoot") final String beaconRoot) { + @JsonProperty("parentDifficulty") final String parentDifficulty, + @JsonProperty("parentExcessBlobGas") final String parentExcessBlobGas, + @JsonProperty("parentExcessDataGas") final String parentExcessDataGas, + @JsonProperty("parentGasLimit") final String parentGasLimit, + @JsonProperty("parentGasUsed") final String parentGasUsed, + @JsonProperty("parentTimestamp") final String parentTimestamp, + @JsonProperty("parentUncleHash") final String _parentUncleHash) { super( generateTestBlockHash(previousHash, number), Hash.EMPTY_LIST_HASH, // ommersHash @@ -141,7 +143,7 @@ public ReferenceTestEnv( Optional.ofNullable(baseFee).map(Wei::fromHexString).orElse(null), Optional.ofNullable(random).map(Difficulty::fromHexString).orElse(Difficulty.ZERO), 0L, - null, // withdrawalsRoot + currentWithdrawalsRoot == null ? null : Hash.fromHexString(currentWithdrawalsRoot), currentBlobGasUsed == null ? currentDataGasUsed == null ? null : Long.decode(currentDataGasUsed) : Long.decode(currentBlobGasUsed), @@ -172,7 +174,10 @@ public ReferenceTestEnv( Map.entry( Long.decode(entry.getKey()), Hash.fromHexString(entry.getValue()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - this.beaconRoot = beaconRoot == null ? null : Hash.fromHexString(beaconRoot); + this.beaconRoot = + beaconRoot == null + ? (currentBeaconRoot == null ? null : Hash.fromHexString(currentBeaconRoot)) + : Hash.fromHexString(beaconRoot); } @Override diff --git a/ethereum/referencetests/src/reference-test/external-resources b/ethereum/referencetests/src/reference-test/external-resources index 06e276776bc..661356317ac 160000 --- a/ethereum/referencetests/src/reference-test/external-resources +++ b/ethereum/referencetests/src/reference-test/external-resources @@ -1 +1 @@ -Subproject commit 06e276776bc87817c38f6efb492bf6f4527fa904 +Subproject commit 661356317ac6df52208d54187e692472a25a01f8 diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java index 3a11761e708..266f8bb6a38 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java @@ -86,6 +86,9 @@ public class BlockchainReferenceTestTools { params.ignore("blobhashListBounds5"); params.ignore("blockWithAllTransactionTypes"); + // EIP-4788 is still in flux and the current fill is not against the final address + params.ignore("[Cancun]"); + // EOF tests are written against an older version of the spec params.ignore("/stEOF/"); } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java index 28e4436fe6e..3b1139cd179 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java @@ -18,9 +18,10 @@ import java.io.PrintStream; import java.nio.charset.StandardCharsets; -import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReadWriteLock; import org.apache.tuweni.bytes.Bytes; @@ -51,9 +52,10 @@ public boolean containsStaticData() { } }; - private static Map>> asSegmentMap( + private static ConcurrentMap>> asSegmentMap( final Map> initialMap) { - final Map>> segmentMap = new HashMap<>(); + final ConcurrentMap>> segmentMap = + new ConcurrentHashMap<>(); segmentMap.put(SEGMENT_IDENTIFIER, initialMap); return segmentMap; } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java index ffc57530682..ddaf567433f 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -59,7 +60,7 @@ public LayeredKeyValueStorage(final SegmentedKeyValueStorage parent) { * @param parent the parent key value storage for this layered storage. */ public LayeredKeyValueStorage( - final Map>> map, + final ConcurrentMap>> map, final SegmentedKeyValueStorage parent) { super(map); this.parent = parent; diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java index 66d70bac4dc..fd48384c366 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java @@ -30,6 +30,8 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -46,14 +48,14 @@ public class SegmentedInMemoryKeyValueStorage implements SnappedKeyValueStorage, SnappableKeyValueStorage, SegmentedKeyValueStorage { /** protected access for the backing hash map. */ - final Map>> hashValueStore; + final ConcurrentMap>> hashValueStore; /** protected access to the rw lock. */ protected final ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** Instantiates a new In memory key value storage. */ public SegmentedInMemoryKeyValueStorage() { - this(new HashMap<>()); + this(new ConcurrentHashMap<>()); } /** @@ -62,7 +64,7 @@ public SegmentedInMemoryKeyValueStorage() { * @param hashValueStore the hash value store */ protected SegmentedInMemoryKeyValueStorage( - final Map>> hashValueStore) { + final ConcurrentMap>> hashValueStore) { this.hashValueStore = hashValueStore; } @@ -76,8 +78,8 @@ public SegmentedInMemoryKeyValueStorage(final List segments) segments.stream() .collect( Collectors - .>>toMap( - s -> s, s -> new HashMap<>()))); + .>> + toConcurrentMap(s -> s, s -> new ConcurrentHashMap<>()))); } @Override @@ -214,7 +216,9 @@ public SegmentedInMemoryKeyValueStorage takeSnapshot() { // need to clone the submaps also: return new SegmentedInMemoryKeyValueStorage( hashValueStore.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> new HashMap<>(e.getValue())))); + .collect( + Collectors.toConcurrentMap( + Map.Entry::getKey, e -> new ConcurrentHashMap<>(e.getValue())))); } @Override From 277424d8a15d74b83b420d9aa100a4272466e445 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 22 Sep 2023 00:42:59 +1000 Subject: [PATCH 06/10] [MINOR] Block number param additional test (#5918) * add test for hex vs decimal block parameter Signed-off-by: Sally MacFarlane * typo Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- .../methods/EthGetBlockByNumberTest.java | 4 +-- .../parameters/BlockParameterTest.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockByNumberTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockByNumberTest.java index 2d3390e7f30..8eafb35f730 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockByNumberTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockByNumberTest.java @@ -82,9 +82,9 @@ public void setUp() { blockchain.appendBlock(block, receipts); } - BlockHeader lastestHeader = blockchain.getChainHeadBlock().getHeader(); + BlockHeader latestHeader = blockchain.getChainHeadBlock().getHeader(); when(worldStateArchive.isWorldStateAvailable( - lastestHeader.getStateRoot(), lastestHeader.getHash())) + latestHeader.getStateRoot(), latestHeader.getHash())) .thenReturn(Boolean.TRUE); blockchainQueries = spy(new BlockchainQueries(blockchain, worldStateArchive)); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockParameterTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockParameterTest.java index 3e8d534e70f..015a217bc28 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockParameterTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockParameterTest.java @@ -114,6 +114,34 @@ public void longShouldReturnLongNumberValue() { assertThat(blockParameter.isSafe()).isFalse(); } + @Test + public void numberStringShouldReturnLongNumberValue() { + final BlockParameter blockParameter = new BlockParameter("55"); + assertThat(blockParameter.getNumber()).isPresent(); + assertThat(blockParameter.getNumber().get()).isEqualTo(55L); + + assertThat(blockParameter.isNumeric()).isTrue(); + assertThat(blockParameter.isEarliest()).isFalse(); + assertThat(blockParameter.isFinalized()).isFalse(); + assertThat(blockParameter.isLatest()).isFalse(); + assertThat(blockParameter.isPending()).isFalse(); + assertThat(blockParameter.isSafe()).isFalse(); + } + + @Test + public void hexShouldReturnLongNumberValue() { + final BlockParameter blockParameter = new BlockParameter("0x55"); + assertThat(blockParameter.getNumber()).isPresent(); + assertThat(blockParameter.getNumber().get()).isEqualTo(85L); + + assertThat(blockParameter.isNumeric()).isTrue(); + assertThat(blockParameter.isEarliest()).isFalse(); + assertThat(blockParameter.isFinalized()).isFalse(); + assertThat(blockParameter.isLatest()).isFalse(); + assertThat(blockParameter.isPending()).isFalse(); + assertThat(blockParameter.isSafe()).isFalse(); + } + @Test public void upperCaseStringShouldBeHandled() { final BlockParameter blockParameter = new BlockParameter("LATEST"); From c9489a499807dcb766e55387fa7e762f33fb5cd8 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 22 Sep 2023 04:35:01 +1000 Subject: [PATCH 07/10] update beacon root again [skip ci] (#5903) Signed-off-by: Sally MacFarlane Co-authored-by: Justin Florentine --- .../besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java index 669815f7d52..d5252a06728 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java @@ -24,10 +24,10 @@ /** A helper class to store the parent beacon block root. */ public interface ParentBeaconBlockRootHelper { - // Modulus use to for the timestamp to store the root + // Modulus to use for the timestamp to store the root public static final long HISTORICAL_ROOTS_MODULUS = 8191; public static final Address BEACON_ROOTS_ADDRESS = - Address.fromHexString("0xBEaC020001c6C8B69E5257f4754e46e25f5dc9cB"); + Address.fromHexString("0xbEAC020008aFF7331c0A389CB2AAb67597567d7a"); static void storeParentBeaconBlockRoot( final WorldUpdater worldUpdater, final long timestamp, final Bytes32 root) { From 5830936583628c589feb36087ebcaaf7a8020255 Mon Sep 17 00:00:00 2001 From: Stefan Pingel <16143240+pinges@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:03:59 +1000 Subject: [PATCH 08/10] fix geth rlpx ping command (#5917) * fix geth rlpx ping command Signed-off-by: Stefan --------- Signed-off-by: Stefan --- .../netty/AbstractHandshakeHandler.java | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/AbstractHandshakeHandler.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/AbstractHandshakeHandler.java index 87826b5f93b..3a827403ec3 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/AbstractHandshakeHandler.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/AbstractHandshakeHandler.java @@ -97,47 +97,47 @@ protected final void channelRead0(final ChannelHandlerContext ctx, final ByteBuf ctx.writeAndFlush(nextMsg.get()); } else if (handshaker.getStatus() != Handshaker.HandshakeStatus.SUCCESS) { LOG.debug("waiting for more bytes"); - } else { - - final Bytes nodeId = handshaker.partyPubKey().getEncodedBytes(); - if (!localNode.isReady()) { - // If we're handling a connection before the node is fully up, just disconnect - LOG.debug("Rejecting connection because local node is not ready {}", nodeId); - disconnect(ctx, DisconnectMessage.DisconnectReason.UNKNOWN); - return; - } + return; + } - LOG.trace("Sending framed hello"); - - // Exchange keys done - final Framer framer = this.framerProvider.buildFramer(handshaker.secrets()); - - final ByteToMessageDecoder deFramer = - new DeFramer( - framer, - subProtocols, - localNode, - expectedPeer, - connectionEventDispatcher, - connectionFuture, - metricsSystem, - inboundInitiated); - - ctx.channel() - .pipeline() - .replace(this, "DeFramer", deFramer) - .addBefore("DeFramer", "validate", new ValidateFirstOutboundMessage(framer)); - - ctx.writeAndFlush(new OutboundMessage(null, HelloMessage.create(localNode.getPeerInfo()))) - .addListener( - ff -> { - if (ff.isSuccess()) { - LOG.trace("Successfully wrote hello message"); - } - }); - msg.retain(); - ctx.fireChannelRead(msg); + final Bytes nodeId = handshaker.partyPubKey().getEncodedBytes(); + if (!localNode.isReady()) { + // If we're handling a connection before the node is fully up, just disconnect + LOG.debug("Rejecting connection because local node is not ready {}", nodeId); + disconnect(ctx, DisconnectMessage.DisconnectReason.UNKNOWN); + return; } + + LOG.trace("Sending framed hello"); + + // Exchange keys done + final Framer framer = this.framerProvider.buildFramer(handshaker.secrets()); + + final ByteToMessageDecoder deFramer = + new DeFramer( + framer, + subProtocols, + localNode, + expectedPeer, + connectionEventDispatcher, + connectionFuture, + metricsSystem, + inboundInitiated); + + ctx.channel() + .pipeline() + .replace(this, "DeFramer", deFramer) + .addBefore("DeFramer", "validate", new ValidateFirstOutboundMessage(framer)); + + ctx.writeAndFlush(new OutboundMessage(null, HelloMessage.create(localNode.getPeerInfo()))) + .addListener( + ff -> { + if (ff.isSuccess()) { + LOG.trace("Successfully wrote hello message"); + } + }); + msg.retain(); + ctx.fireChannelRead(msg); } private void disconnect( From 9d7ee2b52b5703bf1c9e59c7e21297b1199fa729 Mon Sep 17 00:00:00 2001 From: Gabriel-Trintinalia Date: Fri, 22 Sep 2023 22:56:22 +1000 Subject: [PATCH 09/10] [4844] Fix some Devnet9 Hive tests (#5929) * Return latest valid hash for blob validation * Fix invalid hash * Fix null hash * Change HISTORY_BUFFER_LENGTH --------- Signed-off-by: Gabriel-Trintinalia --- .../methods/engine/AbstractEngineNewPayload.java | 9 +++++++-- .../ethereum/mainnet/ParentBeaconBlockRootHelper.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index 7b5d6f852ad..60abf0aa039 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -130,7 +130,12 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) try { maybeVersionedHashes = extractVersionedHashes(maybeVersionedHashParam); } catch (RuntimeException ex) { - return respondWithInvalid(reqId, blockParam, null, INVALID, "Invalid versionedHash"); + return respondWithInvalid( + reqId, + blockParam, + mergeCoordinator.getLatestValidAncestor(blockParam.getParentHash()).orElse(null), + INVALID, + "Invalid versionedHash"); } final Optional maybeParentHeader = @@ -240,7 +245,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) return respondWithInvalid( reqId, blockParam, - null, + mergeCoordinator.getLatestValidAncestor(blockParam.getParentHash()).orElse(null), getInvalidBlockHashStatus(), blobValidationResult.getErrorMessage()); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java index d5252a06728..5bae221bcfd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ParentBeaconBlockRootHelper.java @@ -25,7 +25,7 @@ public interface ParentBeaconBlockRootHelper { // Modulus to use for the timestamp to store the root - public static final long HISTORICAL_ROOTS_MODULUS = 8191; + public static final long HISTORICAL_ROOTS_MODULUS = 98304; public static final Address BEACON_ROOTS_ADDRESS = Address.fromHexString("0xbEAC020008aFF7331c0A389CB2AAb67597567d7a"); From d81e1f30427f96cf1a8321885aa0836443199bfa Mon Sep 17 00:00:00 2001 From: garyschulte Date: Fri, 22 Sep 2023 10:51:39 -0700 Subject: [PATCH 10/10] Add FlatDbStrategy (#5901) * move FlatDbReader to FlatDbStrategy (including writes), add getNearestTo Signed-off-by: garyschulte --- ...nsaiSnapshotWorldStateKeyValueStorage.java | 5 +- .../BonsaiWorldStateKeyValueStorage.java | 100 ++++++++++-------- ...eaderStrategy.java => FlatDbStrategy.java} | 76 +++++++++++-- ...rStrategy.java => FullFlatDbStrategy.java} | 8 +- ...rategy.java => PartialFlatDbStrategy.java} | 8 +- .../bonsai/worldview/BonsaiWorldState.java | 4 +- .../BonsaiWorldStateKeyValueStorageTest.java | 5 +- plugin-api/build.gradle | 2 +- .../storage/SegmentedKeyValueStorage.java | 31 ++++++ .../RocksDBColumnarKeyValueSnapshot.java | 15 +++ .../RocksDBColumnarKeyValueStorage.java | 14 +++ .../segmented/RocksDBSnapshotTransaction.java | 13 +++ .../kvstore/InMemoryKeyValueStorage.java | 2 +- .../kvstore/LayeredKeyValueStorage.java | 20 ++++ .../SegmentedInMemoryKeyValueStorage.java | 27 +++++ .../SegmentedKeyValueStorageAdapter.java | 4 + .../AbstractSegmentedKeyValueStorageTest.java | 82 ++++++++++++++ .../kvstore/InMemoryKeyValueStorageTest.java | 9 +- .../kvstore/LayeredKeyValueStorageTest.java | 33 ++++++ 19 files changed, 389 insertions(+), 69 deletions(-) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/{FlatDbReaderStrategy.java => FlatDbStrategy.java} (69%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/{FullFlatDbReaderStrategy.java => FullFlatDbStrategy.java} (93%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/{PartialFlatDbReaderStrategy.java => PartialFlatDbStrategy.java} (96%) rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/{ => storage}/BonsaiWorldStateKeyValueStorageTest.java (98%) create mode 100644 services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/AbstractSegmentedKeyValueStorageTest.java create mode 100644 services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorageTest.java diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java index 44c79c46b8d..80bd2ce86eb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java @@ -47,7 +47,7 @@ public BonsaiSnapshotWorldStateKeyValueStorage( final ObservableMetricsSystem metricsSystem) { super( parentWorldStateStorage.flatDbMode, - parentWorldStateStorage.flatDbReaderStrategy, + parentWorldStateStorage.flatDbStrategy, segmentedWorldStateStorage, trieLogStorage, metricsSystem); @@ -77,7 +77,8 @@ private boolean isClosedGet() { public BonsaiUpdater updater() { return new Updater( ((SnappedKeyValueStorage) composedWorldStateStorage).getSnapshotTransaction(), - trieLogStorage.startTransaction()); + trieLogStorage.startTransaction(), + flatDbStrategy); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorage.java index 1201fffb3b8..9756b280e45 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorage.java @@ -21,9 +21,9 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.StorageSlotKey; -import org.hyperledger.besu.ethereum.bonsai.storage.flat.FlatDbReaderStrategy; -import org.hyperledger.besu.ethereum.bonsai.storage.flat.FullFlatDbReaderStrategy; -import org.hyperledger.besu.ethereum.bonsai.storage.flat.PartialFlatDbReaderStrategy; +import org.hyperledger.besu.ethereum.bonsai.storage.flat.FlatDbStrategy; +import org.hyperledger.besu.ethereum.bonsai.storage.flat.FullFlatDbStrategy; +import org.hyperledger.besu.ethereum.bonsai.storage.flat.PartialFlatDbStrategy; import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.trie.MerkleTrie; @@ -67,7 +67,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC public static final byte[] FLAT_DB_MODE = "flatDbStatus".getBytes(StandardCharsets.UTF_8); protected FlatDbMode flatDbMode; - protected FlatDbReaderStrategy flatDbReaderStrategy; + protected FlatDbStrategy flatDbStrategy; protected final SegmentedKeyValueStorage composedWorldStateStorage; protected final KeyValueStorage trieLogStorage; @@ -94,33 +94,49 @@ public BonsaiWorldStateKeyValueStorage( public BonsaiWorldStateKeyValueStorage( final FlatDbMode flatDbMode, - final FlatDbReaderStrategy flatDbReaderStrategy, + final FlatDbStrategy flatDbStrategy, final SegmentedKeyValueStorage composedWorldStateStorage, final KeyValueStorage trieLogStorage, final ObservableMetricsSystem metricsSystem) { this.flatDbMode = flatDbMode; - this.flatDbReaderStrategy = flatDbReaderStrategy; + this.flatDbStrategy = flatDbStrategy; this.composedWorldStateStorage = composedWorldStateStorage; this.trieLogStorage = trieLogStorage; this.metricsSystem = metricsSystem; } - public void loadFlatDbStrategy() { - this.flatDbMode = + private void loadFlatDbStrategy() { + // derive our flatdb strategy from db or default: + var newFlatDbMode = deriveFlatDbStrategy(); + + // if flatDbMode is not loaded or has changed, reload flatDbStrategy + if (this.flatDbMode == null || !this.flatDbMode.equals(newFlatDbMode)) { + this.flatDbMode = newFlatDbMode; + if (flatDbMode == FlatDbMode.FULL) { + this.flatDbStrategy = new FullFlatDbStrategy(metricsSystem); + } else { + this.flatDbStrategy = new PartialFlatDbStrategy(metricsSystem); + } + } + } + + public FlatDbMode deriveFlatDbStrategy() { + var flatDbMode = FlatDbMode.fromVersion( composedWorldStateStorage .get(TRIE_BRANCH_STORAGE, FLAT_DB_MODE) .map(Bytes::wrap) - .orElse( - FlatDbMode.PARTIAL - .getVersion())); // for backward compatibility we use partial as - // default + .orElse(FlatDbMode.PARTIAL.getVersion())); LOG.info("Bonsai flat db mode found {}", flatDbMode); - if (flatDbMode == FlatDbMode.FULL) { - this.flatDbReaderStrategy = new FullFlatDbReaderStrategy(metricsSystem); - } else { - this.flatDbReaderStrategy = new PartialFlatDbReaderStrategy(metricsSystem); + + return flatDbMode; + } + + public FlatDbStrategy getFlatDbStrategy() { + if (flatDbStrategy == null) { + loadFlatDbStrategy(); } + return flatDbStrategy; } @Override @@ -133,22 +149,18 @@ public FlatDbMode getFlatDbMode() { return flatDbMode; } - public FlatDbReaderStrategy getFlatDbReaderStrategy() { - return flatDbReaderStrategy; - } - @Override public Optional getCode(final Bytes32 codeHash, final Hash accountHash) { if (codeHash.equals(Hash.EMPTY)) { return Optional.of(Bytes.EMPTY); } else { - return getFlatDbReaderStrategy().getCode(codeHash, accountHash, composedWorldStateStorage); + return getFlatDbStrategy().getFlatCode(codeHash, accountHash, composedWorldStateStorage); } } public Optional getAccount(final Hash accountHash) { - return getFlatDbReaderStrategy() - .getAccount( + return getFlatDbStrategy() + .getFlatAccount( this::getWorldStateRootHash, this::getAccountStateTrieNode, accountHash, @@ -226,8 +238,8 @@ public Optional getStorageValueByStorageSlotKey( final Supplier> storageRootSupplier, final Hash accountHash, final StorageSlotKey storageSlotKey) { - return getFlatDbReaderStrategy() - .getStorageValueByStorageSlotKey( + return getFlatDbStrategy() + .getFlatStorageValueByStorageSlotKey( this::getWorldStateRootHash, storageRootSupplier, (location, hash) -> getAccountStorageTrieNode(accountHash, location, hash), @@ -239,14 +251,14 @@ public Optional getStorageValueByStorageSlotKey( @Override public Map streamFlatAccounts( final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) { - return getFlatDbReaderStrategy() + return getFlatDbStrategy() .streamAccountFlatDatabase(composedWorldStateStorage, startKeyHash, endKeyHash, max); } @Override public Map streamFlatStorages( final Hash accountHash, final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) { - return getFlatDbReaderStrategy() + return getFlatDbStrategy() .streamStorageFlatDatabase( composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max); } @@ -273,6 +285,7 @@ public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHas public void upgradeToFullFlatDbMode() { final SegmentedKeyValueStorageTransaction transaction = composedWorldStateStorage.startTransaction(); + // TODO: consider ARCHIVE mode transaction.put( TRIE_BRANCH_STORAGE, FLAT_DB_MODE, FlatDbMode.FULL.getVersion().toArrayUnsafe()); transaction.commit(); @@ -291,7 +304,7 @@ public void downgradeToPartialFlatDbMode() { @Override public void clear() { subscribers.forEach(BonsaiStorageSubscriber::onClearStorage); - getFlatDbReaderStrategy().clearAll(composedWorldStateStorage); + getFlatDbStrategy().clearAll(composedWorldStateStorage); composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE); trieLogStorage.clear(); loadFlatDbStrategy(); // force reload of flat db reader strategy @@ -306,13 +319,15 @@ public void clearTrieLog() { @Override public void clearFlatDatabase() { subscribers.forEach(BonsaiStorageSubscriber::onClearFlatDatabaseStorage); - getFlatDbReaderStrategy().resetOnResync(composedWorldStateStorage); + getFlatDbStrategy().resetOnResync(composedWorldStateStorage); } @Override public BonsaiUpdater updater() { return new Updater( - composedWorldStateStorage.startTransaction(), trieLogStorage.startTransaction()); + composedWorldStateStorage.startTransaction(), + trieLogStorage.startTransaction(), + flatDbStrategy); } @Override @@ -351,18 +366,21 @@ public static class Updater implements BonsaiUpdater { private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction; private final KeyValueStorageTransaction trieLogStorageTransaction; + private final FlatDbStrategy flatDbStrategy; public Updater( final SegmentedKeyValueStorageTransaction composedWorldStateTransaction, - final KeyValueStorageTransaction trieLogStorageTransaction) { + final KeyValueStorageTransaction trieLogStorageTransaction, + final FlatDbStrategy flatDbStrategy) { this.composedWorldStateTransaction = composedWorldStateTransaction; this.trieLogStorageTransaction = trieLogStorageTransaction; + this.flatDbStrategy = flatDbStrategy; } @Override public BonsaiUpdater removeCode(final Hash accountHash) { - composedWorldStateTransaction.remove(CODE_STORAGE, accountHash.toArrayUnsafe()); + flatDbStrategy.removeFlatCode(composedWorldStateTransaction, accountHash); return this; } @@ -372,14 +390,13 @@ public BonsaiUpdater putCode(final Hash accountHash, final Bytes32 codeHash, fin // Don't save empty values return this; } - composedWorldStateTransaction.put( - CODE_STORAGE, accountHash.toArrayUnsafe(), code.toArrayUnsafe()); + flatDbStrategy.putFlatCode(composedWorldStateTransaction, accountHash, codeHash, code); return this; } @Override public BonsaiUpdater removeAccountInfoState(final Hash accountHash) { - composedWorldStateTransaction.remove(ACCOUNT_INFO_STATE, accountHash.toArrayUnsafe()); + flatDbStrategy.removeFlatAccount(composedWorldStateTransaction, accountHash); return this; } @@ -389,8 +406,7 @@ public BonsaiUpdater putAccountInfoState(final Hash accountHash, final Bytes acc // Don't save empty values return this; } - composedWorldStateTransaction.put( - ACCOUNT_INFO_STATE, accountHash.toArrayUnsafe(), accountValue.toArrayUnsafe()); + flatDbStrategy.putFlatAccount(composedWorldStateTransaction, accountHash, accountValue); return this; } @@ -441,18 +457,16 @@ public synchronized BonsaiUpdater putAccountStorageTrieNode( @Override public synchronized BonsaiUpdater putStorageValueBySlotHash( final Hash accountHash, final Hash slotHash, final Bytes storage) { - composedWorldStateTransaction.put( - ACCOUNT_STORAGE_STORAGE, - Bytes.concatenate(accountHash, slotHash).toArrayUnsafe(), - storage.toArrayUnsafe()); + flatDbStrategy.putFlatAccountStorageValueByStorageSlotHash( + composedWorldStateTransaction, accountHash, slotHash, storage); return this; } @Override public synchronized void removeStorageValueBySlotHash( final Hash accountHash, final Hash slotHash) { - composedWorldStateTransaction.remove( - ACCOUNT_STORAGE_STORAGE, Bytes.concatenate(accountHash, slotHash).toArrayUnsafe()); + flatDbStrategy.removeFlatAccountStorageValueByStorageSlotHash( + composedWorldStateTransaction, accountHash, slotHash); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbReaderStrategy.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbStrategy.java similarity index 69% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbReaderStrategy.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbStrategy.java index 74c7b101c25..c561dcd8609 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbReaderStrategy.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbStrategy.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.metrics.Counter; import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; import java.util.Map; import java.util.Optional; @@ -40,11 +41,11 @@ import org.apache.tuweni.rlp.RLP; /** - * This class represents a FlatDbReaderStrategy, which is responsible for reading data from flat - * databases. It implements various methods for retrieving account data, code data, and storage data - * from the corresponding KeyValueStorage. + * This class represents a FlatDbReaderStrategy, which is responsible for reading and writing data + * from flat databases. It implements various methods for storing and retrieving account data, code + * data, and storage data from the corresponding KeyValueStorage. */ -public abstract class FlatDbReaderStrategy { +public abstract class FlatDbStrategy { protected final MetricsSystem metricsSystem; protected final Counter getAccountCounter; @@ -53,7 +54,7 @@ public abstract class FlatDbReaderStrategy { protected final Counter getStorageValueCounter; protected final Counter getStorageValueFlatDatabaseCounter; - public FlatDbReaderStrategy(final MetricsSystem metricsSystem) { + public FlatDbStrategy(final MetricsSystem metricsSystem) { this.metricsSystem = metricsSystem; getAccountCounter = @@ -84,7 +85,7 @@ public FlatDbReaderStrategy(final MetricsSystem metricsSystem) { /* * Retrieves the account data for the given account hash, using the world state root hash supplier and node loader. */ - public abstract Optional getAccount( + public abstract Optional getFlatAccount( Supplier> worldStateRootHashSupplier, NodeLoader nodeLoader, Hash accountHash, @@ -94,7 +95,7 @@ public abstract Optional getAccount( * Retrieves the storage value for the given account hash and storage slot key, using the world state root hash supplier, storage root supplier, and node loader. */ - public abstract Optional getStorageValueByStorageSlotKey( + public abstract Optional getFlatStorageValueByStorageSlotKey( Supplier> worldStateRootHashSupplier, Supplier> storageRootSupplier, NodeLoader nodeLoader, @@ -105,7 +106,7 @@ public abstract Optional getStorageValueByStorageSlotKey( /* * Retrieves the code data for the given code hash and account hash. */ - public Optional getCode( + public Optional getFlatCode( final Bytes32 codeHash, final Hash accountHash, final SegmentedKeyValueStorage storage) { if (codeHash.equals(Hash.EMPTY)) { return Optional.of(Bytes.EMPTY); @@ -117,6 +118,65 @@ public Optional getCode( } } + /* + * Puts the account data for the given account hash, using the world state root hash supplier and node loader. + */ + public void putFlatAccount( + final SegmentedKeyValueStorageTransaction transaction, + final Hash accountHash, + final Bytes accountValue) { + transaction.put(ACCOUNT_INFO_STATE, accountHash.toArrayUnsafe(), accountValue.toArrayUnsafe()); + } + + public void removeFlatAccount( + final SegmentedKeyValueStorageTransaction transaction, final Hash accountHash) { + transaction.remove(ACCOUNT_INFO_STATE, accountHash.toArrayUnsafe()); + } + + /* + * Puts the storage value for the given account hash and storage slot key, using the world state root hash supplier, storage root supplier, and node loader. + */ + public void putFlatAccountStorageValueByStorageSlotHash( + final SegmentedKeyValueStorageTransaction transaction, + final Hash accountHash, + final Hash slotHash, + final Bytes storage) { + transaction.put( + ACCOUNT_STORAGE_STORAGE, + Bytes.concatenate(accountHash, slotHash).toArrayUnsafe(), + storage.toArrayUnsafe()); + } + + /* + * Removes the storage value for the given account hash and storage slot key, using the world state root hash supplier, storage root supplier, and node loader. + */ + public void removeFlatAccountStorageValueByStorageSlotHash( + final SegmentedKeyValueStorageTransaction transaction, + final Hash accountHash, + final Hash slotHash) { + transaction.remove( + ACCOUNT_STORAGE_STORAGE, Bytes.concatenate(accountHash, slotHash).toArrayUnsafe()); + } + + /* + * Removes code for the given account hash. + */ + public void removeFlatCode( + final SegmentedKeyValueStorageTransaction transaction, final Hash accountHash) { + transaction.remove(CODE_STORAGE, accountHash.toArrayUnsafe()); + } + + /* + * Puts the code data for the given code hash and account hash. + */ + public void putFlatCode( + final SegmentedKeyValueStorageTransaction transaction, + final Hash accountHash, + final Bytes32 codeHash, + final Bytes code) { + transaction.put(CODE_STORAGE, accountHash.toArrayUnsafe(), code.toArrayUnsafe()); + } + public void clearAll(final SegmentedKeyValueStorage storage) { storage.clear(ACCOUNT_INFO_STATE); storage.clear(ACCOUNT_STORAGE_STORAGE); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbReaderStrategy.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbStrategy.java similarity index 93% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbReaderStrategy.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbStrategy.java index efce863a802..de42ba50979 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbReaderStrategy.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FullFlatDbStrategy.java @@ -31,13 +31,13 @@ import org.apache.tuweni.bytes.Bytes; -public class FullFlatDbReaderStrategy extends FlatDbReaderStrategy { +public class FullFlatDbStrategy extends FlatDbStrategy { protected final Counter getAccountNotFoundInFlatDatabaseCounter; protected final Counter getStorageValueNotFoundInFlatDatabaseCounter; - public FullFlatDbReaderStrategy(final MetricsSystem metricsSystem) { + public FullFlatDbStrategy(final MetricsSystem metricsSystem) { super(metricsSystem); getAccountNotFoundInFlatDatabaseCounter = @@ -54,7 +54,7 @@ public FullFlatDbReaderStrategy(final MetricsSystem metricsSystem) { } @Override - public Optional getAccount( + public Optional getFlatAccount( final Supplier> worldStateRootHashSupplier, final NodeLoader nodeLoader, final Hash accountHash, @@ -71,7 +71,7 @@ public Optional getAccount( } @Override - public Optional getStorageValueByStorageSlotKey( + public Optional getFlatStorageValueByStorageSlotKey( final Supplier> worldStateRootHashSupplier, final Supplier> storageRootSupplier, final NodeLoader nodeLoader, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbReaderStrategy.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbStrategy.java similarity index 96% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbReaderStrategy.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbStrategy.java index 288ff67b095..1dc4288b21a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbReaderStrategy.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/PartialFlatDbStrategy.java @@ -44,7 +44,7 @@ * methods, which checks if the data is present in the flat database, and if not, queries the merkle * trie */ -public class PartialFlatDbReaderStrategy extends FlatDbReaderStrategy { +public class PartialFlatDbStrategy extends FlatDbStrategy { protected final Counter getAccountMerkleTrieCounter; protected final Counter getAccountMissingMerkleTrieCounter; @@ -52,7 +52,7 @@ public class PartialFlatDbReaderStrategy extends FlatDbReaderStrategy { protected final Counter getStorageValueMerkleTrieCounter; protected final Counter getStorageValueMissingMerkleTrieCounter; - public PartialFlatDbReaderStrategy(final MetricsSystem metricsSystem) { + public PartialFlatDbStrategy(final MetricsSystem metricsSystem) { super(metricsSystem); getAccountMerkleTrieCounter = metricsSystem.createCounter( @@ -80,7 +80,7 @@ public PartialFlatDbReaderStrategy(final MetricsSystem metricsSystem) { } @Override - public Optional getAccount( + public Optional getFlatAccount( final Supplier> worldStateRootHashSupplier, final NodeLoader nodeLoader, final Hash accountHash, @@ -111,7 +111,7 @@ public Optional getAccount( } @Override - public Optional getStorageValueByStorageSlotKey( + public Optional getFlatStorageValueByStorageSlotKey( final Supplier> worldStateRootHashSupplier, final Supplier> storageRootSupplier, final NodeLoader nodeLoader, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldState.java index f28e24b0970..b0a48b83043 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldState.java @@ -498,7 +498,9 @@ public void rollback() { @Override public Hash frontierRootHash() { return calculateRootHash( - Optional.of(new BonsaiWorldStateKeyValueStorage.Updater(noOpSegmentedTx, noOpTx)), + Optional.of( + new BonsaiWorldStateKeyValueStorage.Updater( + noOpSegmentedTx, noOpTx, worldStateStorage.getFlatDbStrategy())), accumulator.copy()); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateKeyValueStorageTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java similarity index 98% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateKeyValueStorageTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java index 6f67f657f02..32a8272237f 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateKeyValueStorageTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.bonsai; +package org.hyperledger.besu.ethereum.bonsai.storage; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY; @@ -26,7 +26,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.StorageSlotKey; -import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.TrieGenerator; import org.hyperledger.besu.ethereum.rlp.RLP; @@ -372,7 +371,7 @@ void clear_reloadFlatDbStrategy(final FlatDbMode flatDbMode) { // clear storage.clear(); - assertThat(storage.getFlatDbReaderStrategy()).isNotNull(); + assertThat(storage.getFlatDbStrategy()).isNotNull(); assertThat(storage.getAccount(Hash.ZERO)).isEmpty(); } diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index e544419b8ab..a091f97c151 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'tpSnjt4HgqSiOTJhBbYdB0r1nFX4QZbicjfloI71Wf0=' + knownHash = 'BhqPyj1fT50NWuHTgzgCmW1ynAPj/2QiGWraq5OwgOQ=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentedKeyValueStorage.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentedKeyValueStorage.java index 55d04d470c4..df8a8c48941 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentedKeyValueStorage.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentedKeyValueStorage.java @@ -23,6 +23,7 @@ import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; +import org.apache.tuweni.bytes.Bytes; /** Service provided by Besu to facilitate persistent data storage. */ public interface SegmentedKeyValueStorage extends Closeable { @@ -37,6 +38,18 @@ public interface SegmentedKeyValueStorage extends Closeable { */ Optional get(SegmentIdentifier segment, byte[] key) throws StorageException; + /** + * Find the key and corresponding value "nearest to" the specified key. Nearest is defined as + * either matching the supplied key or the key lexicographically prior to it. + * + * @param segmentIdentifier segment to scan + * @param key key for which we are searching for the nearest match. + * @return Optional of NearestKeyValue-wrapped matched key and corresponding value. + * @throws StorageException the storage exception + */ + Optional getNearestTo(final SegmentIdentifier segmentIdentifier, Bytes key) + throws StorageException; + /** * Contains key. * @@ -144,4 +157,22 @@ Set getAllValuesFromKeysThat( * @return boolean indicating whether the underlying storage is closed. */ boolean isClosed(); + + /** + * record type used to wrap responses from getNearestTo, includes the matched key and the value. + * + * @param key the matched (nearest) key + * @param value the corresponding value + */ + record NearestKeyValue(Bytes key, Optional value) { + + /** + * Convenience method to map the Optional value to Bytes. + * + * @return Optional of Bytes. + */ + public Optional wrapBytes() { + return value.map(Bytes::wrap); + } + } } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java index 6a123069001..b1a0920a516 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java @@ -33,8 +33,11 @@ import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; +import org.apache.tuweni.bytes.Bytes; +import org.rocksdb.AbstractRocksIterator; import org.rocksdb.ColumnFamilyHandle; import org.rocksdb.OptimisticTransactionDB; +import org.rocksdb.RocksIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,6 +76,18 @@ public Optional get(final SegmentIdentifier segment, final byte[] key) return snapTx.get(segment, key); } + @Override + public Optional getNearestTo( + final SegmentIdentifier segmentIdentifier, final Bytes key) throws StorageException { + + try (final RocksIterator rocksIterator = snapTx.getIterator(segmentIdentifier)) { + rocksIterator.seekForPrev(key.toArrayUnsafe()); + return Optional.of(rocksIterator) + .filter(AbstractRocksIterator::isValid) + .map(it -> new NearestKeyValue(Bytes.of(it.key()), Optional.of(it.value()))); + } + } + @Override public Stream> stream(final SegmentIdentifier segment) { throwIfClosed(); diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index 9462f9bcb14..952da71f0bc 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -44,6 +44,7 @@ import com.google.common.collect.Streams; import org.apache.commons.lang3.tuple.Pair; import org.apache.tuweni.bytes.Bytes; +import org.rocksdb.AbstractRocksIterator; import org.rocksdb.BlockBasedTableConfig; import org.rocksdb.BloomFilter; import org.rocksdb.ColumnFamilyDescriptor; @@ -318,6 +319,19 @@ public Optional get(final SegmentIdentifier segment, final byte[] key) } } + @Override + public Optional getNearestTo( + final SegmentIdentifier segmentIdentifier, final Bytes key) throws StorageException { + + try (final RocksIterator rocksIterator = + getDB().newIterator(safeColumnHandle(segmentIdentifier))) { + rocksIterator.seekForPrev(key.toArrayUnsafe()); + return Optional.of(rocksIterator) + .filter(AbstractRocksIterator::isValid) + .map(it -> new NearestKeyValue(Bytes.of(it.key()), Optional.of(it.value()))); + } + } + @Override public Stream> stream(final SegmentIdentifier segmentIdentifier) { final RocksIterator rocksIterator = getDB().newIterator(safeColumnHandle(segmentIdentifier)); diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java index 0897493eb19..ad3438d381b 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java @@ -137,6 +137,19 @@ public void remove(final SegmentIdentifier segmentId, final byte[] key) { } } + /** + * get a RocksIterator that reads through the transaction to represent the current state. + * + *

be sure to close this iterator, like in a try-with-resources block, otherwise a native + * memory leak might occur. + * + * @param segmentId id for the segment to iterate over. + * @return RocksIterator + */ + public RocksIterator getIterator(final SegmentIdentifier segmentId) { + return snapTx.getIterator(readOptions, columnFamilyMapper.apply(segmentId)); + } + /** * Stream. * diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java index 3b1139cd179..dbd62eaff9a 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java @@ -32,7 +32,7 @@ */ public class InMemoryKeyValueStorage extends SegmentedKeyValueStorageAdapter { - private static final SegmentIdentifier SEGMENT_IDENTIFIER = + static final SegmentIdentifier SEGMENT_IDENTIFIER = new SegmentIdentifier() { private static final String NAME = "SEGMENT_IDENTIFIER"; diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java index ddaf567433f..6713772a03d 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java @@ -93,6 +93,26 @@ public Optional get(final SegmentIdentifier segmentId, final byte[] key) } } + @Override + public Optional getNearestTo( + final SegmentIdentifier segmentIdentifier, final Bytes key) throws StorageException { + Optional ourNearest = super.getNearestTo(segmentIdentifier, key); + Optional parentNearest = parent.getNearestTo(segmentIdentifier, key); + + if (ourNearest.isPresent() && parentNearest.isPresent()) { + // Both are present, return the one closer to the key + int ourDistance = ourNearest.get().key().commonPrefixLength(key); + int parentDistance = parentNearest.get().key().commonPrefixLength(key); + return (ourDistance <= parentDistance) ? ourNearest : parentNearest; + } else if (ourNearest.isPresent()) { + // Only ourNearest is present + return ourNearest; + } else { + // return parentNearest, which may be an empty Optional + return parentNearest; + } + } + @Override public Stream> stream(final SegmentIdentifier segmentId) { throwIfClosed(); diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java index fd48384c366..ff8ca7249cb 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedInMemoryKeyValueStorage.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.plugin.services.storage.SnappedKeyValueStorage; import java.io.PrintStream; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -113,6 +114,32 @@ public Optional get(final SegmentIdentifier segmentIdentifier, final byt } } + @Override + public Optional getNearestTo( + final SegmentIdentifier segmentIdentifier, final Bytes key) throws StorageException { + + final Lock lock = rwLock.readLock(); + lock.lock(); + try { + // TODO: revisit this for sort performance + Comparator>> comparing = + Comparator.comparing( + (Map.Entry> a) -> a.getKey().commonPrefixLength(key)) + .thenComparing(Map.Entry.comparingByKey()); + return this.hashValueStore + .computeIfAbsent(segmentIdentifier, s -> new HashMap<>()) + .entrySet() + .stream() + // only return keys equal to or less than + .filter(e -> e.getKey().compareTo(key) <= 0) + .sorted(comparing.reversed()) + .findFirst() + .map(z -> new NearestKeyValue(z.getKey(), z.getValue())); + } finally { + lock.unlock(); + } + } + @Override public Set getAllKeysThat( final SegmentIdentifier segmentIdentifier, final Predicate returnCondition) { diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java index a02e9284fa6..404689be420 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java @@ -51,6 +51,10 @@ public SegmentedKeyValueStorageAdapter( this.storage = storage; } + SegmentedKeyValueStorage getSegmentedStore() { + return this.storage; + } + @Override public void clear() { throwIfClosed(); diff --git a/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/AbstractSegmentedKeyValueStorageTest.java b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/AbstractSegmentedKeyValueStorageTest.java new file mode 100644 index 00000000000..47aee3ae580 --- /dev/null +++ b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/AbstractSegmentedKeyValueStorageTest.java @@ -0,0 +1,82 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.services.kvstore; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage.SEGMENT_IDENTIFIER; + +import org.hyperledger.besu.kvstore.AbstractKeyValueStorageTest; +import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; + +import java.util.stream.IntStream; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Test; + +public abstract class AbstractSegmentedKeyValueStorageTest extends AbstractKeyValueStorageTest { + public abstract SegmentedKeyValueStorage createSegmentedStore(); + + @Test + public void assertSegmentedIsNearestTo() throws Exception { + try (final var store = this.createSegmentedStore()) { + + // create 10 entries + final SegmentedKeyValueStorageTransaction tx = store.startTransaction(); + IntStream.range(1, 10) + .forEach( + i -> { + final byte[] key = bytesFromHexString("000" + i); + final byte[] value = bytesFromHexString("0FFF"); + tx.put(SEGMENT_IDENTIFIER, key, value); + // different common prefix, and reversed order of bytes: + final byte[] key2 = bytesFromHexString("010" + (10 - i)); + final byte[] value2 = bytesFromHexString("0FFF"); + tx.put(SEGMENT_IDENTIFIER, key2, value2); + }); + tx.commit(); + + // assert 0009 is closest to 000F + var val = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("000F")); + assertThat(val).isPresent(); + assertThat(val.get().key()).isEqualTo(Bytes.fromHexString("0009")); + + // assert 0109 is closest to 010D + var val2 = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("010D")); + assertThat(val2).isPresent(); + assertThat(val2.get().key()).isEqualTo(Bytes.fromHexString("0109")); + + // assert 0103 is closest to 0103 + var val3 = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("0103")); + assertThat(val3).isPresent(); + assertThat(val3.get().key()).isEqualTo(Bytes.fromHexString("0103")); + + // assert 0003 is closest to 0003 + var val4 = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("0003")); + assertThat(val4).isPresent(); + assertThat(val4.get().key()).isEqualTo(Bytes.fromHexString("0003")); + + // assert 0001 is closest to 0001 + var val5 = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("0001")); + assertThat(val5).isPresent(); + assertThat(val5.get().key()).isEqualTo(Bytes.fromHexString("0001")); + + // assert 0000 is not present + var val6 = store.getNearestTo(SEGMENT_IDENTIFIER, Bytes.fromHexString("0000")); + assertThat(val6).isNotPresent(); + } + } +} diff --git a/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorageTest.java b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorageTest.java index 90581476279..55a10ffa8d1 100644 --- a/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorageTest.java +++ b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorageTest.java @@ -14,13 +14,18 @@ */ package org.hyperledger.besu.services.kvstore; -import org.hyperledger.besu.kvstore.AbstractKeyValueStorageTest; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; -public class InMemoryKeyValueStorageTest extends AbstractKeyValueStorageTest { +public class InMemoryKeyValueStorageTest extends AbstractSegmentedKeyValueStorageTest { @Override protected KeyValueStorage createStore() { return new InMemoryKeyValueStorage(); } + + @Override + public SegmentedKeyValueStorage createSegmentedStore() { + return new SegmentedInMemoryKeyValueStorage(); + } } diff --git a/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorageTest.java b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorageTest.java new file mode 100644 index 00000000000..2117c1c199b --- /dev/null +++ b/services/kvstore/src/test/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorageTest.java @@ -0,0 +1,33 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.services.kvstore; + +import static org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage.SEGMENT_IDENTIFIER; + +import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; + +public class LayeredKeyValueStorageTest extends AbstractSegmentedKeyValueStorageTest { + @Override + protected KeyValueStorage createStore() { + return new SegmentedKeyValueStorageAdapter(SEGMENT_IDENTIFIER, createSegmentedStore()); + } + + @Override + public SegmentedKeyValueStorage createSegmentedStore() { + return new LayeredKeyValueStorage(new SegmentedInMemoryKeyValueStorage()); + } +}