7935: add era1 format to blocks importer (#8352)

* Refactor to use clock to validate expiry

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* 7935: Finish unit testing E2StoreReader

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Build out E2StoreReader and associated files

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Spotless

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Add javadoc to new util module classes

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Implement Era1 block import sub command

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Remove unnecessary e2 and era file stuff

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Rename files to be era1 specific

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Rename e2 package to era1

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Spotless

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Rename Era1StoreReaderListener to Era1ReaderListener

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Clean up after merge

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Set up Era1BlockImporter to enable FAST sync and variations upon besu running

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Use bouncycastle for little endian to long conversion

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Rename slot related variables to blockIndex

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Spotless

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Fix broken unit test

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Fix AT compilation

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Fix javadoc

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Rework Era1BlockImporter to use appropriate data directory. Add unit test

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Fix javadoc

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* changelog

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Add era1 files to .gitattributes as binary file type

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

* Remove pivot block header file creation from Era1BlockImporter

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>

---------

Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>
Signed-off-by: Matilda-Clerke <matilda.clerke@consensys.net>
This commit is contained in:
Matilda-Clerke
2025-03-11 13:42:56 +11:00
committed by GitHub
parent e0bad4660e
commit 90db4872a4
13 changed files with 320 additions and 11 deletions

1
.gitattributes vendored
View File

@@ -17,4 +17,5 @@
*.p12 binary
*.db binary
*.woff2 binary
*.era1 binary
goss-linux-amd64 binary

View File

@@ -40,6 +40,7 @@
- Update `eth_getLogs` to return a `Block not found` error when the requested block is not found. [#8290](https://github.com/hyperledger/besu/pull/8290)
- Change `Invalid block, unable to parse RLP` RPC error message to `Invalid block param (block not found)` [#8328](https://github.com/hyperledger/besu/pull/8328)
- Support pending transaction score when saving and restoring txpool [#8363](https://github.com/hyperledger/besu/pull/8363)
- Add era1 format to blocks import subcommand [#7935](https://github.com/hyperledger/besu/issues/7935)
### Bug fixes
- Add missing RPC method `debug_accountRange` to `RpcMethod.java` so this method can be used with `--rpc-http-api-method-no-auth` [#8153](https://github.com/hyperledger/besu/issues/8153)

View File

@@ -19,6 +19,7 @@ import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import org.hyperledger.besu.Runner;
import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.Era1BlockImporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.BesuCommand;
@@ -632,6 +633,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
new BesuCommand(
RlpBlockImporter::new,
JsonBlockImporter::new,
Era1BlockImporter::new,
RlpBlockExporter::new,
new RunnerBuilder(),
new BesuController.Builder(),

View File

@@ -0,0 +1,171 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.chainimport;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.ProtocolContext;
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.BlockImporter;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.BodyValidationMode;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.util.era1.Era1BlockIndex;
import org.hyperledger.besu.util.era1.Era1ExecutionBlockBody;
import org.hyperledger.besu.util.era1.Era1ExecutionBlockHeader;
import org.hyperledger.besu.util.era1.Era1ExecutionBlockReceipts;
import org.hyperledger.besu.util.era1.Era1Reader;
import org.hyperledger.besu.util.era1.Era1ReaderListener;
import org.hyperledger.besu.util.snappy.SnappyFactory;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Tool for importing era1-encoded block data, headers, and transaction receipts from era1 files.
*/
public class Era1BlockImporter implements Closeable {
private static final Logger LOG = LoggerFactory.getLogger(Era1BlockImporter.class);
private static final int ERA1_BLOCK_COUNT_MAX = 8192;
private static final int IMPORT_COUNT_FOR_LOG_UPDATE = 1000;
/** Default Constructor. */
public Era1BlockImporter() {}
/**
* Imports the blocks, headers, and transaction receipts from the file found at the supplied path
*
* @param controller The BesuController
* @param path The path
* @throws IOException IOException
* @throws ExecutionException ExecutionException
* @throws InterruptedException InterruptedException
* @throws TimeoutException TimeoutException
*/
public void importBlocks(final BesuController controller, final Path path)
throws IOException, ExecutionException, InterruptedException, TimeoutException {
final ProtocolSchedule protocolSchedule = controller.getProtocolSchedule();
final BlockHeaderFunctions blockHeaderFunctions =
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
final ProtocolContext context = controller.getProtocolContext();
Era1Reader reader = new Era1Reader(new SnappyFactory());
final List<Future<BlockHeader>> headersFutures = new ArrayList<>(ERA1_BLOCK_COUNT_MAX);
final List<Future<BlockBody>> bodiesFutures = new ArrayList<>(ERA1_BLOCK_COUNT_MAX);
final List<Future<List<TransactionReceipt>>> receiptsFutures =
new ArrayList<>(ERA1_BLOCK_COUNT_MAX);
reader.read(
new FileInputStream(path.toFile()),
new Era1ReaderListener() {
@Override
public void handleExecutionBlockHeader(
final Era1ExecutionBlockHeader executionBlockHeader) {
headersFutures.add(
CompletableFuture.supplyAsync(
() ->
BlockHeader.readFrom(
new BytesValueRLPInput(
Bytes.wrap(executionBlockHeader.header()), false),
blockHeaderFunctions)));
}
@Override
public void handleExecutionBlockBody(final Era1ExecutionBlockBody executionBlockBody) {
bodiesFutures.add(
CompletableFuture.supplyAsync(
() ->
BlockBody.readWrappedBodyFrom(
new BytesValueRLPInput(Bytes.wrap(executionBlockBody.block()), false),
blockHeaderFunctions,
true)));
}
@Override
public void handleExecutionBlockReceipts(
final Era1ExecutionBlockReceipts executionBlockReceipts) {
receiptsFutures.add(
CompletableFuture.supplyAsync(
() -> {
RLPInput input =
new BytesValueRLPInput(
Bytes.wrap(executionBlockReceipts.receipts()), false);
final List<TransactionReceipt> receiptsForBlock = new ArrayList<>();
input.readList((in) -> receiptsForBlock.add(TransactionReceipt.readFrom(in)));
return receiptsForBlock;
}));
}
@Override
public void handleBlockIndex(final Era1BlockIndex blockIndex) {
// not really necessary, do nothing
}
});
LOG.info("Read {} blocks, now importing", headersFutures.size());
Block block = null;
for (int i = 0; i < headersFutures.size(); i++) {
BlockHeader blockHeader = headersFutures.get(i).get(10, TimeUnit.SECONDS);
BlockImporter blockImporter =
protocolSchedule.getByBlockHeader(blockHeader).getBlockImporter();
block = new Block(blockHeader, bodiesFutures.get(i).get(10, TimeUnit.SECONDS));
BlockImportResult importResult =
blockImporter.importBlockForSyncing(
context,
block,
receiptsFutures.get(i).get(10, TimeUnit.SECONDS),
HeaderValidationMode.NONE,
HeaderValidationMode.NONE,
BodyValidationMode.NONE,
false);
if (importResult.getStatus() != BlockImportResult.BlockImportStatus.IMPORTED) {
LOG.warn(
"Failed to import block {} due to {}",
blockHeader.getNumber(),
importResult.getStatus());
} else if (i % IMPORT_COUNT_FOR_LOG_UPDATE == 0) {
LOG.info("{}/{} blocks imported", i, headersFutures.size());
}
}
LOG.info("Done importing {} blocks", headersFutures.size());
}
@Override
public void close() throws IOException {}
}

View File

@@ -31,6 +31,7 @@ import org.hyperledger.besu.BesuInfo;
import org.hyperledger.besu.Runner;
import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.Era1BlockImporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
@@ -284,6 +285,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final Supplier<RlpBlockImporter> rlpBlockImporter;
private final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory;
private final Supplier<Era1BlockImporter> era1BlockImporter;
private final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory;
// Unstable CLI options
@@ -719,6 +721,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
*
* @param rlpBlockImporter RlpBlockImporter supplier
* @param jsonBlockImporterFactory instance of {@code Function<BesuController, JsonBlockImporter>}
* @param era1BlockImporter Era1BlockImporter supplier
* @param rlpBlockExporterFactory instance of {@code Function<Blockchain, RlpBlockExporter>}
* @param runnerBuilder instance of RunnerBuilder
* @param controllerBuilder instance of BesuController.Builder
@@ -729,6 +732,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
public BesuCommand(
final Supplier<RlpBlockImporter> rlpBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final RunnerBuilder runnerBuilder,
final BesuController.Builder controllerBuilder,
@@ -738,6 +742,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
this(
rlpBlockImporter,
jsonBlockImporterFactory,
era1BlockImporter,
rlpBlockExporterFactory,
runnerBuilder,
controllerBuilder,
@@ -760,6 +765,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
*
* @param rlpBlockImporter RlpBlockImporter supplier
* @param jsonBlockImporterFactory instance of {@code Function<BesuController, JsonBlockImporter>}
* @param era1BlockImporter Era1BlockImporter supplier
* @param rlpBlockExporterFactory instance of {@code Function<Blockchain, RlpBlockExporter>}
* @param runnerBuilder instance of RunnerBuilder
* @param controllerBuilder instance of BesuController.Builder
@@ -780,6 +786,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
protected BesuCommand(
final Supplier<RlpBlockImporter> rlpBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final RunnerBuilder runnerBuilder,
final BesuController.Builder controllerBuilder,
@@ -798,8 +805,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
this.logger = commandLogger;
this.rlpBlockImporter = rlpBlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
this.jsonBlockImporterFactory = jsonBlockImporterFactory;
this.era1BlockImporter = era1BlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
this.runnerBuilder = runnerBuilder;
this.controllerBuilder = controllerBuilder;
this.besuPluginContext = besuPluginContext;
@@ -1100,6 +1108,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
new BlocksSubCommand(
rlpBlockImporter,
jsonBlockImporterFactory,
era1BlockImporter,
rlpBlockExporterFactory,
commandLine.getOut()));
commandLine.addSubcommand(

View File

@@ -19,5 +19,7 @@ public enum BlockImportFormat {
/** RLP block import format. */
RLP,
/** Json block import format. */
JSON
JSON,
/** Era1 block import format. */
ERA1,
}

View File

@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand.COMMAND_NAME;
import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.Era1BlockImporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.BesuCommand;
@@ -51,6 +52,7 @@ import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -92,6 +94,7 @@ public class BlocksSubCommand implements Runnable {
private final Supplier<RlpBlockImporter> rlpBlockImporter;
private final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory;
private final Supplier<Era1BlockImporter> era1BlockImporter;
private final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory;
private final PrintWriter out;
@@ -101,17 +104,20 @@ public class BlocksSubCommand implements Runnable {
*
* @param rlpBlockImporter the RLP block importer
* @param jsonBlockImporterFactory the Json block importer factory
* @param era1BlockImporter the era1 block importer supplier
* @param rlpBlockExporterFactory the RLP block exporter factory
* @param out Instance of PrintWriter where command usage will be written.
*/
public BlocksSubCommand(
final Supplier<RlpBlockImporter> rlpBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final PrintWriter out) {
this.rlpBlockImporter = rlpBlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
this.jsonBlockImporterFactory = jsonBlockImporterFactory;
this.era1BlockImporter = era1BlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
this.out = out;
}
@@ -198,6 +204,7 @@ public class BlocksSubCommand implements Runnable {
checkCommand(parentCommand);
checkNotNull(parentCommand.rlpBlockImporter);
checkNotNull(parentCommand.jsonBlockImporterFactory);
checkNotNull(parentCommand.era1BlockImporter);
if (blockImportFiles.isEmpty()) {
throw new ParameterException(spec.commandLine(), "No files specified to import.");
}
@@ -214,12 +221,9 @@ public class BlocksSubCommand implements Runnable {
try {
LOG.info("Importing from {}", path);
switch (format) {
case RLP:
importRlpBlocks(controller, path);
break;
case JSON:
importJsonBlocks(controller, path);
break;
case RLP -> importRlpBlocks(controller, path);
case JSON -> importJsonBlocks(controller, path);
case ERA1 -> importEra1Blocks(controller, path);
}
} catch (final FileNotFoundException e) {
if (blockImportFiles.size() == 1) {
@@ -297,6 +301,14 @@ public class BlocksSubCommand implements Runnable {
.get()
.importBlockchain(path, controller, skipPow, startBlock, endBlock);
}
private void importEra1Blocks(final BesuController controller, final Path path)
throws IOException,
java.util.concurrent.ExecutionException,
InterruptedException,
TimeoutException {
parentCommand.era1BlockImporter.get().importBlocks(controller, path);
}
}
/**

View File

@@ -17,6 +17,7 @@ package org.hyperledger.besu.components;
import org.hyperledger.besu.Besu;
import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.Era1BlockImporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.BesuCommand;
@@ -50,6 +51,7 @@ public class BesuCommandModule {
new BesuCommand(
RlpBlockImporter::new,
JsonBlockImporter::new,
Era1BlockImporter::new,
RlpBlockExporter::new,
new RunnerBuilder(),
new BesuController.Builder(),

View File

@@ -0,0 +1,95 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.chainimport;
import static org.mockito.Mockito.mock;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.components.BesuComponent;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.testutil.BlockTestUtil;
import org.hyperledger.besu.testutil.TestClock;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class Era1BlockImporterTest {
@TempDir Path dataDirectory;
private final Era1BlockImporter era1BlockImporter = new Era1BlockImporter();
@Test
public void testImport()
throws IOException,
ExecutionException,
InterruptedException,
TimeoutException,
URISyntaxException {
final Path source =
Path.of(
BlockTestUtil.class
.getClassLoader()
.getResource("mainnet-00000-5ec1ffb8.era1")
.toURI());
final BesuController targetController =
new BesuController.Builder()
.fromEthNetworkConfig(
EthNetworkConfig.getNetworkConfig(NetworkName.MAINNET), SyncMode.FAST)
.synchronizerConfiguration(SynchronizerConfiguration.builder().build())
.ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig())
.storageProvider(new InMemoryKeyValueStorageProvider())
.networkId(BigInteger.ONE)
.miningParameters(MiningConfiguration.newDefault())
.nodeKey(NodeKeyUtils.generate())
.metricsSystem(new NoOpMetricsSystem())
.privacyParameters(PrivacyParameters.DEFAULT)
.clock(TestClock.fixed())
.transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT)
.evmConfiguration(EvmConfiguration.DEFAULT)
.networkConfiguration(NetworkingConfiguration.create())
.besuComponent(mock(BesuComponent.class))
.apiConfiguration(ImmutableApiConfiguration.builder().build())
.dataDirectory(dataDirectory)
.build();
era1BlockImporter.importBlocks(targetController, source);
Blockchain blockchain = targetController.getProtocolContext().getBlockchain();
BlockHeader chainHeadHeader = blockchain.getChainHeadHeader();
Assertions.assertEquals(8191, chainHeadHeader.getNumber());
}
}

View File

@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.Runner;
import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.Era1BlockImporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
@@ -216,6 +217,7 @@ public abstract class CommandTestAbstract {
@Mock protected RlpBlockExporter rlpBlockExporter;
@Mock protected JsonBlockImporter jsonBlockImporter;
@Mock protected RlpBlockImporter rlpBlockImporter;
@Mock protected Era1BlockImporter era1BlockImporter;
@Mock protected StorageServiceImpl storageService;
@Mock protected TransactionSelectionServiceImpl txSelectionService;
@Mock protected SecurityModuleServiceImpl securityModuleService;
@@ -472,6 +474,7 @@ public abstract class CommandTestAbstract {
return new TestBesuCommandWithRequiredOption(
() -> rlpBlockImporter,
this::jsonBlockImporterFactory,
() -> era1BlockImporter,
(blockchain) -> rlpBlockExporter,
mockRunnerBuilder,
mockControllerBuilderFactory,
@@ -485,6 +488,7 @@ public abstract class CommandTestAbstract {
return new TestBesuCommand(
() -> rlpBlockImporter,
this::jsonBlockImporterFactory,
() -> era1BlockImporter,
(blockchain) -> rlpBlockExporter,
mockRunnerBuilder,
mockControllerBuilderFactory,
@@ -498,6 +502,7 @@ public abstract class CommandTestAbstract {
return new TestBesuCommandWithoutPortCheck(
() -> rlpBlockImporter,
this::jsonBlockImporterFactory,
() -> era1BlockImporter,
(blockchain) -> rlpBlockExporter,
mockRunnerBuilder,
mockControllerBuilderFactory,
@@ -538,6 +543,7 @@ public abstract class CommandTestAbstract {
TestBesuCommand(
final Supplier<RlpBlockImporter> mockBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final RunnerBuilder mockRunnerBuilder,
final BesuController.Builder controllerBuilderFactory,
@@ -550,6 +556,7 @@ public abstract class CommandTestAbstract {
super(
mockBlockImporter,
jsonBlockImporterFactory,
era1BlockImporter,
rlpBlockExporterFactory,
mockRunnerBuilder,
controllerBuilderFactory,
@@ -635,6 +642,7 @@ public abstract class CommandTestAbstract {
TestBesuCommandWithRequiredOption(
final Supplier<RlpBlockImporter> mockBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final RunnerBuilder mockRunnerBuilder,
final BesuController.Builder controllerBuilderFactory,
@@ -647,6 +655,7 @@ public abstract class CommandTestAbstract {
super(
mockBlockImporter,
jsonBlockImporterFactory,
era1BlockImporter,
rlpBlockExporterFactory,
mockRunnerBuilder,
controllerBuilderFactory,
@@ -669,6 +678,7 @@ public abstract class CommandTestAbstract {
TestBesuCommandWithoutPortCheck(
final Supplier<RlpBlockImporter> mockBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Supplier<Era1BlockImporter> era1BlockImporter,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
final RunnerBuilder mockRunnerBuilder,
final BesuController.Builder controllerBuilderFactory,
@@ -681,6 +691,7 @@ public abstract class CommandTestAbstract {
super(
mockBlockImporter,
jsonBlockImporterFactory,
era1BlockImporter,
rlpBlockExporterFactory,
mockRunnerBuilder,
controllerBuilderFactory,

View File

@@ -72,7 +72,7 @@ public class BlocksSubCommandTest extends CommandTestAbstract {
+ " (exclusive). If not specified all blocks after\n"
+ " the start block will be imported.\n"
+ " --format=<format> The type of data to be imported, possible values\n"
+ " are: RLP, JSON (default: RLP).\n"
+ " are: RLP, JSON, ERA1 (default: RLP).\n"
+ " --from[=<FILE>...] File containing blocks to import.\n"
+ " -h, --help Show this help message and exit.\n"
+ " --run Start besu after importing.\n"

Binary file not shown.

View File

@@ -252,7 +252,10 @@ public class BlockHeader extends SealableBlockHeader
public static BlockHeader readFrom(
final RLPInput input, final BlockHeaderFunctions blockHeaderFunctions) {
final RLPInput headerRlp = input.readAsRlp();
headerRlp.enterList();
if (headerRlp.enterList() == 0) {
return null;
}
final Hash parentHash = Hash.wrap(headerRlp.readBytes32());
final Hash ommersHash = Hash.wrap(headerRlp.readBytes32());
final Address coinbase = Address.readFrom(headerRlp);