From ce705b6da2c1df35ea351bb91870a0f59ca8ed03 Mon Sep 17 00:00:00 2001 From: "stefan.pingel@consensys.net" Date: Fri, 20 Sep 2024 17:25:51 +1000 Subject: [PATCH 1/3] keep the rlp when it makes sense Signed-off-by: stefan.pingel@consensys.net --- .../ethereum/core/TransactionReceipt.java | 56 ++++++++++++++++--- .../besu/ethereum/mainnet/BodyValidation.java | 21 +++++-- .../manager/task/GetReceiptsFromPeerTask.java | 2 +- .../eth/messages/ReceiptsMessage.java | 6 +- 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java index 79fb1a50149..114f3578129 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java @@ -57,6 +57,7 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran private final int status; private final TransactionReceiptType transactionReceiptType; private final Optional revertReason; + private final Bytes rlp; /** * Creates an instance of a state root-encoded transaction receipt. @@ -78,7 +79,8 @@ public TransactionReceipt( cumulativeGasUsed, logs, LogsBloomFilter.builder().insertLogs(logs).build(), - revertReason); + revertReason, + null); } private TransactionReceipt( @@ -87,7 +89,8 @@ private TransactionReceipt( final long cumulativeGasUsed, final List logs, final LogsBloomFilter bloomFilter, - final Optional revertReason) { + final Optional revertReason, + final Bytes rlp) { this( transactionType, stateRoot, @@ -95,7 +98,8 @@ private TransactionReceipt( cumulativeGasUsed, logs, bloomFilter, - revertReason); + revertReason, + rlp); } /** @@ -118,7 +122,8 @@ public TransactionReceipt( cumulativeGasUsed, logs, LogsBloomFilter.builder().insertLogs(logs).build(), - revertReason); + revertReason, + null); } public TransactionReceipt( @@ -128,7 +133,18 @@ public TransactionReceipt( final List logs, final LogsBloomFilter bloomFilter, final Optional revertReason) { - this(transactionType, null, status, cumulativeGasUsed, logs, bloomFilter, revertReason); + this(transactionType, null, status, cumulativeGasUsed, logs, bloomFilter, revertReason, null); + } + + public TransactionReceipt( + final TransactionType transactionType, + final int status, + final long cumulativeGasUsed, + final List logs, + final LogsBloomFilter bloomFilter, + final Optional revertReason, + final Bytes rlp) { + this(transactionType, null, status, cumulativeGasUsed, logs, bloomFilter, revertReason, rlp); } public TransactionReceipt( @@ -153,7 +169,8 @@ private TransactionReceipt( final long cumulativeGasUsed, final List logs, final LogsBloomFilter bloomFilter, - final Optional revertReason) { + final Optional revertReason, + final Bytes rlp) { this.transactionType = transactionType; this.stateRoot = stateRoot; this.cumulativeGasUsed = cumulativeGasUsed; @@ -163,6 +180,7 @@ private TransactionReceipt( this.transactionReceiptType = stateRoot == null ? TransactionReceiptType.STATUS : TransactionReceiptType.ROOT; this.revertReason = revertReason; + this.rlp = rlp; } /** @@ -233,6 +251,19 @@ public static TransactionReceipt readFrom(final RLPInput input) { */ public static TransactionReceipt readFrom( final RLPInput rlpInput, final boolean revertReasonAllowed) { + return readFrom(rlpInput, revertReasonAllowed, false); + } + + /** + * Creates a transaction receipt for the given RLP + * + * @param rlpInput the RLP-encoded transaction receipt + * @param revertReasonAllowed whether the rlp input is allowed to have a revert reason + * @param keepRlp whether to store the rlp with the receipt + * @return the transaction receipt + */ + public static TransactionReceipt readFrom( + final RLPInput rlpInput, final boolean revertReasonAllowed, final boolean keepRlp) { RLPInput input = rlpInput; TransactionType transactionType = TransactionType.FRONTIER; if (!rlpInput.nextIsList()) { @@ -271,18 +302,23 @@ public static TransactionReceipt readFrom( revertReason = Optional.of(input.readBytes()); } + Bytes raw = null; + if (keepRlp) { + raw = input.raw(); + } + // Status code-encoded transaction receipts have a single // byte for success (0x01) or failure (0x80). if (firstElement.raw().size() == 1) { final int status = firstElement.readIntScalar(); input.leaveList(); return new TransactionReceipt( - transactionType, status, cumulativeGas, logs, bloomFilter, revertReason); + transactionType, status, cumulativeGas, logs, bloomFilter, revertReason, raw); } else { final Hash stateRoot = Hash.wrap(firstElement.readBytes32()); input.leaveList(); return new TransactionReceipt( - transactionType, stateRoot, cumulativeGas, logs, bloomFilter, revertReason); + transactionType, stateRoot, cumulativeGas, logs, bloomFilter, revertReason, raw); } } @@ -353,6 +389,10 @@ public Optional getRevertReason() { return revertReason; } + public Optional getRlp() { + return Optional.ofNullable(rlp); + } + @Override public boolean equals(final Object obj) { if (obj == this) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java index 15e8c3c804f..86249ab527b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java @@ -112,12 +112,21 @@ public static Hash receiptsRoot(final List receipts) { IntStream.range(0, receipts.size()) .forEach( - i -> - trie.put( - indexKey(i), - RLP.encode( - rlpOutput -> - receipts.get(i).writeToForReceiptTrie(rlpOutput, false, false)))); + i -> { + final TransactionReceipt receipt = receipts.get(i); + if (receipt.getRlp().isPresent()) { + System.out.println(receipt.getRlp().get()); + } + System.out.println( + RLP.encode(rlpOutput -> receipt.writeToForReceiptTrie(rlpOutput, false, false))); + System.out.println(); + trie.put( + indexKey(i), + receipt.getRlp().isPresent() + ? receipt.getRlp().get() + : RLP.encode( + rlpOutput -> receipt.writeToForReceiptTrie(rlpOutput, false, false))); + }); return Hash.wrap(trie.getRootHash()); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetReceiptsFromPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetReceiptsFromPeerTask.java index 5b52078b23e..8716c2b8849 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetReceiptsFromPeerTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetReceiptsFromPeerTask.java @@ -104,7 +104,7 @@ protected Optional>> processResponse( } final ReceiptsMessage receiptsMessage = ReceiptsMessage.readFrom(message); - final List> receiptsByBlock = receiptsMessage.receipts(); + final List> receiptsByBlock = receiptsMessage.receipts(true); if (receiptsByBlock.isEmpty()) { return Optional.empty(); } else if (receiptsByBlock.size() > blockHeaders.size()) { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/ReceiptsMessage.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/ReceiptsMessage.java index 7ca823cd8d7..beda51b60b2 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/ReceiptsMessage.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/ReceiptsMessage.java @@ -74,6 +74,10 @@ public int getCode() { } public List> receipts() { + return receipts(false); + } + + public List> receipts(final boolean keepRlp) { final RLPInput input = new BytesValueRLPInput(data, false); input.enterList(); final List> receipts = new ArrayList<>(); @@ -81,7 +85,7 @@ public List> receipts() { final int setSize = input.enterList(); final List receiptSet = new ArrayList<>(setSize); for (int i = 0; i < setSize; i++) { - receiptSet.add(TransactionReceipt.readFrom(input, false)); + receiptSet.add(TransactionReceipt.readFrom(input.readAsRlp(), false, keepRlp)); } input.leaveList(); receipts.add(receiptSet); From 7f2337003fc398aa20aaf400fb8b90d0efe51ce4 Mon Sep 17 00:00:00 2001 From: "stefan.pingel@consensys.net" Date: Fri, 20 Sep 2024 17:39:10 +1000 Subject: [PATCH 2/3] use the rlp when it is available Signed-off-by: stefan.pingel@consensys.net --- .../hyperledger/besu/ethereum/core/TransactionReceipt.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java index 114f3578129..7c16a7c6c7b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java @@ -208,6 +208,11 @@ void writeTo(final RLPOutput rlpOutput, final boolean withRevertReason, final bo public void writeToForReceiptTrie( final RLPOutput rlpOutput, final boolean withRevertReason, final boolean compacted) { + if (rlp != null) { + rlpOutput.writeBytes(rlp); + return; + } + if (!transactionType.equals(TransactionType.FRONTIER)) { rlpOutput.writeIntScalar(transactionType.getSerializedType()); } From aa41457f1145e90995747587004da193a9c45a0f Mon Sep 17 00:00:00 2001 From: "stefan.pingel@consensys.net" Date: Fri, 20 Sep 2024 18:20:37 +1000 Subject: [PATCH 3/3] spotless Signed-off-by: stefan.pingel@consensys.net --- .../org/hyperledger/besu/ethereum/core/TransactionReceipt.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java index 7c16a7c6c7b..8a6c00472a8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java @@ -212,7 +212,7 @@ public void writeToForReceiptTrie( rlpOutput.writeBytes(rlp); return; } - + if (!transactionType.equals(TransactionType.FRONTIER)) { rlpOutput.writeIntScalar(transactionType.getSerializedType()); }