From d8a342b8c7a9c27788e7bb7b1c8d8ed1e4853e13 Mon Sep 17 00:00:00 2001 From: shemnon Date: Sat, 20 Jul 2019 16:30:13 -0600 Subject: [PATCH] [PAN-2935] Add nonce handling to GenesisState Retesteh has some genesis file that specify a nonce in the relevant accounts. Add support to the GenesisState class to pre-set nonces. --- .../pantheon/config/GenesisAllocation.java | 6 +++- .../pantheon/ethereum/chain/GenesisState.java | 25 ++++++++------ .../ethereum/chain/GenesisStateTest.java | 14 ++++++++ .../pantheon/ethereum/chain/genesisNonce.json | 33 +++++++++++++++++++ 4 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 ethereum/core/src/test/resources/tech/pegasys/pantheon/ethereum/chain/genesisNonce.json diff --git a/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java b/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java index f748e1fccb..12ca3ca2b3 100644 --- a/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java +++ b/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java @@ -20,7 +20,7 @@ public class GenesisAllocation { private final String address; private final JsonObject data; - public GenesisAllocation(final String address, final JsonObject data) { + GenesisAllocation(final String address, final JsonObject data) { this.address = address; this.data = data; } @@ -37,6 +37,10 @@ public String getCode() { return data.getString("code"); } + public String getNonce() { + return data.getString("nonce", "0"); + } + public String getVersion() { return data.getString("version"); } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java index 1a7fa2a58d..f8b9f31481 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java @@ -110,6 +110,7 @@ private static void writeAccountsTo( genesisAccounts.forEach( genesisAccount -> { final MutableAccount account = updater.getOrCreate(genesisAccount.address); + account.setNonce(genesisAccount.nonce); account.setBalance(genesisAccount.balance); account.setCode(genesisAccount.code); account.setVersion(genesisAccount.version); @@ -194,16 +195,15 @@ private static Stream parseAllocations(final GenesisConfigFile g } private static long parseNonce(final GenesisConfigFile genesis) { - return withNiceErrorMessage( - "nonce", - genesis.getNonce(), - value -> { - String nonce = value.toLowerCase(Locale.US); - if (nonce.startsWith("0x")) { - nonce = nonce.substring(2); - } - return Long.parseUnsignedLong(nonce, 16); - }); + return withNiceErrorMessage("nonce", genesis.getNonce(), GenesisState::parseUnsignedLong); + } + + private static long parseUnsignedLong(final String value) { + String nonce = value.toLowerCase(Locale.US); + if (nonce.startsWith("0x")) { + nonce = nonce.substring(2); + } + return Long.parseUnsignedLong(nonce, 16); } @Override @@ -216,6 +216,7 @@ public String toString() { private static final class GenesisAccount { + final long nonce; final Address address; final Wei balance; final Map storage; @@ -224,6 +225,7 @@ private static final class GenesisAccount { static GenesisAccount fromAllocation(final GenesisAllocation allocation) { return new GenesisAccount( + allocation.getNonce(), allocation.getAddress(), allocation.getBalance(), allocation.getStorage(), @@ -232,11 +234,13 @@ static GenesisAccount fromAllocation(final GenesisAllocation allocation) { } private GenesisAccount( + final String hexNonce, final String hexAddress, final String balance, final Map storage, final String hexCode, final String version) { + this.nonce = withNiceErrorMessage("nonce", hexNonce, GenesisState::parseUnsignedLong); this.address = withNiceErrorMessage("address", hexAddress, Address::fromHexString); this.balance = withNiceErrorMessage("balance", balance, this::parseBalance); this.code = hexCode != null ? BytesValue.fromHexString(hexCode) : null; @@ -270,6 +274,7 @@ private Map parseStorage(final Map storage) { public String toString() { return MoreObjects.toStringHelper(this) .add("address", address) + .add("nonce", nonce) .add("balance", balance) .add("storage", storage) .add("code", code) diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java index 10c59deba2..1669f047cb 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java @@ -126,6 +126,20 @@ public void createFromJsonWithVersion() throws Exception { "genesis4.json", "0x3224ddae856381f5fb67492b4561ecbc0cb1e9e50e6cf3238f6e049fe95a8604", 1); } + @Test + public void createFromJsonWithNonce() throws Exception { + final GenesisState genesisState = + GenesisState.fromJson( + Resources.toString( + GenesisStateTest.class.getResource("genesisNonce.json"), Charsets.UTF_8), + MainnetProtocolSchedule.create()); + final BlockHeader header = genesisState.getBlock().getHeader(); + assertThat(header.getHash()) + .isEqualTo( + Hash.fromHexString( + "0x36750291f1a8429aeb553a790dc2d149d04dbba0ca4cfc7fd5eb12d478117c9f")); + } + @Test public void encodeOlympicBlock() throws Exception { final GenesisState genesisState = diff --git a/ethereum/core/src/test/resources/tech/pegasys/pantheon/ethereum/chain/genesisNonce.json b/ethereum/core/src/test/resources/tech/pegasys/pantheon/ethereum/chain/genesisNonce.json new file mode 100644 index 0000000000..2f692ed9d0 --- /dev/null +++ b/ethereum/core/src/test/resources/tech/pegasys/pantheon/ethereum/chain/genesisNonce.json @@ -0,0 +1,33 @@ +{ + "config" : { + "ethash" : { + "fixeddifficulty" : 0 + }, + "homesteadBlock" : 0, + "eip150Block" : 0, + "eip158Block" : 0, + "byzantiumBlock" : 0, + "constantinopleBlock" : 0 + }, + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x42", + "gasLimit" : "0x2fefd8", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "timestamp" : "0x54c98c81", + "alloc" : { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x", + "nonce" : "0x00", + "storage" : { } + }, + "0xec0e71ad0a90ffe1909d27dac207f7680abba42d" : { + "balance" : "0x01", + "code" : "0x6010ff", + "nonce" : "0x03", + "storage" : { } + } + } +} \ No newline at end of file