Allow use of large chain ids (#1289)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Jason Frame 6 years ago committed by Trent Mohay
parent 4c873ef4af
commit d931e37903
  1. 20
      config/src/main/java/tech/pegasys/pantheon/config/ConfigUtil.java
  2. 4
      config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java
  3. 12
      config/src/main/java/tech/pegasys/pantheon/config/JsonGenesisConfigOptions.java
  4. 12
      config/src/test-support/java/tech/pegasys/pantheon/config/StubGenesisConfigOptions.java
  5. 16
      config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java
  6. 6
      config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java
  7. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java
  8. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java
  9. 2
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java
  10. 6
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java
  11. 3
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java
  12. 3
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java
  13. 64
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Transaction.java
  14. 3
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java
  15. 3
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java
  16. 15
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  17. 20
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetTransactionValidator.java
  18. 8
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java
  19. 5
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java
  20. 26
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java
  21. 7
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/BlockDataGenerator.java
  22. 3
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java
  23. 9
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TransactionTestFixture.java
  24. 23
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionIntegrationTest.java
  25. 30
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetTransactionValidatorTest.java
  26. 5
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java
  27. 2
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionHandlerTest.java
  28. 3
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java
  29. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java
  30. 2
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcResponseUtils.java
  31. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java
  32. 9
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthChainId.java
  33. 7
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/NetVersion.java
  34. 4
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/results/Quantity.java
  35. 5
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java
  36. 5
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java
  37. 4
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java
  38. 3
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminNodeInfoTest.java
  39. 22
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/EthChainIdTest.java
  40. 64
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/NetVersionTest.java
  41. 2
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetTransactionReceiptTest.java
  42. 2
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java
  43. 6
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
  44. 2
      pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java

@ -12,6 +12,8 @@
*/
package tech.pegasys.pantheon.config;
import java.math.BigInteger;
import java.util.Optional;
import java.util.OptionalLong;
import io.vertx.core.json.JsonObject;
@ -22,4 +24,22 @@ public class ConfigUtil {
? OptionalLong.of(jsonObject.getLong(key))
: OptionalLong.empty();
}
public static Optional<BigInteger> getOptionalBigInteger(
final JsonObject jsonObject, final String key) {
return jsonObject.containsKey(key)
? Optional.ofNullable(getBigInteger(jsonObject, key))
: Optional.empty();
}
private static BigInteger getBigInteger(final JsonObject jsonObject, final String key) {
final Number value = (Number) jsonObject.getMap().get(key);
if (value == null) {
return null;
} else if (value instanceof BigInteger) {
return (BigInteger) value;
} else {
return BigInteger.valueOf(value.longValue());
}
}
}

@ -12,7 +12,9 @@
*/
package tech.pegasys.pantheon.config;
import java.math.BigInteger;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
@ -48,7 +50,7 @@ public interface GenesisConfigOptions {
OptionalLong getConstantinopleFixBlockNumber();
OptionalInt getChainId();
Optional<BigInteger> getChainId();
OptionalInt getContractSizeLimit();

@ -12,7 +12,11 @@
*/
package tech.pegasys.pantheon.config;
import static tech.pegasys.pantheon.config.ConfigUtil.getOptionalBigInteger;
import java.math.BigInteger;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
@ -119,10 +123,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
}
@Override
public OptionalInt getChainId() {
return configRoot.containsKey("chainid")
? OptionalInt.of(configRoot.getInteger("chainid"))
: OptionalInt.empty();
public Optional<BigInteger> getChainId() {
return getOptionalBigInteger(configRoot, "chainid");
}
@Override
@ -135,7 +137,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
@Override
public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put("chainId", getChainId().getAsInt());
getChainId().ifPresent(chainId -> builder.put("chainId", chainId));
getHomesteadBlockNumber().ifPresent(l -> builder.put("homesteadBlock", l));
getDaoForkBlock()
.ifPresent(

@ -12,7 +12,9 @@
*/
package tech.pegasys.pantheon.config;
import java.math.BigInteger;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
@ -27,7 +29,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private OptionalLong byzantiumBlockNumber = OptionalLong.empty();
private OptionalLong constantinopleBlockNumber = OptionalLong.empty();
private OptionalLong constantinopleFixBlockNumber = OptionalLong.empty();
private OptionalInt chainId = OptionalInt.empty();
private Optional<BigInteger> chainId = Optional.empty();
private OptionalInt contractSizeLimit = OptionalInt.empty();
@Override
@ -111,14 +113,14 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
}
@Override
public OptionalInt getChainId() {
public Optional<BigInteger> getChainId() {
return chainId;
}
@Override
public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put("chainId", getChainId().getAsInt());
getChainId().ifPresent(chainId -> builder.put("chainId", chainId));
getHomesteadBlockNumber().ifPresent(l -> builder.put("homesteadBlock", l));
getDaoForkBlock()
.ifPresent(
@ -187,8 +189,8 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return this;
}
public StubGenesisConfigOptions chainId(final int chainId) {
this.chainId = OptionalInt.of(chainId);
public StubGenesisConfigOptions chainId(final BigInteger chainId) {
this.chainId = Optional.ofNullable(chainId);
return this;
}

@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
import java.math.BigInteger;
import java.util.Map;
import java.util.stream.Collectors;
@ -24,8 +25,8 @@ import org.junit.Test;
public class GenesisConfigFileTest {
private static final int MAINNET_CHAIN_ID = 1;
private static final int DEVELOPMENT_CHAIN_ID = 2018;
private static final BigInteger MAINNET_CHAIN_ID = BigInteger.ONE;
private static final BigInteger DEVELOPMENT_CHAIN_ID = BigInteger.valueOf(2018);
private static final GenesisConfigFile EMPTY_CONFIG = GenesisConfigFile.fromConfig("{}");
@Test
@ -170,6 +171,17 @@ public class GenesisConfigFileTest {
assertThat(config.getAllocations()).isEmpty();
}
@Test
public void shouldGetLargeChainId() {
final GenesisConfigFile config =
GenesisConfigFile.fromConfig(
"{\"config\": { \"chainId\": 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095 }}");
assertThat(config.getConfigOptions().getChainId())
.contains(
new BigInteger(
"31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095"));
}
private GenesisConfigFile configWithProperty(final String key, final String value) {
return GenesisConfigFile.fromConfig("{\"" + key + "\":\"" + value + "\"}");
}

@ -16,6 +16,7 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Map;
@ -128,8 +129,9 @@ public class GenesisConfigOptionsTest {
@Test
public void shouldGetChainIdWhenSpecified() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("chainId", 32));
assertThat(config.getChainId()).hasValue(32);
final GenesisConfigOptions config =
fromConfigOptions(singletonMap("chainId", BigInteger.valueOf(32)));
assertThat(config.getChainId()).hasValue(BigInteger.valueOf(32));
}
@Test

@ -29,10 +29,12 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger;
/** Defines the protocol behaviours for a blockchain using Clique. */
public class CliqueProtocolSchedule {
private static final int DEFAULT_CHAIN_ID = 4;
private static final BigInteger DEFAULT_CHAIN_ID = BigInteger.valueOf(4);
public static ProtocolSchedule<CliqueContext> create(
final GenesisConfigOptions config,

@ -30,7 +30,7 @@ import java.math.BigInteger;
/** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule {
private static final int DEFAULT_CHAIN_ID = 1;
private static final BigInteger DEFAULT_CHAIN_ID = BigInteger.ONE;
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final PrivacyParameters privacyParameters) {

@ -31,7 +31,7 @@ import java.math.BigInteger;
/** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule {
private static final int DEFAULT_CHAIN_ID = 1;
private static final BigInteger DEFAULT_CHAIN_ID = BigInteger.ONE;
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final PrivacyParameters privacyParameters) {

@ -31,6 +31,9 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.util.Subscribers;
import java.math.BigInteger;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.Test;
@ -124,7 +127,8 @@ public class BlockMinerTest {
}
private ProtocolSchedule<Void> singleSpecSchedule(final ProtocolSpec<Void> protocolSpec) {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(1234);
final MutableProtocolSchedule<Void> protocolSchedule =
new MutableProtocolSchedule<>(Optional.of(BigInteger.valueOf(1234)));
protocolSchedule.putMilestone(0, protocolSpec);
return protocolSchedule;
}

@ -52,6 +52,7 @@ import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.time.Instant;
import java.util.List;
import java.util.function.Supplier;
@ -567,7 +568,7 @@ public class BlockTransactionSelectorTest {
.to(Address.ID)
.value(Wei.of(transactionNumber))
.sender(Address.ID)
.chainId(1)
.chainId(BigInteger.ONE)
.signAndBuild(keyPair);
}

@ -29,6 +29,7 @@ import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException;
import java.math.BigInteger;
import java.util.function.Function;
import com.google.common.collect.Lists;
@ -53,7 +54,7 @@ public class EthHashBlockCreatorTest {
.protocolSchedule(
new ProtocolScheduleBuilder<>(
GenesisConfigFile.DEFAULT.getConfigOptions(),
42,
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT)
.createProtocolSchedule())

@ -28,20 +28,22 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
/** An operation submitted by an external actor to be applied to the system. */
public class Transaction {
// Used for transactions that are not tied to a specific chain
// (e.g. does not have a chain id associated with it).
private static final int REPLAY_UNPROTECTED_V_BASE = 27;
private static final BigInteger REPLAY_UNPROTECTED_V_BASE = BigInteger.valueOf(27);
private static final BigInteger REPLAY_UNPROTECTED_V_BASE_PLUS_1 = BigInteger.valueOf(28);
private static final int REPLAY_PROTECTED_V_BASE = 35;
private static final BigInteger REPLAY_PROTECTED_V_BASE = BigInteger.valueOf(35);
// The v signature parameter starts at 36 because 1 is the first valid chainId so:
// chainId > 1 implies that 2 * chainId + V_BASE > 36.
private static final int REPLAY_PROTECTED_V_MIN = 36;
private static final BigInteger REPLAY_PROTECTED_V_MIN = BigInteger.valueOf(36);
private static final BigInteger TWO = BigInteger.valueOf(2);
private final long nonce;
@ -57,7 +59,7 @@ public class Transaction {
private final BytesValue payload;
private final OptionalInt chainId;
private final Optional<BigInteger> chainId;
// Caches a "hash" of a portion of the transaction used for sender recovery.
// Note that this hash does not include the transaction signature so it does not
@ -87,14 +89,14 @@ public class Transaction {
.value(input.readUInt256Scalar(Wei::wrap))
.payload(input.readBytesValue());
final int v = input.readIntScalar();
final BigInteger v = input.readBigIntegerScalar();
final byte recId;
int chainId = -1;
if (v == REPLAY_UNPROTECTED_V_BASE || v == REPLAY_UNPROTECTED_V_BASE + 1) {
recId = (byte) (v - REPLAY_UNPROTECTED_V_BASE);
} else if (v > REPLAY_PROTECTED_V_MIN) {
chainId = (v - REPLAY_PROTECTED_V_BASE) / 2;
recId = (byte) (v - (2 * chainId + REPLAY_PROTECTED_V_BASE));
Optional<BigInteger> chainId = Optional.empty();
if (v.equals(REPLAY_UNPROTECTED_V_BASE) || v.equals(REPLAY_UNPROTECTED_V_BASE_PLUS_1)) {
recId = v.subtract(REPLAY_UNPROTECTED_V_BASE).byteValueExact();
} else if (v.compareTo(REPLAY_PROTECTED_V_MIN) > 0) {
chainId = Optional.of(v.subtract(REPLAY_PROTECTED_V_BASE).divide(TWO));
recId = v.subtract(TWO.multiply(chainId.get()).add(REPLAY_PROTECTED_V_BASE)).byteValueExact();
} else {
throw new RuntimeException(
String.format("An unsupported encoded `v` value of %s was found", v));
@ -105,7 +107,8 @@ public class Transaction {
input.leaveList();
return builder.chainId(chainId).signature(signature).build();
chainId.ifPresent(builder::chainId);
return builder.signature(signature).build();
}
/**
@ -134,7 +137,7 @@ public class Transaction {
final SECP256K1.Signature signature,
final BytesValue payload,
final Address sender,
final int chainId) {
final Optional<BigInteger> chainId) {
this.nonce = nonce;
this.gasPrice = gasPrice;
this.gasLimit = gasLimit;
@ -143,7 +146,7 @@ public class Transaction {
this.signature = signature;
this.payload = payload;
this.sender = sender;
this.chainId = chainId > 0 ? OptionalInt.of(chainId) : OptionalInt.empty();
this.chainId = chainId;
}
/**
@ -220,7 +223,7 @@ public class Transaction {
*
* @return the transaction chain id if it exists; otherwise {@code OptionalInt.empty()}
*/
public OptionalInt getChainId() {
public Optional<BigInteger> getChainId() {
return chainId;
}
@ -246,7 +249,7 @@ public class Transaction {
if (hashNoSignature == null) {
hashNoSignature =
computeSenderRecoveryHash(
nonce, gasPrice, gasLimit, to.isPresent() ? to.get() : null, value, payload, chainId);
nonce, gasPrice, gasLimit, to.orElse(null), value, payload, chainId);
}
return hashNoSignature;
}
@ -271,7 +274,7 @@ public class Transaction {
}
private void writeSignature(final RLPOutput out) {
out.writeIntScalar(getV());
out.writeBigIntegerScalar(getV());
out.writeBigIntegerScalar(getSignature().getR());
out.writeBigIntegerScalar(getSignature().getS());
}
@ -284,12 +287,13 @@ public class Transaction {
return signature.getS();
}
public int getV() {
final int v;
public BigInteger getV() {
final BigInteger v;
final BigInteger recId = BigInteger.valueOf(signature.getRecId());
if (!chainId.isPresent()) {
v = signature.getRecId() + REPLAY_UNPROTECTED_V_BASE;
v = recId.add(REPLAY_UNPROTECTED_V_BASE);
} else {
v = (getSignature().getRecId() + REPLAY_PROTECTED_V_BASE + 2 * chainId.getAsInt());
v = recId.add(REPLAY_PROTECTED_V_BASE).add(TWO.multiply(chainId.get()));
}
return v;
}
@ -345,7 +349,7 @@ public class Transaction {
final Address to,
final Wei value,
final BytesValue payload,
final OptionalInt chainId) {
final Optional<BigInteger> chainId) {
return keccak256(
RLP.encode(
out -> {
@ -357,7 +361,7 @@ public class Transaction {
out.writeUInt256Scalar(value);
out.writeBytesValue(payload);
if (chainId.isPresent()) {
out.writeIntScalar(chainId.getAsInt());
out.writeBigIntegerScalar(chainId.get());
out.writeUInt256Scalar(UInt256.ZERO);
out.writeUInt256Scalar(UInt256.ZERO);
}
@ -396,7 +400,7 @@ public class Transaction {
if (getTo().isPresent()) sb.append("to=").append(getTo().get()).append(", ");
sb.append("value=").append(getValue()).append(", ");
sb.append("sig=").append(getSignature()).append(", ");
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().getAsInt()).append(", ");
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", ");
sb.append("payload=").append(getPayload());
return sb.append("}").toString();
}
@ -426,10 +430,10 @@ public class Transaction {
protected Address sender;
protected int chainId = -1;
protected Optional<BigInteger> chainId = Optional.empty();
public Builder chainId(final int chainId) {
this.chainId = chainId;
public Builder chainId(final BigInteger chainId) {
this.chainId = Optional.of(chainId);
return this;
}
@ -495,10 +499,8 @@ public class Transaction {
}
protected SECP256K1.Signature computeSignature(final SECP256K1.KeyPair keys) {
final OptionalInt optionalChainId =
chainId > 0 ? OptionalInt.of(chainId) : OptionalInt.empty();
final Bytes32 hash =
computeSenderRecoveryHash(nonce, gasPrice, gasLimit, to, value, payload, optionalChainId);
computeSenderRecoveryHash(nonce, gasPrice, gasLimit, to, value, payload, chainId);
return SECP256K1.sign(hash, keys);
}
}

@ -12,8 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.difficulty.fixed;
import static tech.pegasys.pantheon.ethereum.mainnet.MainnetTransactionValidator.NO_CHAIN_ID;
import tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
@ -26,7 +24,6 @@ public class FixedDifficultyProtocolSchedule {
final GenesisConfigOptions config, final PrivacyParameters privacyParameters) {
return new ProtocolScheduleBuilder<>(
config,
NO_CHAIN_ID,
builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)),
privacyParameters)
.createProtocolSchedule();

@ -18,12 +18,13 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyCalculators;
import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule;
import java.math.BigInteger;
import java.util.function.Function;
/** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */
public class MainnetProtocolSchedule {
public static final int DEFAULT_CHAIN_ID = 1;
public static final BigInteger DEFAULT_CHAIN_ID = BigInteger.ONE;
public static ProtocolSchedule<Void> create() {
return fromConfig(GenesisConfigFile.mainnet().getConfigOptions(), PrivacyParameters.DEFAULT);

@ -26,8 +26,10 @@ import tech.pegasys.pantheon.ethereum.core.WorldUpdater;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionProcessor;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -73,7 +75,8 @@ public abstract class MainnetProtocolSpecs {
new MainnetContractCreationProcessor(
gasCalculator, evm, false, contractSizeLimit, 0))
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, false))
gasCalculator ->
new MainnetTransactionValidator(gasCalculator, false, Optional.empty()))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
@ -122,7 +125,7 @@ public abstract class MainnetProtocolSpecs {
new MainnetContractCreationProcessor(
gasCalculator, evm, true, contractSizeLimit, 0))
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true))
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, Optional.empty()))
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
.name("Homestead");
}
@ -160,7 +163,7 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> spuriousDragonDefinition(
final int chainId, final OptionalInt configContractSizeLimit) {
final Optional<BigInteger> chainId, final OptionalInt configContractSizeLimit) {
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
return tangerineWhistleDefinition(OptionalInt.empty())
@ -208,7 +211,7 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> byzantiumDefinition(
final int chainId, final OptionalInt contractSizeLimit) {
final Optional<BigInteger> chainId, final OptionalInt contractSizeLimit) {
return spuriousDragonDefinition(chainId, contractSizeLimit)
.evmBuilder(MainnetEvmRegistries::byzantium)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
@ -220,7 +223,7 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> constantinopleDefinition(
final int chainId, final OptionalInt contractSizeLimit) {
final Optional<BigInteger> chainId, final OptionalInt contractSizeLimit) {
return byzantiumDefinition(chainId, contractSizeLimit)
.difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE)
.gasCalculator(ConstantinopleGasCalculator::new)
@ -230,7 +233,7 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> constantinopleFixDefinition(
final int chainId, final OptionalInt contractSizeLimit) {
final Optional<BigInteger> chainId, final OptionalInt contractSizeLimit) {
return constantinopleDefinition(chainId, contractSizeLimit)
.gasCalculator(ConstantinopleFixGasCalculator::new)
.name("ConstantinopleFix");

@ -27,7 +27,8 @@ import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.vm.GasCalculator;
import java.util.OptionalInt;
import java.math.BigInteger;
import java.util.Optional;
/**
* Validates a transaction based on Frontier protocol runtime requirements.
@ -37,30 +38,23 @@ import java.util.OptionalInt;
*/
public class MainnetTransactionValidator implements TransactionValidator {
public static final int NO_CHAIN_ID = -1;
public static MainnetTransactionValidator create() {
return new MainnetTransactionValidator(new FrontierGasCalculator(), false);
return new MainnetTransactionValidator(new FrontierGasCalculator(), false, Optional.empty());
}
private final GasCalculator gasCalculator;
private final boolean disallowSignatureMalleability;
private final OptionalInt chainId;
public MainnetTransactionValidator(
final GasCalculator gasCalculator, final boolean checkSignatureMalleability) {
this(gasCalculator, checkSignatureMalleability, NO_CHAIN_ID);
}
private final Optional<BigInteger> chainId;
public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final boolean checkSignatureMalleability,
final int chainId) {
final Optional<BigInteger> chainId) {
this.gasCalculator = gasCalculator;
this.disallowSignatureMalleability = checkSignatureMalleability;
this.chainId = chainId > 0 ? OptionalInt.of(chainId) : OptionalInt.empty();
this.chainId = chainId;
}
@Override
@ -130,7 +124,7 @@ public class MainnetTransactionValidator implements TransactionValidator {
WRONG_CHAIN_ID,
String.format(
"transaction was meant for chain id %s and not this chain id %s",
transaction.getChainId().getAsInt(), chainId.getAsInt()));
transaction.getChainId().get(), chainId.get()));
}
if (!chainId.isPresent() && transaction.getChainId().isPresent()) {

@ -14,8 +14,10 @@ package tech.pegasys.pantheon.ethereum.mainnet;
import static com.google.common.base.Preconditions.checkArgument;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.TreeSet;
import java.util.stream.Collectors;
@ -25,14 +27,14 @@ public class MutableProtocolSchedule<C> implements ProtocolSchedule<C> {
new TreeSet<>(
Comparator.<ScheduledProtocolSpec<C>, Long>comparing(ScheduledProtocolSpec::getBlock)
.reversed());
private final int chainId;
private final Optional<BigInteger> chainId;
public MutableProtocolSchedule(final int chainId) {
public MutableProtocolSchedule(final Optional<BigInteger> chainId) {
this.chainId = chainId;
}
@Override
public int getChainId() {
public Optional<BigInteger> getChainId() {
return chainId;
}

@ -12,9 +12,12 @@
*/
package tech.pegasys.pantheon.ethereum.mainnet;
import java.math.BigInteger;
import java.util.Optional;
public interface ProtocolSchedule<C> {
ProtocolSpec<C> getByBlockNumber(long number);
int getChainId();
Optional<BigInteger> getChainId();
}

@ -15,6 +15,8 @@ package tech.pegasys.pantheon.ethereum.mainnet;
import tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import java.math.BigInteger;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
@ -25,22 +27,38 @@ public class ProtocolScheduleBuilder<C> {
private static final Logger LOG = LogManager.getLogger();
private final GenesisConfigOptions config;
private final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter;
private final int defaultChainId;
private final Optional<BigInteger> defaultChainId;
private final PrivacyParameters privacyParameters;
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final int defaultChainId,
final BigInteger defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters) {
this(config, Optional.of(defaultChainId), protocolSpecAdapter, privacyParameters);
}
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters) {
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters);
}
private ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final Optional<BigInteger> defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters) {
this.config = config;
this.protocolSpecAdapter = protocolSpecAdapter;
this.defaultChainId = defaultChainId;
this.protocolSpecAdapter = protocolSpecAdapter;
this.privacyParameters = privacyParameters;
}
public ProtocolSchedule<C> createProtocolSchedule() {
final int chainId = config.getChainId().orElse(defaultChainId);
final Optional<BigInteger> chainId =
config.getChainId().map(Optional::of).orElse(defaultChainId);
final MutableProtocolSchedule<C> protocolSchedule = new MutableProtocolSchedule<>(chainId);
validateForkOrdering();

@ -23,6 +23,7 @@ import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
@ -252,7 +253,7 @@ public class BlockDataGenerator {
.to(address())
.value(Wei.wrap(bytes32()))
.payload(payload)
.chainId(1)
.chainId(BigInteger.ONE)
.signAndBuild(SECP256K1.KeyPair.generate());
}
@ -264,7 +265,7 @@ public class BlockDataGenerator {
.to(address())
.value(Wei.wrap(bytes32()))
.payload(bytes32())
.chainId(1)
.chainId(BigInteger.ONE)
.signAndBuild(SECP256K1.KeyPair.generate());
}
@ -291,7 +292,7 @@ public class BlockDataGenerator {
signature,
payload,
to,
chainId))
Optional.of(BigInteger.valueOf(chainId))))
.collect(toSet());
return txs;
}

@ -28,6 +28,7 @@ import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage;
import tech.pegasys.pantheon.services.kvstore.KeyValueStorage;
import java.math.BigInteger;
import java.util.function.Function;
public class ExecutionContextTestFixture {
@ -111,7 +112,7 @@ public class ExecutionContextTestFixture {
protocolSchedule =
new ProtocolScheduleBuilder<>(
new StubGenesisConfigOptions().constantinopleFixBlock(0),
42,
BigInteger.valueOf(42),
Function.identity(),
new PrivacyParameters())
.createProtocolSchedule();

@ -15,6 +15,7 @@ package tech.pegasys.pantheon.ethereum.core;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import java.util.Optional;
public class TransactionTestFixture {
@ -32,7 +33,7 @@ public class TransactionTestFixture {
private BytesValue payload = BytesValue.EMPTY;
private int chainId = 2018;
private Optional<BigInteger> chainId = Optional.of(BigInteger.valueOf(2018));
public Transaction createTransaction(final KeyPair keys) {
final Transaction.Builder builder = Transaction.builder();
@ -42,10 +43,10 @@ public class TransactionTestFixture {
.nonce(nonce)
.payload(payload)
.value(value)
.sender(sender)
.chainId(chainId);
.sender(sender);
to.ifPresent(builder::to);
chainId.ifPresent(builder::chainId);
return builder.signAndBuild(keys);
}
@ -85,7 +86,7 @@ public class TransactionTestFixture {
return this;
}
public TransactionTestFixture chainId(final int chainId) {
public TransactionTestFixture chainId(final Optional<BigInteger> chainId) {
this.chainId = chainId;
return this;
}

@ -13,6 +13,7 @@
package tech.pegasys.pantheon.ethereum.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@ -21,6 +22,8 @@ import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import org.junit.Test;
public class TransactionIntegrationTest {
@ -35,7 +38,7 @@ public class TransactionIntegrationTest {
final Transaction transaction = Transaction.readFrom(input);
assertNotNull(transaction);
assertTrue(transaction.isContractCreation());
assertEquals(2018, transaction.getChainId().getAsInt());
assertEquals(BigInteger.valueOf(2018), transaction.getChainId().get());
assertEquals(
Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"),
transaction.getSender());
@ -52,4 +55,22 @@ public class TransactionIntegrationTest {
transaction.writeTo(output);
assertEquals(encodedString, output.encoded().toString());
}
@Test
public void shouldDecodeTransactionWithLargeChainId() {
final String encodedString =
"0xf86a018609184e72a0008276c094d30c3d13b07029deba00de1da369cd69a02c20560180850100000021a07d344f26d7329e8932d2878b99f07b12752bbd13a0b3b822644dbf9600fe718da01d6e6b6c66e1aadf4e33e318a7eef03d3bd3602de52662f0cb5af5b372d44dcd";
final BytesValue encoded = BytesValue.fromHexString(encodedString);
final RLPInput input = RLP.input(encoded);
final Transaction transaction = Transaction.readFrom(input);
assertNotNull(transaction);
assertFalse(transaction.isContractCreation());
assertEquals(BigInteger.valueOf(2147483647), transaction.getChainId().get());
assertEquals(
Address.fromHexString("0xdf664d0d2270ef97b48f222e3187bd14c8ca9428"),
transaction.getSender());
assertEquals(
Address.fromHexString("0xd30c3d13b07029deba00de1da369cd69a02c2056"),
transaction.getTo().get());
}
}

@ -31,6 +31,9 @@ import tech.pegasys.pantheon.ethereum.core.TransactionTestFixture;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.vm.GasCalculator;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -44,14 +47,19 @@ public class MainnetTransactionValidatorTest {
@Mock private GasCalculator gasCalculator;
private final Transaction basicTransaction =
new TransactionTestFixture().chainId(1).createTransaction(senderKeys);
new TransactionTestFixture()
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
@Test
public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false);
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
final Transaction transaction =
new TransactionTestFixture().gasLimit(10).chainId(0).createTransaction(senderKeys);
new TransactionTestFixture()
.gasLimit(10)
.chainId(Optional.empty())
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCost(transaction)).thenReturn(Gas.of(50));
assertThat(validator.validate(transaction))
@ -61,7 +69,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionHasChainIdAndValidatorDoesNot() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false);
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
assertThat(validator.validate(basicTransaction))
.isEqualTo(ValidationResult.invalid(REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED));
}
@ -69,7 +77,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionHasIncorrectChainId() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 2);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.valueOf(2)));
assertThat(validator.validate(basicTransaction))
.isEqualTo(ValidationResult.invalid(WRONG_CHAIN_ID));
}
@ -77,7 +85,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenSenderAccountDoesNotExist() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
assertThat(validator.validateForSender(basicTransaction, null, false))
.isEqualTo(ValidationResult.invalid(UPFRONT_COST_EXCEEDS_BALANCE));
}
@ -85,7 +93,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionNonceBelowAccountNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
final Account account = accountWithNonce(basicTransaction.getNonce() + 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -96,7 +104,7 @@ public class MainnetTransactionValidatorTest {
public void
shouldRejectTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsNotAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -107,7 +115,7 @@ public class MainnetTransactionValidatorTest {
public void
shouldAcceptTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, true))
@ -117,7 +125,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenNonceExceedsMaximumAllowedNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
final Transaction transaction =
new TransactionTestFixture().nonce(11).createTransaction(senderKeys);
@ -130,7 +138,7 @@ public class MainnetTransactionValidatorTest {
@Test
public void transactionWithNullSenderCanBeValidIfGasPriceAndValueIsZero() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, 1);
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
final TransactionTestFixture builder = new TransactionTestFixture();
final KeyPair senderKeyPair = KeyPair.generate();

@ -15,12 +15,15 @@ package tech.pegasys.pantheon.ethereum.mainnet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import java.math.BigInteger;
import java.util.Optional;
import org.assertj.core.api.Assertions;
import org.junit.Test;
public class ProtocolScheduleTest {
private static final int CHAIN_ID = 1;
private static final Optional<BigInteger> CHAIN_ID = Optional.of(BigInteger.ONE);
@SuppressWarnings("unchecked")
@Test

@ -79,7 +79,7 @@ public class PrivateTransactionHandlerTest {
.value(Wei.ZERO)
.payload(BytesValue.wrap(TRANSACTION_KEY.getBytes(Charsets.UTF_8)))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(2018)
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
Enclave mockEnclave() throws IOException {

@ -18,6 +18,7 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import java.math.BigInteger;
import java.util.Map;
import java.util.function.Function;
@ -25,7 +26,7 @@ import com.google.common.collect.ImmutableMap;
public class ReferenceTestProtocolSchedules {
private static final int CHAIN_ID = 1;
private static final BigInteger CHAIN_ID = BigInteger.ONE;
public static ReferenceTestProtocolSchedules create() {
final ImmutableMap.Builder<String, ProtocolSchedule<Void>> builder = ImmutableMap.builder();

@ -28,8 +28,10 @@ import tech.pegasys.pantheon.ethereum.vm.ehalt.ExceptionalHaltException;
import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState;
import tech.pegasys.pantheon.testutil.JsonTestParameters;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Optional;
import java.util.OptionalInt;
import org.junit.runner.RunWith;
@ -92,7 +94,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
"CallToPrecompiledContract",
"createNameRegistrator"
};
private static final int CHAIN_ID = 1;
private static final Optional<BigInteger> CHAIN_ID = Optional.of(BigInteger.ONE);
private final String name;
private final VMReferenceTestCaseSpec spec;

@ -155,7 +155,7 @@ public class JsonRpcResponseUtils {
final Transaction transaction = mock(Transaction.class);
when(transaction.getGasPrice()).thenReturn(Wei.fromHexString(gasPrice));
when(transaction.getNonce()).thenReturn(unsignedLong(nonce));
when(transaction.getV()).thenReturn(bigInteger(v).intValue());
when(transaction.getV()).thenReturn(bigInteger(v));
when(transaction.getR()).thenReturn(bigInteger(r));
when(transaction.getS()).thenReturn(bigInteger(s));
when(transaction.hash()).thenReturn(hash(hash));

@ -55,6 +55,7 @@ import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.util.List;
import org.assertj.core.util.Lists;
@ -282,7 +283,7 @@ public class EthGetFilterChangesIntegrationTest {
.to(Address.ID)
.value(Wei.of(transactionNumber))
.sender(Address.ID)
.chainId(1)
.chainId(BigInteger.ONE)
.signAndBuild(keyPair);
}

@ -17,11 +17,14 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.Quantity;
import java.math.BigInteger;
import java.util.Optional;
public class EthChainId implements JsonRpcMethod {
private final int chainId;
private final Optional<BigInteger> chainId;
public EthChainId(final int chainId) {
public EthChainId(final Optional<BigInteger> chainId) {
this.chainId = chainId;
}
@ -32,6 +35,6 @@ public class EthChainId implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequest req) {
return new JsonRpcSuccessResponse(req.getId(), Quantity.create(chainId));
return new JsonRpcSuccessResponse(req.getId(), chainId.map(Quantity::create).orElse(null));
}
}

@ -16,6 +16,9 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import java.math.BigInteger;
import java.util.Optional;
/**
* In Consensys' client, net_version maps to the network id, as specified in *
* https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version
@ -25,8 +28,8 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessRe
public class NetVersion implements JsonRpcMethod {
private final String chainId;
public NetVersion(final int chainId) {
this.chainId = String.valueOf(chainId);
public NetVersion(final Optional<BigInteger> chainId) {
this.chainId = String.valueOf(chainId.orElse(null));
}
@Override

@ -48,6 +48,10 @@ public class Quantity {
return uint256ToHex(UInt256.of(value));
}
public static String create(final BigInteger value) {
return uint256ToHex(UInt256.of(value));
}
public static String format(final BigInteger input) {
return formatMinimalValue(input.toString(16));
}

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@ -95,7 +96,9 @@ public class JsonRpcHttpServiceHostWhitelistTest {
blockchainQueries,
synchronizer,
MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
new StubGenesisConfigOptions()
.constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),

@ -41,6 +41,7 @@ import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.KeyStoreException;
@ -114,7 +115,7 @@ public class JsonRpcHttpServiceLoginTest {
supportedCapabilities.add(EthProtocol.ETH63);
final StubGenesisConfigOptions genesisConfigOptions =
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID);
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(BigInteger.valueOf(CHAIN_ID));
rpcMethods =
spy(
new JsonRpcMethodsFactory()
@ -388,7 +389,7 @@ public class JsonRpcHttpServiceLoginTest {
assertThat(token).isNotNull();
JsonRpcMethod ethAccounts = new EthAccounts();
JsonRpcMethod netVersion = new NetVersion(123);
JsonRpcMethod netVersion = new NetVersion(Optional.of(BigInteger.valueOf(123)));
JsonRpcMethod ethBlockNumber = new EthBlockNumber(blockchainQueries);
JsonRpcMethod web3Sha3 = new Web3Sha3();
JsonRpcMethod web3ClientVersion = new Web3ClientVersion("777");

@ -123,7 +123,9 @@ public class JsonRpcHttpServiceTest {
blockchainQueries,
synchronizer,
MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions().constantinopleBlock(0).chainId(CHAIN_ID)),
new StubGenesisConfigOptions()
.constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@ -57,7 +58,7 @@ public class AdminNodeInfoTest {
"0x0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807");
private final ChainHead testChainHead = new ChainHead(Hash.EMPTY, UInt256.ONE);
private final GenesisConfigOptions genesisConfigOptions =
new StubGenesisConfigOptions().chainId(2019);
new StubGenesisConfigOptions().chainId(BigInteger.valueOf(2019));
private final DefaultPeer defaultPeer = new DefaultPeer(nodeId, "1.2.3.4", 7890, 30303);
@Before

@ -19,17 +19,20 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.Quantity;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class EthChainIdTest {
private EthChainId method;
private final int CHAIN_ID = 1;
private final BigInteger CHAIN_ID = BigInteger.ONE;
@Before
public void setUp() {
method = new EthChainId(CHAIN_ID);
method = new EthChainId(Optional.of(CHAIN_ID));
}
@Test
@ -39,9 +42,20 @@ public class EthChainIdTest {
@Test
public void shouldReturnChainId() {
JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Quantity.create(CHAIN_ID));
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(null, Quantity.create(CHAIN_ID));
final JsonRpcResponse response = method.response(request());
assertThat(response).isEqualToComparingFieldByField(expectedResponse);
}
@Test
public void shouldReturnNullWhenNoChainId() {
method = new EthChainId(Optional.empty());
final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, null);
JsonRpcResponse response = method.response(request());
final JsonRpcResponse response = method.response(request());
assertThat(response).isEqualToComparingFieldByField(expectedResponse);
}

@ -0,0 +1,64 @@
/*
* Copyright 2018 ConsenSys AG.
*
* 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.
*/
package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class NetVersionTest {
private NetVersion method;
private final BigInteger CHAIN_ID = BigInteger.ONE;
@Before
public void setUp() {
method = new NetVersion(Optional.of(CHAIN_ID));
}
@Test
public void shouldReturnCorrectMethodName() {
assertThat(method.getName()).isEqualTo("net_version");
}
@Test
public void shouldReturnChainId() {
final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, CHAIN_ID.toString());
final JsonRpcResponse response = method.response(request());
assertThat(response).isEqualToComparingFieldByField(expectedResponse);
}
@Test
public void shouldReturnNullWhenNoChainId() {
method = new NetVersion(Optional.empty());
final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "null");
final JsonRpcResponse response = method.response(request());
assertThat(response).isEqualToComparingFieldByField(expectedResponse);
}
private JsonRpcRequest request() {
return new JsonRpcRequest(null, "net_version", null);
}
}

@ -109,7 +109,7 @@ public class EeaGetTransactionReceiptTest {
.value(Wei.ZERO)
.payload(BytesValue.wrap("EnclaveKey".getBytes(UTF_8)))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(2018)
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
private final Hash mockTransactionHash =

@ -84,7 +84,7 @@ public class EeaSendRawTransactionTest {
Byte.valueOf("0")),
BytesValue.fromHexString("0x"),
Address.wrap(BytesValue.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
0);
Optional.empty());
@Mock private TransactionPool transactionPool;

@ -1054,10 +1054,16 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
genesisConfigFile
.getConfigOptions()
.getChainId()
.map(BigInteger::intValueExact)
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId()));
} catch (final DecodeException e) {
throw new ParameterException(
this.commandLine, String.format("Unable to parse genesis file %s.", genesisFile), e);
} catch (final ArithmeticException e) {
throw new ParameterException(
this.commandLine,
"No networkId specified and chainId in "
+ "genesis file is too large to be used as a networkId");
}
}

@ -811,7 +811,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final GenesisConfigFile genesisConfigFile =
GenesisConfigFile.fromConfig(EthNetworkConfig.getNetworkConfig(MAINNET).getGenesisConfig());
assertThat(genesisConfigFile.getConfigOptions().getChainId().isPresent()).isTrue();
assertThat(genesisConfigFile.getConfigOptions().getChainId().getAsInt())
assertThat(genesisConfigFile.getConfigOptions().getChainId().get().intValueExact())
.isEqualTo(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId());
}

Loading…
Cancel
Save