Fix for block import withdrawals (#5442)

* Refactor to remove duplicated code that was handling RLP read/write. This logic doesn't change that ofter having the read and writes spread accross the code base has tripped some devs. We are now handling all the Body readfrom rlp and write to rlp using methods of the BlockBody class.

Signed-off-by: Gabriel Fukushima <gabrielfukushima@gmail.com>

---------

Signed-off-by: Gabriel Fukushima <gabrielfukushima@gmail.com>
pull/5451/head
Gabriel Fukushima 2 years ago committed by GitHub
parent 2571353a3b
commit 7fff05a4cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java
  2. 2
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/RestoreState.java
  3. 8
      besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java
  4. 11
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/BlockchainImporter.java
  5. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java
  6. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/StateBackupService.java
  7. 7
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
  8. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Block.java
  9. 62
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockBody.java
  10. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java
  11. 20
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/util/RawBlockIterator.java
  12. 5
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockSyncTestUtils.java
  13. 3
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java
  14. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/util/RawBlockIteratorTest.java
  15. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthServer.java
  16. 4
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessage.java
  17. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java
  18. 4
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessageTest.java
  19. 60
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java

@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Transaction;
@ -102,13 +103,9 @@ public class RlpBlockImporter implements Closeable {
final ProtocolContext context = besuController.getProtocolContext();
final MutableBlockchain blockchain = context.getBlockchain();
int count = 0;
try (final RawBlockIterator iterator =
new RawBlockIterator(
blocks,
rlp ->
BlockHeader.readFrom(
rlp, ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)))) {
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
try (final RawBlockIterator iterator = new RawBlockIterator(blocks, blockHeaderFunctions)) {
BlockHeader previousHeader = null;
CompletableFuture<Void> previousBlockFuture = null;
final AtomicReference<Throwable> threadedException = new AtomicReference<>();

@ -145,7 +145,7 @@ public class RestoreState implements Runnable {
BlockHeader.readFrom(
new BytesValueRLPInput(Bytes.wrap(headerEntry), false, true), functions);
final BlockBody body =
BlockBody.readFrom(
BlockBody.readWrappedBodyFrom(
new BytesValueRLPInput(Bytes.wrap(bodyEntry), false, true), functions);
final RLPInput receiptsRlp = new BytesValueRLPInput(Bytes.wrap(receiptEntry), false, true);
final int receiptsCount = receiptsRlp.enterList();

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
@ -244,10 +245,9 @@ public final class RlpBlockExporterTest {
}
private RawBlockIterator getBlockIterator(final Path blocks) throws IOException {
return new RawBlockIterator(
blocks,
rlp ->
BlockHeader.readFrom(rlp, ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)));
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
return new RawBlockIterator(blocks, blockHeaderFunctions);
}
private Block getBlock(final Blockchain blockchain, final long blockNumber) {

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
@ -43,14 +43,11 @@ public class BlockchainImporter {
protocolSchedule =
MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(genesisJson).getConfigOptions());
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
blocks = new ArrayList<>();
try (final RawBlockIterator iterator =
new RawBlockIterator(
Paths.get(blocksUrl.toURI()),
rlp ->
BlockHeader.readFrom(
rlp, ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)))) {
new RawBlockIterator(Paths.get(blocksUrl.toURI()), blockHeaderFunctions)) {
while (iterator.hasNext()) {
blocks.add(iterator.next());
}

@ -273,7 +273,7 @@ public class BlockAdapterBase extends AdapterBase {
.map(
blockBody -> {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
blockBody.writeTo(rlpOutput);
blockBody.writeWrappedBodyTo(rlpOutput);
return rlpOutput.encoded();
});
}

@ -307,7 +307,7 @@ public class StateBackupService {
headerWriter.writeBytes(headerOutput.encoded().toArrayUnsafe());
final BytesValueRLPOutput bodyOutput = new BytesValueRLPOutput();
block.get().getBody().writeTo(bodyOutput);
block.get().getBody().writeWrappedBodyTo(bodyOutput);
bodyWriter.writeBytes(bodyOutput.encoded().toArrayUnsafe());
final BytesValueRLPOutput receiptsOutput = new BytesValueRLPOutput();

@ -24,7 +24,7 @@ import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.DefaultSyncStatus;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
@ -106,11 +106,10 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
final URL genesisJsonUrl = BlockTestUtil.getTestGenesisUrl();
final BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions();
BLOCKS = new ArrayList<>();
try (final RawBlockIterator iterator =
new RawBlockIterator(
Paths.get(blocksUrl.toURI()),
rlp -> BlockHeader.readFrom(rlp, new MainnetBlockHeaderFunctions()))) {
new RawBlockIterator(Paths.get(blocksUrl.toURI()), blockHeaderFunctions)) {
while (iterator.hasNext()) {
BLOCKS.add(iterator.next());
}

@ -19,9 +19,7 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
@ -59,10 +57,7 @@ public class Block {
out.startList();
header.writeTo(out);
out.writeList(body.getTransactions(), Transaction::writeTo);
out.writeList(body.getOmmers(), BlockHeader::writeTo);
body.getWithdrawals().ifPresent(withdrawals -> out.writeList(withdrawals, Withdrawal::writeTo));
body.getDeposits().ifPresent(deposits -> out.writeList(deposits, Deposit::writeTo));
body.writeTo(out);
out.endList();
}
@ -70,15 +65,10 @@ public class Block {
public static Block readFrom(final RLPInput in, final BlockHeaderFunctions hashFunction) {
in.enterList();
final BlockHeader header = BlockHeader.readFrom(in, hashFunction);
final List<Transaction> transactions = in.readList(Transaction::readFrom);
final List<BlockHeader> ommers = in.readList(rlp -> BlockHeader.readFrom(rlp, hashFunction));
final Optional<List<Withdrawal>> withdrawals =
in.isEndOfCurrentList() ? Optional.empty() : Optional.of(in.readList(Withdrawal::readFrom));
final Optional<List<Deposit>> deposits =
in.isEndOfCurrentList() ? Optional.empty() : Optional.of(in.readList(Deposit::readFrom));
final BlockBody body = BlockBody.readFrom(in, hashFunction);
in.leaveList();
return new Block(header, new BlockBody(transactions, ommers, withdrawals, deposits));
return new Block(header, body);
}
@Override

@ -28,7 +28,9 @@ public class BlockBody implements org.hyperledger.besu.plugin.data.BlockBody {
new BlockBody(Collections.emptyList(), Collections.emptyList());
/**
* Adding a new field with a corresponding root hash in the block header will require a change in
* {@link org.hyperledger.besu.ethereum.eth.manager.task.GetBodiesFromPeerTask.BodyIdentifier }
* {@link org.hyperledger.besu.ethereum.eth.manager.task.GetBodiesFromPeerTask.BodyIdentifier}
* Also requires adding the new field to the constructor used in the {@link
* org.hyperledger.besu.ethereum.util.RawBlockIterator }
*/
private final List<Transaction> transactions;
@ -99,23 +101,35 @@ public class BlockBody implements org.hyperledger.besu.plugin.data.BlockBody {
*
* @param output Output to write to
*/
public void writeTo(final RLPOutput output) {
public void writeWrappedBodyTo(final RLPOutput output) {
output.startList();
writeTo(output);
output.endList();
}
public void writeTo(final RLPOutput output) {
output.writeList(getTransactions(), Transaction::writeTo);
output.writeList(getOmmers(), BlockHeader::writeTo);
withdrawals.ifPresent(withdrawals -> output.writeList(withdrawals, Withdrawal::writeTo));
deposits.ifPresent(deposits -> output.writeList(deposits, Deposit::writeTo));
output.endList();
}
public static BlockBody readFrom(
public static BlockBody readWrappedBodyFrom(
final RLPInput input, final BlockHeaderFunctions blockHeaderFunctions) {
return readFrom(input, blockHeaderFunctions, false);
return readWrappedBodyFrom(input, blockHeaderFunctions, false);
}
public static BlockBody readFrom(
/**
* Read all fields from the block body expecting a list wrapping them An example of valid body
* structure that this method would be able to read is: [[txs],[ommers],[withdrawals]] This is
* used for decoding list of bodies
*
* @param input The RLP-encoded input
* @param blockHeaderFunctions The block header functions used for parsing block headers
* @param allowEmptyBody A flag indicating whether an empty body is allowed
* @return the decoded BlockBody from the RLP
*/
public static BlockBody readWrappedBodyFrom(
final RLPInput input,
final BlockHeaderFunctions blockHeaderFunctions,
final boolean allowEmptyBody) {
@ -125,21 +139,33 @@ public class BlockBody implements org.hyperledger.besu.plugin.data.BlockBody {
input.leaveList();
return empty();
}
// TODO: Support multiple hard fork transaction formats.
final BlockBody body =
new BlockBody(
input.readList(Transaction::readFrom),
input.readList(rlp -> BlockHeader.readFrom(rlp, blockHeaderFunctions)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Withdrawal::readFrom)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Deposit::readFrom)));
final BlockBody body = readFrom(input, blockHeaderFunctions);
input.leaveList();
return body;
}
/**
* Read all fields from the block body expecting no list wrapping them. An example of a valid body
* would be: [txs],[ommers],[withdrawals],[deposits] this method is called directly when importing
* a single block
*
* @param input The RLP-encoded input
* @param blockHeaderFunctions The block header functions used for parsing block headers
* @return the BlockBody decoded from the RLP
*/
public static BlockBody readFrom(
final RLPInput input, final BlockHeaderFunctions blockHeaderFunctions) {
return new BlockBody(
input.readList(Transaction::readFrom),
input.readList(rlp -> BlockHeader.readFrom(rlp, blockHeaderFunctions)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Withdrawal::readFrom)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Deposit::readFrom)));
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;

@ -95,7 +95,7 @@ public class KeyValueStoragePrefixedKeyBlockchainStorage implements BlockchainSt
@Override
public Optional<BlockBody> getBlockBody(final Hash blockHash) {
return get(BLOCK_BODY_PREFIX, blockHash)
.map(bytes -> BlockBody.readFrom(RLP.input(bytes), blockHeaderFunctions));
.map(bytes -> BlockBody.readWrappedBodyFrom(RLP.input(bytes), blockHeaderFunctions));
}
@Override
@ -151,7 +151,7 @@ public class KeyValueStoragePrefixedKeyBlockchainStorage implements BlockchainSt
@Override
public void putBlockBody(final Hash blockHash, final BlockBody blockBody) {
set(BLOCK_BODY_PREFIX, blockHash, RLP.encode(blockBody::writeTo));
set(BLOCK_BODY_PREFIX, blockHash, RLP.encode(blockBody::writeWrappedBodyTo));
}
@Override

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.util;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
@ -29,7 +29,6 @@ import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
@ -37,25 +36,23 @@ public final class RawBlockIterator implements Iterator<Block>, Closeable {
private static final int DEFAULT_INIT_BUFFER_CAPACITY = 1 << 16;
private final FileChannel fileChannel;
private final Function<RLPInput, BlockHeader> headerReader;
private ByteBuffer readBuffer;
private final BlockHeaderFunctions blockHeaderFunctions;
private Block next;
RawBlockIterator(
final Path file,
final Function<RLPInput, BlockHeader> headerReader,
final int initialCapacity)
final Path file, final BlockHeaderFunctions blockHeaderFunctions, final int initialCapacity)
throws IOException {
this.blockHeaderFunctions = blockHeaderFunctions;
fileChannel = FileChannel.open(file);
this.headerReader = headerReader;
readBuffer = ByteBuffer.allocate(initialCapacity);
nextBlock();
}
public RawBlockIterator(final Path file, final Function<RLPInput, BlockHeader> headerReader)
public RawBlockIterator(final Path file, final BlockHeaderFunctions blockHeaderFunctions)
throws IOException {
this(file, headerReader, DEFAULT_INIT_BUFFER_CAPACITY);
this(file, blockHeaderFunctions, DEFAULT_INIT_BUFFER_CAPACITY);
}
@Override
@ -99,9 +96,8 @@ public final class RawBlockIterator implements Iterator<Block>, Closeable {
final Bytes rlpBytes = Bytes.wrap(Bytes.wrapByteBuffer(readBuffer, 0, length).toArray());
final RLPInput rlp = new BytesValueRLPInput(rlpBytes, false);
rlp.enterList();
final BlockHeader header = headerReader.apply(rlp);
final BlockBody body =
new BlockBody(rlp.readList(Transaction::readFrom), rlp.readList(headerReader));
final BlockHeader header = BlockHeader.readFrom(rlp, blockHeaderFunctions);
final BlockBody body = BlockBody.readFrom(rlp, blockHeaderFunctions);
next = new Block(header, body);
readBuffer.position(length);
readBuffer.compact();

@ -37,10 +37,9 @@ public final class BlockSyncTestUtils {
try {
temp.create();
final Path blocks = temp.newFile().toPath();
final BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions();
BlockTestUtil.write1000Blocks(blocks);
try (final RawBlockIterator iterator =
new RawBlockIterator(
blocks, rlp -> BlockHeader.readFrom(rlp, new MainnetBlockHeaderFunctions()))) {
try (final RawBlockIterator iterator = new RawBlockIterator(blocks, blockHeaderFunctions)) {
for (int i = 0; i < count; ++i) {
result.add(iterator.next());
}

@ -184,8 +184,7 @@ public class BlockchainSetupUtil {
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
try (final RawBlockIterator iterator =
new RawBlockIterator(
blocksPath, rlp -> BlockHeader.readFrom(rlp, blockHeaderFunctions))) {
new RawBlockIterator(blocksPath, blockHeaderFunctions)) {
while (iterator.hasNext()) {
blocks.add(iterator.next());
}

@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@ -77,14 +78,11 @@ public class RawBlockIteratorTest {
}
}
writer.close();
final BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions();
// Read blocks
final int initialCapacity = initialCapacityFromBlockSize.apply(firstSerializedBlock.length);
final RawBlockIterator iterator =
new RawBlockIterator(
blocksFile.toPath(),
rlp -> BlockHeader.readFrom(rlp, new MainnetBlockHeaderFunctions()),
initialCapacity);
new RawBlockIterator(blocksFile.toPath(), blockHeaderFunctions, initialCapacity);
// Read blocks and check that they match
for (int i = 0; i < blockCount; i++) {

@ -197,7 +197,7 @@ class EthServer {
final BlockBody body = maybeBody.get();
final BytesValueRLPOutput bodyOutput = new BytesValueRLPOutput();
body.writeTo(bodyOutput);
body.writeWrappedBodyTo(bodyOutput);
final int encodedSize = bodyOutput.encodedSize();
if (responseSizeEstimate + encodedSize > maxMessageSize) {
break;

@ -43,7 +43,7 @@ public final class BlockBodiesMessage extends AbstractMessageData {
public static BlockBodiesMessage create(final Iterable<BlockBody> bodies) {
final BytesValueRLPOutput tmp = new BytesValueRLPOutput();
tmp.writeList(bodies, BlockBody::writeTo);
tmp.writeList(bodies, BlockBody::writeWrappedBodyTo);
return new BlockBodiesMessage(tmp.encoded());
}
@ -71,6 +71,6 @@ public final class BlockBodiesMessage extends AbstractMessageData {
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
return new BytesValueRLPInput(data, false)
.readList(rlp -> BlockBody.readFrom(rlp, blockHeaderFunctions, true));
.readList(rlp -> BlockBody.readWrappedBodyFrom(rlp, blockHeaderFunctions, true));
}
}

@ -379,7 +379,7 @@ public class EthServerTest {
}
private int calculateRlpEncodedSize(final BlockBody blockBody) {
return RLP.encode(blockBody::writeTo).size();
return RLP.encode(blockBody::writeWrappedBodyTo).size();
}
private int calculateRlpEncodedSize(final BlockHeader header) {

@ -99,7 +99,7 @@ public final class BlockBodiesMessageTest {
@Test
public void shouldNotThrowRLPExceptionIfAllowedEmptyBody() {
final Bytes bytes = Bytes.fromHexString("0xc0");
final BlockBody empty = BlockBody.readFrom(RLP.input(bytes), null, true);
final BlockBody empty = BlockBody.readWrappedBodyFrom(RLP.input(bytes), null, true);
Assertions.assertThat(empty.isEmpty()).isTrue();
}
@ -111,7 +111,7 @@ public final class BlockBodiesMessageTest {
assertThrows(
RLPException.class,
() -> {
BlockBody.readFrom(RLP.input(bytes), blockHeaderFunctions, false);
BlockBody.readWrappedBodyFrom(RLP.input(bytes), blockHeaderFunctions, false);
});
}
}

@ -22,6 +22,7 @@ import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_MIN;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE_PLUS_1;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.datatypes.Address;
@ -34,6 +35,8 @@ import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.evm.log.LogTopic;
import org.hyperledger.besu.evm.log.LogsBloomFilter;
import org.hyperledger.besu.plugin.data.TransactionType;
@ -41,6 +44,7 @@ import org.hyperledger.besu.plugin.data.TransactionType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -231,6 +235,62 @@ public class MessageWrapperTest {
assertThat(actual).isEqualTo(expected);
}
@Test
public void readFromExpectsListWrappingBodyFields() {
// BodiesMessages broadcast bodies in this format
// [[txs],[ommers],[withdrawals]]
// 0xc3c0c0c0
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(Bytes.fromHexString("0xc3c0c0c0"), false);
final BlockBody blockBodyDecodefromRLP =
BlockBody.readWrappedBodyFrom(bytesValueRLPInput, new MainnetBlockHeaderFunctions());
assertThat(blockBodyDecodefromRLP)
.isEqualTo(
new BlockBody(
Collections.emptyList(),
Collections.emptyList(),
Optional.of(Collections.emptyList()),
Optional.empty()));
}
@Test
public void readBodyFieldsExpectsNoListWrappingBodyFields() {
// rlps of blocks contains block data in this format
// [[blockheader],[txs],[ommers],[withdrawals]]
// 0xc4c0c0c0c0
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(Bytes.fromHexString("0xc4c0c0c0c0"), false);
// Enters the initial
bytesValueRLPInput.enterList();
// skips block header list
bytesValueRLPInput.enterList();
bytesValueRLPInput.leaveList();
final BlockBody blockBodyDecodefromRLP =
BlockBody.readFrom(bytesValueRLPInput, new MainnetBlockHeaderFunctions());
assertThat(blockBodyDecodefromRLP)
.isEqualTo(
new BlockBody(
Collections.emptyList(),
Collections.emptyList(),
Optional.of(Collections.emptyList()),
Optional.empty()));
}
@Test
public void readBodyFieldsThrowsIfThereIsListWrappingBodyFields() {
// [[txs],[ommers],[withdrawals]]
// 0xc3c0c0c0
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(Bytes.fromHexString("0xc3c0c0c0"), false);
assertThrows(
RLPException.class,
() -> BlockBody.readFrom(bytesValueRLPInput, new MainnetBlockHeaderFunctions()));
}
private static class TestTransaction extends Transaction {
@JsonCreator

Loading…
Cancel
Save