From 1c396b93d0ec1f98e222464245998914a0571466 Mon Sep 17 00:00:00 2001 From: Juraj Piar Date: Tue, 5 Mar 2024 10:01:01 +0000 Subject: [PATCH] feat(genesis): allows external genesis file test(genesis): adds file loader tests squashme: better catch handling --- .../core/genesis/GenesisLoaderException.java | 7 ++ .../core/genesis/GenesisLoaderImpl.java | 22 +++++- .../core/genesis/GenesisLoaderImplTest.java | 73 +++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderException.java create mode 100644 rskj-core/src/test/java/org/ethereum/core/genesis/GenesisLoaderImplTest.java diff --git a/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderException.java b/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderException.java new file mode 100644 index 00000000000..443c52ce657 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderException.java @@ -0,0 +1,7 @@ +package org.ethereum.core.genesis; + +public class GenesisLoaderException extends RuntimeException { + GenesisLoaderException(String message, Throwable error) { + super(message, error); + } +} diff --git a/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderImpl.java b/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderImpl.java index 75c53643711..01e818d226e 100644 --- a/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderImpl.java +++ b/rskj-core/src/main/java/org/ethereum/core/genesis/GenesisLoaderImpl.java @@ -44,6 +44,8 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -54,6 +56,7 @@ * 4. Registers the genesis state root in the state root handler */ public class GenesisLoaderImpl implements GenesisLoader { + private static final byte[] EMPTY_LIST_HASH = HashUtil.keccak256(RLP.encodeList()); private static final Logger logger = LoggerFactory.getLogger(GenesisLoaderImpl.class); @@ -81,7 +84,7 @@ public GenesisLoaderImpl( activationConfig, stateRootHandler, trieStore, - GenesisLoaderImpl.class.getResourceAsStream("/genesis/" + genesisFile), + loadGenesisFile(genesisFile), initialNonce, isRsk, useRskip92Encoding, @@ -230,6 +233,21 @@ private void setupPrecompiledContractsStorage(Repository repository) { } } + static InputStream loadGenesisFile(String fileName) { + InputStream inputStream = GenesisLoaderImpl.class.getResourceAsStream("/genesis/" + fileName); + if (inputStream != null) { + return inputStream; + } + + try { + return Files.newInputStream(Paths.get(fileName)); + } catch (Exception e) { + logger.error("Cannot read genesis json file"); + + throw new GenesisLoaderException("Cannot open genesis block configuration file", e); + } + } + public static void loadGenesisInitalState(Repository repository, Genesis genesis) { // first we need to create the accounts, which creates also the associated ContractDetails for (RskAddress accounts : genesis.getAccounts().keySet()) { @@ -259,7 +277,7 @@ private static GenesisJson readGenesisJson(InputStream inputStream) { } catch (Exception e) { logger.error("Cannot read genesis json file"); - throw new RuntimeException("Genesis block configuration is corrupted or not found ./resources/genesis/...", e); + throw new GenesisLoaderException("Genesis block configuration is corrupted or not found", e); } finally { closeStream(inputStream); } diff --git a/rskj-core/src/test/java/org/ethereum/core/genesis/GenesisLoaderImplTest.java b/rskj-core/src/test/java/org/ethereum/core/genesis/GenesisLoaderImplTest.java new file mode 100644 index 00000000000..9c9c268d888 --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/core/genesis/GenesisLoaderImplTest.java @@ -0,0 +1,73 @@ +package org.ethereum.core.genesis; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Objects; + +class GenesisLoaderImplTest { + private final String GENESIS_FILE_NAME = "temp_genesis.json"; + + private final String RESOURCES_GENESIS_FILE_PATH = Objects.requireNonNull(GenesisLoaderImpl.class.getResource("/genesis")).getPath() + "/" + GENESIS_FILE_NAME; + + @SuppressWarnings("ResultOfMethodCallIgnored") + private boolean isStreamReadable(InputStream stream) { + try { + stream.read(); + return true; + } catch (IOException e) { + return false; + } + } + + @BeforeEach + public void createTempFiles() throws IOException { + boolean created = (new File(RESOURCES_GENESIS_FILE_PATH)).createNewFile(); + Assertions.assertTrue(created); + } + + @AfterEach + public void cleanUpFiles() { + boolean deleted = (new File(RESOURCES_GENESIS_FILE_PATH)).delete(); + Assertions.assertTrue(deleted); + } + + @Test + void loadGenesisFile_fromResourcesDir() { + InputStream genesisFileStream = GenesisLoaderImpl.loadGenesisFile(GENESIS_FILE_NAME); + + Assertions.assertTrue(isStreamReadable(genesisFileStream)); + } + + @Test + void loadGenesisFile_missingFile_inResourcesDir() { + String genesisFilePath = new File("non-existent-file.json").getPath(); + + Exception e = Assertions.assertThrows(GenesisLoaderException.class, () -> GenesisLoaderImpl.loadGenesisFile(genesisFilePath)); + Assertions.assertEquals("Cannot open genesis block configuration file", e.getMessage()); + } + + @Test + void loadGenesisFile_fromSystem(@TempDir Path tempGenesisDir) throws IOException { + File genesisFile = new File(tempGenesisDir + "/" + GENESIS_FILE_NAME); + Assertions.assertTrue(genesisFile.createNewFile()); + InputStream genesisFileStream = GenesisLoaderImpl.loadGenesisFile(genesisFile.getPath()); + + Assertions.assertTrue(isStreamReadable(genesisFileStream)); + } + + @Test + void loadGenesisFile_missingFile_inSystem(@TempDir Path tempGenesisDir) { + String genesisFilePath = new File(tempGenesisDir + "/non-existent-file.json").getPath(); + + Exception e = Assertions.assertThrows(GenesisLoaderException.class, () -> GenesisLoaderImpl.loadGenesisFile(genesisFilePath)); + Assertions.assertEquals("Cannot open genesis block configuration file", e.getMessage()); + } +}