This is an automated email from the ASF dual-hosted git repository.
toulmean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git
The following commit(s) were added to refs/heads/main by this push:
new 43ab630 Add genesis lib
new 4f687c0 Merge pull request #372 from atoulme/add_genesis
43ab630 is described below
commit 43ab630c0c52721e9f94cb30d6c7a84bfe282baf
Author: Antoine Toulme <[email protected]>
AuthorDate: Wed Mar 2 00:25:13 2022 -0800
Add genesis lib
---
.../main/java/org/apache/tuweni/bytes/Bytes.java | 13 ++
.../main/java/org/apache/tuweni/eth/Address.java | 5 +
.../java/org/apache/tuweni/eth/EthJsonModule.java | 13 ++
genesis/build.gradle | 31 +++++
.../apache/tuweni/genesis/AllocationGenerator.kt | 35 +++++
.../kotlin/org/apache/tuweni/genesis/Genesis.kt | 67 +++++++++
.../main/kotlin/org/apache/tuweni/genesis/Main.kt | 42 ++++++
.../kotlin/org/apache/tuweni/genesis/Quorum.kt | 155 +++++++++++++++++++++
.../org/apache/tuweni/genesis/GenesisTest.kt | 52 +++++++
.../kotlin/org/apache/tuweni/genesis/QuorumTest.kt | 58 ++++++++
settings.gradle | 1 +
11 files changed, 472 insertions(+)
diff --git a/bytes/src/main/java/org/apache/tuweni/bytes/Bytes.java
b/bytes/src/main/java/org/apache/tuweni/bytes/Bytes.java
index 596812f..2d5faf3 100644
--- a/bytes/src/main/java/org/apache/tuweni/bytes/Bytes.java
+++ b/bytes/src/main/java/org/apache/tuweni/bytes/Bytes.java
@@ -592,6 +592,19 @@ public interface Bytes extends Comparable<Bytes> {
}
/**
+ * Generate a bytes object filled with the same byte.
+ *
+ * @param b the byte to fill the Bytes with
+ * @param size the size of the object
+ * @return a value filled with a fixed byte
+ */
+ static Bytes repeat(byte b, int size) {
+ byte[] buffer = new byte[size];
+ Arrays.fill(buffer, b);
+ return Bytes.wrap(buffer);
+ }
+
+ /**
*
* Provides the number of bytes this value represents.
*
diff --git a/eth/src/main/java/org/apache/tuweni/eth/Address.java
b/eth/src/main/java/org/apache/tuweni/eth/Address.java
index b7d426c..9dce379 100644
--- a/eth/src/main/java/org/apache/tuweni/eth/Address.java
+++ b/eth/src/main/java/org/apache/tuweni/eth/Address.java
@@ -25,6 +25,11 @@ import org.apache.tuweni.crypto.SECP256K1;
public final class Address extends DelegatingBytes {
/**
+ * Burn address.
+ */
+ public static final Address ZERO = Address.fromBytes(Bytes.repeat((byte) 0,
20));
+
+ /**
* Transform a public key into an Ethereum address.
*
* @param publicKey the public key
diff --git a/eth/src/main/java/org/apache/tuweni/eth/EthJsonModule.java
b/eth/src/main/java/org/apache/tuweni/eth/EthJsonModule.java
index f3e8719..66ea82d 100644
--- a/eth/src/main/java/org/apache/tuweni/eth/EthJsonModule.java
+++ b/eth/src/main/java/org/apache/tuweni/eth/EthJsonModule.java
@@ -56,6 +56,18 @@ public class EthJsonModule extends SimpleModule {
}
}
+ static class AddressKeySerializer extends StdSerializer<Address> {
+
+ protected AddressKeySerializer() {
+ super(Address.class);
+ }
+
+ @Override
+ public void serialize(Address value, JsonGenerator g, SerializerProvider
provider) throws IOException {
+ g.writeFieldName(value.toHexString());
+ }
+ }
+
static class BytesSerializer extends StdSerializer<Bytes> {
BytesSerializer() {
@@ -204,6 +216,7 @@ public class EthJsonModule extends SimpleModule {
public EthJsonModule() {
addSerializer(Hash.class, new HashSerializer());
addSerializer(Address.class, new AddressSerializer());
+ addKeySerializer(Address.class, new AddressKeySerializer());
addSerializer(Bytes.class, new BytesSerializer());
addSerializer(Gas.class, new GasSerializer());
addSerializer(UInt256.class, new UInt256Serializer());
diff --git a/genesis/build.gradle b/genesis/build.gradle
new file mode 100644
index 0000000..055ca26
--- /dev/null
+++ b/genesis/build.gradle
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE
+ * file distributed with this work for additional information regarding
copyright ownership. The ASF licenses this file
+ * to You 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.
+ */
+description = 'Create genesis blocks and related artifacts'
+
+dependencies {
+ implementation project(':bytes')
+ implementation project(':crypto')
+ implementation project(':eth')
+ implementation project(':rlp')
+ implementation project(':units')
+ implementation 'com.fasterxml.jackson.core:jackson-databind'
+ implementation 'org.bouncycastle:bcprov-jdk15on'
+
+
+ testImplementation project(':junit')
+ testImplementation 'org.bouncycastle:bcprov-jdk15on'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params'
+
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
+}
diff --git
a/genesis/src/main/kotlin/org/apache/tuweni/genesis/AllocationGenerator.kt
b/genesis/src/main/kotlin/org/apache/tuweni/genesis/AllocationGenerator.kt
new file mode 100644
index 0000000..0798b8b
--- /dev/null
+++ b/genesis/src/main/kotlin/org/apache/tuweni/genesis/AllocationGenerator.kt
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import org.apache.tuweni.crypto.SECP256K1
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.units.bigints.UInt256
+
+data class Allocation(val address: Address, val amount: UInt256, val keyPair:
SECP256K1.KeyPair)
+
+class AllocationGenerator {
+
+ fun createAllocations(numberAllocations: Int, amount: UInt256):
List<Allocation> {
+ val allocs = mutableListOf<Allocation>()
+ for (i in 0..numberAllocations) {
+ val keyPair = SECP256K1.KeyPair.random()
+ allocs.add(Allocation(Address.fromPublicKey(keyPair.publicKey()),
amount, keyPair))
+ }
+ return allocs
+ }
+}
diff --git a/genesis/src/main/kotlin/org/apache/tuweni/genesis/Genesis.kt
b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Genesis.kt
new file mode 100644
index 0000000..75eaa51
--- /dev/null
+++ b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Genesis.kt
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.bytes.Bytes32
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.units.bigints.UInt256
+
+@JsonPropertyOrder(alphabetic = true)
+open class GenesisConfig(
+ val chainId: Int,
+ val homesteadBlock: Int = 0,
+ val eip150Block: Int = 0,
+ val eip155Block: Int = 0,
+ val eip158Block: Int = 0,
+ val byzantiumBlock: Int = 0,
+ val constantinopleBlock: Int = 0,
+)
+
+/**
+ * Genesis block representation
+ *
+ * The block contains the information about the chain, and the initial state
of the chain, such as account balances.
+ */
+@JsonPropertyOrder("config", "nonce", "timestamp", "extraData", "gasLimit",
"difficulty", "number", "gasUsed", "parentHash", "mixHash", "coinbase", "alloc")
+class Genesis(
+ val nonce: Bytes,
+ val difficulty: UInt256,
+ val mixHash: Bytes32,
+ val coinbase: Address,
+ private val timestamp: Long,
+ val extraData: Bytes,
+ private val gasLimit: Long,
+ val parentHash: Bytes32,
+ val alloc: Map<Address, UInt256>,
+ val config: GenesisConfig,
+) {
+
+ fun getTimestamp(): String {
+ if (timestamp == 0L) {
+ return "0x0"
+ }
+ return Bytes.ofUnsignedLong(timestamp).toHexString()
+ }
+
+ fun getGasLimit(): String {
+ return Bytes.ofUnsignedLong(gasLimit).toHexString()
+ }
+
+ fun getNumber(): String = "0x0"
+}
diff --git a/genesis/src/main/kotlin/org/apache/tuweni/genesis/Main.kt
b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Main.kt
new file mode 100644
index 0000000..2dcd823
--- /dev/null
+++ b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Main.kt
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import com.fasterxml.jackson.databind.json.JsonMapper
+import org.apache.tuweni.bytes.Bytes32
+import org.apache.tuweni.eth.EthJsonModule
+import org.apache.tuweni.units.bigints.UInt256
+import org.bouncycastle.jce.provider.BouncyCastleProvider
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.security.Security
+
+fun main(args: Array<String>) {
+ Security.addProvider(BouncyCastleProvider())
+ val config = QuorumConfig.generate(
+ mixHash = Bytes32.random(), config = QuorumGenesisConfig(chainId =
args[0].toInt()),
+ numberValidators = 10,
+ numberAllocations = 10,
+ amount = UInt256.valueOf(3000)
+ )
+
+ val mapper = JsonMapper()
+ mapper.registerModule(EthJsonModule())
+ val contents =
mapper.writerWithDefaultPrettyPrinter().writeValueAsBytes(config.genesis)
+ Files.write(Paths.get("genesis.json"), contents)
+ Files.write(Paths.get("accounts.csv"), config.allocsToCsv().toByteArray())
+}
diff --git a/genesis/src/main/kotlin/org/apache/tuweni/genesis/Quorum.kt
b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Quorum.kt
new file mode 100644
index 0000000..70f3f88
--- /dev/null
+++ b/genesis/src/main/kotlin/org/apache/tuweni/genesis/Quorum.kt
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.annotation.JsonPropertyOrder
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.bytes.Bytes32
+import org.apache.tuweni.crypto.SECP256K1
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.rlp.RLP
+import org.apache.tuweni.units.bigints.UInt256
+
+class QuorumConfig(val genesis: Genesis, val validators:
List<SECP256K1.KeyPair>, val allocations: List<Allocation>) {
+
+ companion object {
+ val header = "User,Public key,Address,Secret key\n"
+
+ fun generate(
+ nonce: Bytes = Bytes.ofUnsignedLong(0),
+ difficulty: UInt256 = UInt256.ONE.shiftLeft(252),
+ mixHash: Bytes32,
+ coinbase: Address = Address.ZERO,
+ timestamp: Long = 0,
+ gasLimit: Long = 0,
+ parentHash: Bytes32 = Bytes32.ZERO,
+ vanity: Bytes32 = Bytes32.ZERO,
+ config: QuorumGenesisConfig,
+ numberValidators: Int,
+ numberAllocations: Int,
+ amount: UInt256,
+ ): QuorumConfig {
+ val allocations =
AllocationGenerator().createAllocations(numberAllocations, amount)
+
+ val validators = (0..numberValidators).map {
+ SECP256K1.KeyPair.random()
+ }
+
+ return generate(
+ nonce = nonce,
+ difficulty = difficulty,
+ mixHash = mixHash,
+ coinbase = coinbase,
+ timestamp = timestamp,
+ gasLimit = gasLimit,
+ parentHash = parentHash,
+ config = config,
+ vanity = vanity,
+ allocations = allocations,
+ validators = validators
+ )
+ }
+
+ fun generate(
+ nonce: Bytes = Bytes.ofUnsignedLong(0),
+ difficulty: UInt256 = UInt256.ONE.shiftLeft(252),
+ coinbase: Address = Address.ZERO,
+ timestamp: Long = 0,
+ gasLimit: Long = 0,
+ parentHash: Bytes32 = Bytes32.ZERO,
+ config: QuorumGenesisConfig,
+ vanity: Bytes32 = Bytes32.ZERO,
+ mixHash: Bytes32,
+ allocations: List<Allocation>,
+ validators: List<SECP256K1.KeyPair>,
+ ): QuorumConfig {
+ val allocs = mutableMapOf<Address, UInt256>()
+ for (alloc in allocations) {
+ allocs[alloc.address] = alloc.amount
+ }
+ val genesis = Genesis(
+ nonce = nonce,
+ difficulty = difficulty,
+ mixHash = mixHash,
+ coinbase = coinbase,
+ timestamp = timestamp,
+ gasLimit = gasLimit,
+ parentHash = parentHash,
+ alloc = allocs,
+ extraData = QBFTGenesisExtraData(vanity, validators).toBytes(),
+ config = config
+ )
+
+ return QuorumConfig(genesis, validators, allocations)
+ }
+ }
+
+ fun allocsToCsv(): String {
+ val lines = allocations.map {
+ "Unclaimed,${
+ it.keyPair.publicKey().toHexString()
+ },${it.address.toHexString()},${it.keyPair.secretKey().bytes()}"
+ }
+
+ return header + lines.joinToString("\n")
+ }
+}
+
+data class QBFTGenesisExtraData(val vanity: Bytes32, val validators:
List<SECP256K1.KeyPair>) {
+
+ /**
+ * A RLP serialization of the extradata for QBFT:
+ * RLP([32 bytes Vanity, List<Validators>, No Vote, Round=Int(0), 0 Seals]).
+ */
+ fun toBytes(): Bytes = RLP.encodeList {
+ it.writeValue(vanity)
+ it.writeList { valWriter ->
+ for (validator in validators) {
+ valWriter.writeValue(Address.fromPublicKey(validator.publicKey()))
+ }
+ }
+ it.writeList {}
+ it.writeString("")
+ it.writeList {}
+ }
+}
+
+class IstanbulConfigOptions(
+ val epoch: Int = 3000,
+ val policy: Int = 0,
+ val testQBFTBlock: Int = 0,
+ val ceil2Nby3Block: Int = 0,
+)
+
+@JsonPropertyOrder(alphabetic = true)
+class QuorumGenesisConfig(
+ chainId: Int,
+ homesteadBlock: Int = 0,
+ eip150Block: Int = 0,
+ eip155Block: Int = 0,
+ eip158Block: Int = 0,
+ byzantiumBlock: Int = 0,
+ constantinopleBlock: Int = 0,
+ val istanbul: IstanbulConfigOptions = IstanbulConfigOptions(),
+ val txnSizeLimit: Int = 64,
+ val maxCodeSize: Int = 0,
+) : GenesisConfig(chainId, homesteadBlock, eip150Block, eip155Block,
eip158Block, byzantiumBlock, constantinopleBlock) {
+
+ @JsonProperty("isQuorum")
+ fun isQuorum(): Boolean = true
+}
diff --git a/genesis/src/test/kotlin/org/apache/tuweni/genesis/GenesisTest.kt
b/genesis/src/test/kotlin/org/apache/tuweni/genesis/GenesisTest.kt
new file mode 100644
index 0000000..c23c961
--- /dev/null
+++ b/genesis/src/test/kotlin/org/apache/tuweni/genesis/GenesisTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import com.fasterxml.jackson.databind.json.JsonMapper
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.bytes.Bytes32
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.eth.EthJsonModule
+import org.apache.tuweni.eth.genesis.GenesisFile
+import org.apache.tuweni.junit.BouncyCastleExtension
+import org.apache.tuweni.units.bigints.UInt256
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+
+@ExtendWith(BouncyCastleExtension::class)
+class GenesisTest {
+
+ @Test
+ fun testMinimalJson() {
+ val genesis = Genesis(
+ nonce = Bytes.fromHexString("0xdeadbeef"),
+ difficulty = UInt256.ONE,
+ mixHash = Bytes32.leftPad(Bytes.fromHexString("0xf000")),
+ coinbase =
Address.fromHexString("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ timestamp = 0L,
+ extraData = Bytes.EMPTY,
+ gasLimit = 0L,
+ parentHash = Bytes32.leftPad(Bytes.fromHexString("0x00ff")),
+ alloc =
mapOf(Pair(Address.fromHexString("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
UInt256.ONE)),
+ config = GenesisConfig(chainId = 1337)
+ )
+ val mapper = JsonMapper()
+ mapper.registerModule(EthJsonModule())
+ val contents = mapper.writeValueAsBytes(genesis)
+ GenesisFile.read(contents)
+ }
+}
diff --git a/genesis/src/test/kotlin/org/apache/tuweni/genesis/QuorumTest.kt
b/genesis/src/test/kotlin/org/apache/tuweni/genesis/QuorumTest.kt
new file mode 100644
index 0000000..05b8daa
--- /dev/null
+++ b/genesis/src/test/kotlin/org/apache/tuweni/genesis/QuorumTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tuweni.genesis
+
+import com.fasterxml.jackson.databind.json.JsonMapper
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.bytes.Bytes32
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.eth.EthJsonModule
+import org.apache.tuweni.eth.genesis.GenesisFile
+import org.apache.tuweni.junit.BouncyCastleExtension
+import org.apache.tuweni.units.bigints.UInt256
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+
+@ExtendWith(BouncyCastleExtension::class)
+class QuorumTest {
+
+ @Test
+ fun testGenerateQuorumGenesis() {
+ val quorum = QuorumConfig.generate(
+ nonce = Bytes.fromHexString("0xdeadbeef"),
+ difficulty = UInt256.ONE.shiftLeft(252),
+ mixHash = Bytes32.leftPad(Bytes.fromHexString("0xf000")),
+ coinbase =
Address.fromHexString("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ timestamp = 0L,
+ gasLimit = 0L,
+ parentHash = Bytes32.leftPad(Bytes.fromHexString("0x00ff")),
+ config = QuorumGenesisConfig(chainId = 1337,),
+ numberAllocations = 10,
+ amount = UInt256.valueOf(123),
+ numberValidators = 4,
+ vanity = Bytes32.leftPad(Bytes.fromHexString("0xdeadbeef"))
+ )
+ val genesis = quorum.genesis
+ assertEquals(12, quorum.allocsToCsv().split("\n").size)
+ assertEquals("User,Public key,Address,Secret key",
quorum.allocsToCsv().split("\n")[0])
+ val mapper = JsonMapper()
+ mapper.registerModule(EthJsonModule())
+ val contents = mapper.writeValueAsBytes(genesis)
+ GenesisFile.read(contents)
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 3949e41..b798cc2 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -33,6 +33,7 @@ include 'eth-repository'
include 'ethstats'
include 'evm'
include 'eth-faucet'
+include 'genesis'
include 'gossip'
include 'hobbits'
include 'hobbits-relayer'
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]