diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2821eab33..17bd4f09e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,8 @@
### Additions and Improvements
- Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494)
--
+- Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496)
+
### Bug Fixes
### Download Links
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java
index bfaf092b3..251f4815b 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java
@@ -17,8 +17,13 @@ package org.hyperledger.besu.ethereum.api.graphql.internal;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
import graphql.language.IntValue;
import graphql.language.StringValue;
+import graphql.language.Value;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -35,19 +40,19 @@ public class Scalars {
private static final Coercing
ADDRESS_COERCING =
new Coercing() {
Address convertImpl(final Object input) {
- if (input instanceof Address) {
- return (Address) input;
- } else if (input instanceof Bytes) {
+ if (input instanceof Address address) {
+ return address;
+ } else if (input instanceof Bytes bytes) {
if (((Bytes) input).size() <= 20) {
- return Address.wrap((Bytes) input);
+ return Address.wrap(bytes);
} else {
return null;
}
- } else if (input instanceof StringValue) {
- return convertImpl(((StringValue) input).getValue());
- } else if (input instanceof String) {
+ } else if (input instanceof StringValue stringValue) {
+ return convertImpl(stringValue.getValue());
+ } else if (input instanceof String string) {
try {
- return Address.fromHexStringStrict((String) input);
+ return Address.fromHexStringStrict(string);
} catch (IllegalArgumentException iae) {
return null;
}
@@ -57,7 +62,9 @@ public class Scalars {
}
@Override
- public String serialize(final Object input) throws CoercingSerializeException {
+ public String serialize(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingSerializeException {
Address result = convertImpl(input);
if (result != null) {
return result.toHexString();
@@ -67,7 +74,9 @@ public class Scalars {
}
@Override
- public Address parseValue(final Object input) throws CoercingParseValueException {
+ public Address parseValue(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingParseValueException {
Address result = convertImpl(input);
if (result != null) {
return result;
@@ -78,7 +87,12 @@ public class Scalars {
}
@Override
- public Address parseLiteral(final Object input) throws CoercingParseLiteralException {
+ public Address parseLiteral(
+ final Value> input,
+ final CoercedVariables variables,
+ final GraphQLContext graphQLContext,
+ final Locale locale)
+ throws CoercingParseLiteralException {
Address result = convertImpl(input);
if (result != null) {
return result;
@@ -92,25 +106,27 @@ public class Scalars {
new Coercing() {
String convertImpl(final Object input) {
- if (input instanceof String) {
+ if (input instanceof String string) {
try {
- return Bytes.fromHexStringLenient((String) input).toShortHexString();
+ return Bytes.fromHexStringLenient(string).toShortHexString();
} catch (IllegalArgumentException iae) {
return null;
}
- } else if (input instanceof Bytes) {
- return ((Bytes) input).toShortHexString();
- } else if (input instanceof StringValue) {
- return convertImpl(((StringValue) input).getValue());
- } else if (input instanceof IntValue) {
- return UInt256.valueOf(((IntValue) input).getValue()).toShortHexString();
+ } else if (input instanceof Bytes bytes) {
+ return bytes.toShortHexString();
+ } else if (input instanceof StringValue stringValue) {
+ return convertImpl(stringValue.getValue());
+ } else if (input instanceof IntValue intValue) {
+ return UInt256.valueOf(intValue.getValue()).toShortHexString();
} else {
return null;
}
}
@Override
- public String serialize(final Object input) throws CoercingSerializeException {
+ public String serialize(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingSerializeException {
var result = convertImpl(input);
if (result != null) {
return result;
@@ -120,7 +136,9 @@ public class Scalars {
}
@Override
- public String parseValue(final Object input) throws CoercingParseValueException {
+ public String parseValue(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingParseValueException {
var result = convertImpl(input);
if (result != null) {
return result;
@@ -131,7 +149,12 @@ public class Scalars {
}
@Override
- public String parseLiteral(final Object input) throws CoercingParseLiteralException {
+ public String parseLiteral(
+ final Value> input,
+ final CoercedVariables variables,
+ final GraphQLContext graphQLContext,
+ final Locale locale)
+ throws CoercingParseLiteralException {
var result = convertImpl(input);
if (result != null) {
return result;
@@ -145,12 +168,12 @@ public class Scalars {
new Coercing() {
Bytes convertImpl(final Object input) {
- if (input instanceof Bytes) {
- return (Bytes) input;
- } else if (input instanceof StringValue) {
- return convertImpl(((StringValue) input).getValue());
- } else if (input instanceof String) {
- if (!Quantity.isValid((String) input)) {
+ if (input instanceof Bytes bytes) {
+ return bytes;
+ } else if (input instanceof StringValue stringValue) {
+ return convertImpl(stringValue.getValue());
+ } else if (input instanceof String string) {
+ if (!Quantity.isValid(string)) {
throw new CoercingParseLiteralException(
"Bytes value '" + input + "' is not prefixed with 0x");
}
@@ -165,7 +188,9 @@ public class Scalars {
}
@Override
- public String serialize(final Object input) throws CoercingSerializeException {
+ public String serialize(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingSerializeException {
var result = convertImpl(input);
if (result != null) {
return result.toHexString();
@@ -175,7 +200,9 @@ public class Scalars {
}
@Override
- public Bytes parseValue(final Object input) throws CoercingParseValueException {
+ public Bytes parseValue(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingParseValueException {
var result = convertImpl(input);
if (result != null) {
return result;
@@ -186,7 +213,12 @@ public class Scalars {
}
@Override
- public Bytes parseLiteral(final Object input) throws CoercingParseLiteralException {
+ public Bytes parseLiteral(
+ final Value> input,
+ final CoercedVariables variables,
+ final GraphQLContext graphQLContext,
+ final Locale locale)
+ throws CoercingParseLiteralException {
var result = convertImpl(input);
if (result != null) {
return result;
@@ -200,18 +232,18 @@ public class Scalars {
new Coercing() {
Bytes32 convertImpl(final Object input) {
- if (input instanceof Bytes32) {
- return (Bytes32) input;
- } else if (input instanceof Bytes) {
- if (((Bytes) input).size() <= 32) {
+ if (input instanceof Bytes32 bytes32) {
+ return bytes32;
+ } else if (input instanceof Bytes bytes) {
+ if (bytes.size() <= 32) {
return Bytes32.leftPad((Bytes) input);
} else {
return null;
}
- } else if (input instanceof StringValue) {
- return convertImpl((((StringValue) input).getValue()));
- } else if (input instanceof String) {
- if (!Quantity.isValid((String) input)) {
+ } else if (input instanceof StringValue stringValue) {
+ return convertImpl(stringValue.getValue());
+ } else if (input instanceof String string) {
+ if (!Quantity.isValid(string)) {
throw new CoercingParseLiteralException(
"Bytes32 value '" + input + "' is not prefixed with 0x");
} else {
@@ -227,7 +259,9 @@ public class Scalars {
}
@Override
- public String serialize(final Object input) throws CoercingSerializeException {
+ public String serialize(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingSerializeException {
var result = convertImpl(input);
if (result == null) {
throw new CoercingSerializeException("Unable to serialize " + input + " as an Bytes32");
@@ -237,7 +271,9 @@ public class Scalars {
}
@Override
- public Bytes32 parseValue(final Object input) throws CoercingParseValueException {
+ public Bytes32 parseValue(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingParseValueException {
var result = convertImpl(input);
if (result == null) {
throw new CoercingParseValueException(
@@ -248,7 +284,12 @@ public class Scalars {
}
@Override
- public Bytes32 parseLiteral(final Object input) throws CoercingParseLiteralException {
+ public Bytes32 parseLiteral(
+ final Value> input,
+ final CoercedVariables variables,
+ final GraphQLContext graphQLContext,
+ final Locale locale)
+ throws CoercingParseLiteralException {
var result = convertImpl(input);
if (result == null) {
throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'");
@@ -259,13 +300,15 @@ public class Scalars {
};
private static final Coercing LONG_COERCING =
- new Coercing() {
+ new Coercing<>() {
@Override
- public Number serialize(final Object input) throws CoercingSerializeException {
- if (input instanceof Number) {
- return (Number) input;
- } else if (input instanceof String) {
- final String value = ((String) input).toLowerCase();
+ public Number serialize(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingSerializeException {
+ if (input instanceof Number number) {
+ return number;
+ } else if (input instanceof String string) {
+ final String value = string.toLowerCase();
if (value.startsWith("0x")) {
return Bytes.fromHexStringLenient(value).toLong();
} else {
@@ -276,11 +319,13 @@ public class Scalars {
}
@Override
- public Number parseValue(final Object input) throws CoercingParseValueException {
- if (input instanceof Number) {
- return (Number) input;
- } else if (input instanceof String) {
- final String value = ((String) input).toLowerCase();
+ public Number parseValue(
+ final Object input, final GraphQLContext graphQLContext, final Locale locale)
+ throws CoercingParseValueException {
+ if (input instanceof Number number) {
+ return number;
+ } else if (input instanceof String string) {
+ final String value = string.toLowerCase();
if (value.startsWith("0x")) {
return Bytes.fromHexStringLenient(value).toLong();
} else {
@@ -292,12 +337,17 @@ public class Scalars {
}
@Override
- public Number parseLiteral(final Object input) throws CoercingParseLiteralException {
+ public Number parseLiteral(
+ final Value> input,
+ final CoercedVariables variables,
+ final GraphQLContext graphQLContext,
+ final Locale locale)
+ throws CoercingParseLiteralException {
try {
- if (input instanceof IntValue) {
- return ((IntValue) input).getValue().longValue();
- } else if (input instanceof StringValue) {
- final String value = ((StringValue) input).getValue().toLowerCase();
+ if (input instanceof IntValue intValue) {
+ return intValue.getValue().longValue();
+ } else if (input instanceof StringValue stringValue) {
+ final String value = stringValue.getValue().toLowerCase();
if (value.startsWith("0x")) {
return Bytes.fromHexStringLenient(value).toLong();
} else {
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java
index f49d709b2..c8acb708a 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java
@@ -41,24 +41,26 @@ public class AccountAdapter extends AdapterBase {
this.address = address;
}
- public Optional getAddress() {
- return Optional.of(address);
+ public Address getAddress() {
+ return address;
}
- public Optional getBalance() {
- return account.map(AccountState::getBalance).or(() -> Optional.of(Wei.ZERO));
+ public Wei getBalance() {
+ return account.map(AccountState::getBalance).orElse(Wei.ZERO);
}
- public Optional getTransactionCount() {
- return account.map(AccountState::getNonce).or(() -> Optional.of(0L));
+ public Long getTransactionCount() {
+ return account.map(AccountState::getNonce).orElse(0L);
}
- public Optional getCode() {
- return account.map(AccountState::getCode);
+ public Bytes getCode() {
+ return account.map(AccountState::getCode).orElse(Bytes.EMPTY);
}
- public Optional getStorage(final DataFetchingEnvironment environment) {
+ public Bytes32 getStorage(final DataFetchingEnvironment environment) {
final Bytes32 slot = environment.getArgument("slot");
- return account.map(account -> account.getStorageValue(UInt256.fromBytes(slot)));
+ return account
+ .map(a -> (Bytes32) a.getStorageValue(UInt256.fromBytes(slot)))
+ .orElse(Bytes32.ZERO);
}
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java
index 9a22dedd5..2b8251ce8 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java
@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
+import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@@ -39,7 +40,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
+import java.util.function.Function;
import com.google.common.primitives.Longs;
import graphql.schema.DataFetchingEnvironment;
@@ -64,29 +65,29 @@ public class BlockAdapterBase extends AdapterBase {
return block.map(NormalBlockAdapter::new);
}
- public Optional getHash() {
- return Optional.of(header.getHash());
+ public Bytes32 getHash() {
+ return header.getHash();
}
- public Optional getNonce() {
+ public Bytes getNonce() {
final long nonce = header.getNonce();
final byte[] bytes = Longs.toByteArray(nonce);
- return Optional.of(Bytes.wrap(bytes));
+ return Bytes.wrap(bytes);
}
- public Optional getTransactionsRoot() {
- return Optional.of(header.getTransactionsRoot());
+ public Bytes32 getTransactionsRoot() {
+ return header.getTransactionsRoot();
}
- public Optional getStateRoot() {
- return Optional.of(header.getStateRoot());
+ public Bytes32 getStateRoot() {
+ return header.getStateRoot();
}
- public Optional getReceiptsRoot() {
- return Optional.of(header.getReceiptsRoot());
+ public Bytes32 getReceiptsRoot() {
+ return header.getReceiptsRoot();
}
- public Optional getMiner(final DataFetchingEnvironment environment) {
+ public AdapterBase getMiner(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
long blockNumber = header.getNumber();
@@ -98,60 +99,61 @@ public class BlockAdapterBase extends AdapterBase {
return query
.getAndMapWorldState(blockNumber, ws -> Optional.ofNullable(ws.get(header.getCoinbase())))
.map(account -> (AdapterBase) new AccountAdapter(account))
- .or(() -> Optional.of(new EmptyAccountAdapter(header.getCoinbase())));
+ .orElseGet(() -> new EmptyAccountAdapter(header.getCoinbase()));
}
- public Optional getExtraData() {
- return Optional.of(header.getExtraData());
+ public Bytes getExtraData() {
+ return header.getExtraData();
}
public Optional getBaseFeePerGas() {
return header.getBaseFee();
}
- public Optional getGasLimit() {
- return Optional.of(header.getGasLimit());
+ public Long getGasLimit() {
+ return header.getGasLimit();
}
- public Optional getGasUsed() {
- return Optional.of(header.getGasUsed());
+ public Long getGasUsed() {
+ return header.getGasUsed();
}
- public Optional getTimestamp() {
- return Optional.of(header.getTimestamp());
+ public Long getTimestamp() {
+ return header.getTimestamp();
}
- public Optional getLogsBloom() {
- return Optional.of(header.getLogsBloom());
+ public Bytes getLogsBloom() {
+ return header.getLogsBloom();
}
- public Optional getMixHash() {
- return Optional.of(header.getMixHash());
+ public Bytes32 getMixHash() {
+ return header.getMixHash();
}
- public Optional getDifficulty() {
- return Optional.of(header.getDifficulty());
+ public Difficulty getDifficulty() {
+ return header.getDifficulty();
}
- public Optional getOmmerHash() {
- return Optional.of(header.getOmmersHash());
+ public Bytes32 getOmmerHash() {
+ return header.getOmmersHash();
}
- public Optional getNumber() {
- final long bn = header.getNumber();
- return Optional.of(bn);
+ public Long getNumber() {
+ return header.getNumber();
}
- public Optional getAccount(final DataFetchingEnvironment environment) {
+ public AccountAdapter getAccount(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
final long bn = header.getNumber();
- return query.getAndMapWorldState(
- bn,
- ws -> {
- final Address address = environment.getArgument("address");
- return Optional.of(new AccountAdapter(ws.get(address)));
- });
+ return query
+ .getAndMapWorldState(
+ bn,
+ ws -> {
+ final Address address = environment.getArgument("address");
+ return Optional.of(new AccountAdapter(ws.get(address)));
+ })
+ .get();
}
public List getLogs(final DataFetchingEnvironment environment) {
@@ -168,7 +170,7 @@ public class BlockAdapterBase extends AdapterBase {
if (topic.isEmpty()) {
transformedTopics.add(Collections.singletonList(null));
} else {
- transformedTopics.add(topic.stream().map(LogTopic::of).collect(Collectors.toList()));
+ transformedTopics.add(topic.stream().map(LogTopic::of).toList());
}
}
final LogsQuery query =
@@ -185,9 +187,9 @@ public class BlockAdapterBase extends AdapterBase {
return results;
}
- public Optional getEstimateGas(final DataFetchingEnvironment environment) {
+ public Long getEstimateGas(final DataFetchingEnvironment environment) {
final Optional result = executeCall(environment);
- return result.map(CallResult::getGasUsed);
+ return result.map(CallResult::getGasUsed).orElse(0L);
}
public Optional getCall(final DataFetchingEnvironment environment) {
@@ -240,12 +242,14 @@ public class BlockAdapterBase extends AdapterBase {
data,
Optional.empty());
+ ImmutableTransactionValidationParams.Builder transactionValidationParams =
+ ImmutableTransactionValidationParams.builder()
+ .from(TransactionValidationParams.transactionSimulator());
+ transactionValidationParams.isAllowExceedingBalance(true);
+
final Optional opt =
transactionSimulator.process(
- param,
- TransactionValidationParams.transactionSimulator(),
- OperationTracer.NO_TRACING,
- bn);
+ param, transactionValidationParams.build(), OperationTracer.NO_TRACING, bn);
if (opt.isPresent()) {
final TransactionSimulatorResult result = opt.get();
long status = 0;
@@ -259,13 +263,13 @@ public class BlockAdapterBase extends AdapterBase {
return Optional.empty();
}
- Optional getRawHeader() {
+ Bytes getRawHeader() {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
header.writeTo(rlpOutput);
- return Optional.of(rlpOutput.encoded());
+ return rlpOutput.encoded();
}
- Optional getRaw(final DataFetchingEnvironment environment) {
+ Bytes getRaw(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
return query
.getBlockchain()
@@ -275,6 +279,23 @@ public class BlockAdapterBase extends AdapterBase {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
blockBody.writeWrappedBodyTo(rlpOutput);
return rlpOutput.encoded();
- });
+ })
+ .orElse(Bytes.EMPTY);
+ }
+
+ Optional getWithdrawalsRoot() {
+ return header.getWithdrawalsRoot().map(Function.identity());
+ }
+
+ Optional> getWithdrawals(final DataFetchingEnvironment environment) {
+ final BlockchainQueries query = getBlockchainQueries(environment);
+ return query
+ .getBlockchain()
+ .getBlockBody(header.getBlockHash())
+ .flatMap(
+ blockBody ->
+ blockBody
+ .getWithdrawals()
+ .map(wl -> wl.stream().map(WithdrawalAdapter::new).toList()));
}
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java
index ecb16a82a..7fc6d7695 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java
@@ -17,8 +17,6 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
-import java.util.Optional;
-
import graphql.schema.DataFetchingEnvironment;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
@@ -32,27 +30,27 @@ public class EmptyAccountAdapter extends AccountAdapter {
}
@Override
- public Optional getAddress() {
- return Optional.of(address);
+ public Address getAddress() {
+ return address;
}
@Override
- public Optional getBalance() {
- return Optional.of(Wei.ZERO);
+ public Wei getBalance() {
+ return Wei.ZERO;
}
@Override
- public Optional getTransactionCount() {
- return Optional.of(0L);
+ public Long getTransactionCount() {
+ return 0L;
}
@Override
- public Optional getCode() {
- return Optional.of(Bytes.EMPTY);
+ public Bytes getCode() {
+ return Bytes.EMPTY;
}
@Override
- public Optional getStorage(final DataFetchingEnvironment environment) {
- return Optional.of(Bytes32.ZERO);
+ public Bytes32 getStorage(final DataFetchingEnvironment environment) {
+ return Bytes32.ZERO;
}
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java
index 20c1e31fe..10357de0c 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java
@@ -35,8 +35,8 @@ public class LogAdapter extends AdapterBase {
this.logWithMetadata = logWithMetadata;
}
- public Optional getIndex() {
- return Optional.of(logWithMetadata.getLogIndex());
+ public Integer getIndex() {
+ return logWithMetadata.getLogIndex();
}
public List getTopics() {
@@ -44,18 +44,18 @@ public class LogAdapter extends AdapterBase {
return new ArrayList<>(topics);
}
- public Optional getData() {
- return Optional.of(logWithMetadata.getData());
+ public Bytes getData() {
+ return logWithMetadata.getData();
}
- public Optional getTransaction(final DataFetchingEnvironment environment) {
+ public TransactionAdapter getTransaction(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
final Hash hash = logWithMetadata.getTransactionHash();
final Optional tran = query.transactionByHash(hash);
- return tran.map(TransactionAdapter::new);
+ return tran.map(TransactionAdapter::new).orElseThrow();
}
- public Optional getAccount(final DataFetchingEnvironment environment) {
+ public AccountAdapter getAccount(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
long blockNumber = logWithMetadata.getBlockNumber();
final Long bn = environment.getArgument("block");
@@ -63,7 +63,9 @@ public class LogAdapter extends AdapterBase {
blockNumber = bn;
}
- return query.getAndMapWorldState(
- blockNumber, ws -> Optional.of(new AccountAdapter(ws.get(logWithMetadata.getLogger()))));
+ return query
+ .getAndMapWorldState(
+ blockNumber, ws -> Optional.of(new AccountAdapter(ws.get(logWithMetadata.getLogger()))))
+ .get();
}
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java
index 0245b404c..f54b3f0da 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java
@@ -42,8 +42,8 @@ public class NormalBlockAdapter extends BlockAdapterBase {
return Optional.of(blockWithMetaData.getTransactions().size());
}
- public Optional getTotalDifficulty() {
- return Optional.of(blockWithMetaData.getTotalDifficulty());
+ public Difficulty getTotalDifficulty() {
+ return blockWithMetaData.getTotalDifficulty();
}
public Optional getOmmerCount() {
@@ -65,7 +65,7 @@ public class NormalBlockAdapter extends BlockAdapterBase {
public Optional getOmmerAt(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
- final int index = environment.getArgument("index");
+ final int index = ((Number) environment.getArgument("index")).intValue();
final List ommers = blockWithMetaData.getOmmers();
if (ommers.size() > index) {
final Hash hash = blockWithMetaData.getHeader().getHash();
@@ -85,7 +85,7 @@ public class NormalBlockAdapter extends BlockAdapterBase {
}
public Optional getTransactionAt(final DataFetchingEnvironment environment) {
- final int index = environment.getArgument("index");
+ final int index = ((Number) environment.getArgument("index")).intValue();
final List trans = blockWithMetaData.getTransactions();
if (trans.size() > index) {
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java
index f3462f420..fbdfb54ae 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java
@@ -21,15 +21,17 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
+import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
+import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
+import org.hyperledger.besu.evm.tracing.OperationTracer;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
import graphql.schema.DataFetchingEnvironment;
import org.apache.tuweni.bytes.Bytes;
@@ -53,13 +55,12 @@ public class PendingStateAdapter extends AdapterBase {
.map(PendingTransaction::getTransaction)
.map(TransactionWithMetadata::new)
.map(TransactionAdapter::new)
- .collect(Collectors.toList());
+ .toList();
}
// until the miner can expose the current "proposed block" we have no
// speculative environment, so estimate against latest.
- public Optional getAccount(
- final DataFetchingEnvironment dataFetchingEnvironment) {
+ public AccountAdapter getAccount(final DataFetchingEnvironment dataFetchingEnvironment) {
final BlockchainQueries blockchainQuery =
dataFetchingEnvironment.getGraphQlContext().get(GraphQLContextType.BLOCKCHAIN_QUERIES);
final Address addr = dataFetchingEnvironment.getArgument("address");
@@ -67,7 +68,8 @@ public class PendingStateAdapter extends AdapterBase {
final long latestBlockNumber = blockchainQuery.latestBlock().get().getHeader().getNumber();
return blockchainQuery
.getAndMapWorldState(latestBlockNumber, ws -> Optional.ofNullable(ws.get(addr)))
- .map(AccountAdapter::new);
+ .map(AccountAdapter::new)
+ .orElseGet(() -> new AccountAdapter(null));
}
// until the miner can expose the current "proposed block" we have no
@@ -111,7 +113,18 @@ public class PendingStateAdapter extends AdapterBase {
final CallParameter param =
new CallParameter(from, to, gasParam, gasPriceParam, valueParam, data);
- final Optional opt = transactionSimulator.processAtHead(param);
+ ImmutableTransactionValidationParams.Builder transactionValidationParams =
+ ImmutableTransactionValidationParams.builder()
+ .from(TransactionValidationParams.transactionSimulator());
+ transactionValidationParams.isAllowExceedingBalance(true);
+
+ final Optional opt =
+ transactionSimulator.process(
+ param,
+ transactionValidationParams.build(),
+ OperationTracer.NO_TRACING,
+ query.getBlockchain().getChainHeadHeader());
+
if (opt.isPresent()) {
final TransactionSimulatorResult result = opt.get();
long status = 0;
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java
index ddbad14bf..0a8dcbbf9 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java
@@ -16,8 +16,6 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
import org.hyperledger.besu.plugin.data.SyncStatus;
-import java.util.Optional;
-
@SuppressWarnings("unused") // reflected by GraphQL
public class SyncStateAdapter {
private final SyncStatus syncStatus;
@@ -26,15 +24,15 @@ public class SyncStateAdapter {
this.syncStatus = syncStatus;
}
- public Optional getStartingBlock() {
- return Optional.of(syncStatus.getStartingBlock());
+ public Long getStartingBlock() {
+ return syncStatus.getStartingBlock();
}
- public Optional getCurrentBlock() {
- return Optional.of(syncStatus.getCurrentBlock());
+ public Long getCurrentBlock() {
+ return syncStatus.getCurrentBlock();
}
- public Optional getHighestBlock() {
- return Optional.of(syncStatus.getHighestBlock());
+ public Long getHighestBlock() {
+ return syncStatus.getHighestBlock();
}
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java
index f77c5f724..49c1da5da 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java
@@ -28,7 +28,6 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import graphql.schema.DataFetchingEnvironment;
@@ -58,35 +57,37 @@ public class TransactionAdapter extends AdapterBase {
return transactionReceiptWithMetadata;
}
- public Optional getHash() {
- return Optional.of(transactionWithMetadata.getTransaction().getHash());
+ public Hash getHash() {
+ return transactionWithMetadata.getTransaction().getHash();
}
public Optional getType() {
return Optional.of(transactionWithMetadata.getTransaction().getType().ordinal());
}
- public Optional getNonce() {
- final long nonce = transactionWithMetadata.getTransaction().getNonce();
- return Optional.of(nonce);
+ public Long getNonce() {
+ return transactionWithMetadata.getTransaction().getNonce();
}
public Optional getIndex() {
return transactionWithMetadata.getTransactionIndex();
}
- public Optional getFrom(final DataFetchingEnvironment environment) {
+ public AccountAdapter getFrom(final DataFetchingEnvironment environment) {
final BlockchainQueries query = getBlockchainQueries(environment);
Long blockNumber = environment.getArgument("block");
if (blockNumber == null) {
blockNumber = transactionWithMetadata.getBlockNumber().orElseGet(query::headBlockNumber);
}
- return query.getAndMapWorldState(
- blockNumber,
- mutableWorldState ->
- Optional.of(
- new AccountAdapter(
- mutableWorldState.get(transactionWithMetadata.getTransaction().getSender()))));
+ return query
+ .getAndMapWorldState(
+ blockNumber,
+ mutableWorldState ->
+ Optional.of(
+ new AccountAdapter(
+ mutableWorldState.get(
+ transactionWithMetadata.getTransaction().getSender()))))
+ .get();
}
public Optional getTo(final DataFetchingEnvironment environment) {
@@ -105,12 +106,12 @@ public class TransactionAdapter extends AdapterBase {
.map(address -> new AccountAdapter(address, ws.get(address))));
}
- public Optional getValue() {
- return Optional.of(transactionWithMetadata.getTransaction().getValue());
+ public Wei getValue() {
+ return transactionWithMetadata.getTransaction().getValue();
}
- public Optional getGasPrice() {
- return transactionWithMetadata.getTransaction().getGasPrice();
+ public Wei getGasPrice() {
+ return transactionWithMetadata.getTransaction().getGasPrice().orElse(Wei.ZERO);
}
public Optional getMaxPriorityFeePerGas() {
@@ -126,12 +127,17 @@ public class TransactionAdapter extends AdapterBase {
.map(rwm -> rwm.getTransaction().getEffectiveGasPrice(rwm.getBaseFee()));
}
- public Optional getGas() {
- return Optional.of(transactionWithMetadata.getTransaction().getGasLimit());
+ public Optional getEffectiveTip(final DataFetchingEnvironment environment) {
+ return getReceipt(environment)
+ .map(rwm -> rwm.getTransaction().getEffectivePriorityFeePerGas(rwm.getBaseFee()));
}
- public Optional getInputData() {
- return Optional.of(transactionWithMetadata.getTransaction().getPayload());
+ public Long getGas() {
+ return transactionWithMetadata.getTransaction().getGasLimit();
+ }
+
+ public Bytes getInputData() {
+ return transactionWithMetadata.getTransaction().getPayload();
}
public Optional getBlock(final DataFetchingEnvironment environment) {
@@ -212,7 +218,7 @@ public class TransactionAdapter extends AdapterBase {
return transactionWithMetadata
.getTransaction()
.getAccessList()
- .map(l -> l.stream().map(AccessListEntryAdapter::new).collect(Collectors.toList()))
+ .map(l -> l.stream().map(AccessListEntryAdapter::new).toList())
.orElse(List.of());
}
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java
index c0e273682..8d9e947ee 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java
@@ -33,8 +33,8 @@ class UncleBlockAdapter extends BlockAdapterBase {
return Optional.of(0);
}
- public Optional getTotalDifficulty() {
- return Optional.of(UInt256.ZERO);
+ public UInt256 getTotalDifficulty() {
+ return UInt256.ZERO;
}
public Optional getOmmerCount() {
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java
new file mode 100644
index 000000000..86782b6af
--- /dev/null
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright contributors to Hyperledger 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.ethereum.api.graphql.internal.pojoadapter;
+
+import org.hyperledger.besu.datatypes.Address;
+import org.hyperledger.besu.plugin.data.Withdrawal;
+
+public class WithdrawalAdapter {
+
+ Withdrawal withdrawal;
+
+ public WithdrawalAdapter(final Withdrawal withdrawal) {
+ this.withdrawal = withdrawal;
+ }
+
+ public Long getIndex() {
+ return withdrawal.getIndex().toLong();
+ }
+
+ public Long getValidator() {
+ return withdrawal.getValidatorIndex().toLong();
+ }
+
+ public Address getAddress() {
+ return withdrawal.getAddress();
+ }
+
+ public Long getAmount() {
+ return withdrawal.getAmount().getAsBigInteger().longValue();
+ }
+}
diff --git a/ethereum/api/src/main/resources/schema.graphqls b/ethereum/api/src/main/resources/schema.graphqls
index 01e20f95d..183bce31e 100644
--- a/ethereum/api/src/main/resources/schema.graphqls
+++ b/ethereum/api/src/main/resources/schema.graphqls
@@ -69,7 +69,7 @@ type Block {
TransactionCount is the number of transactions in this block. if
transactions are not available for this block, this field will be null.
"""
- transactionCount: Int
+ transactionCount: Long
"""
StateRoot is the keccak256 hash of the state trie after this block was processed.
@@ -132,7 +132,7 @@ type Block {
OmmerCount is the number of ommers (AKA uncles) associated with this
block. If ommers are unavailable, this field will be null.
"""
- ommerCount: Int
+ ommerCount: Long
"""
Ommers is a list of ommer (AKA uncle) blocks associated with this block.
@@ -146,7 +146,7 @@ type Block {
OmmerAt returns the ommer (AKA uncle) at the specified index. If ommers
are unavailable, or the index is out of bounds, this field will be null.
"""
- ommerAt(index: Int!): Block
+ ommerAt(index: Long!): Block
"""
OmmerHash is the keccak256 hash of all the ommers (AKA uncles)
@@ -165,13 +165,13 @@ type Block {
transactions are unavailable for this block, or if the index is out of
bounds, this field will be null.
"""
- transactionAt(index: Int!): Transaction
+ transactionAt(index: Long!): Transaction
"""Logs returns a filtered set of logs from this block."""
logs(filter: BlockFilterCriteria!): [Log!]!
"""Account fetches an Ethereum account at the current block's state."""
- account(address: Address!): Account
+ account(address: Address!): Account!
"""Call executes a local call operation at the current block's state."""
call(data: CallData!): CallResult
@@ -187,6 +187,18 @@ type Block {
"""Raw is the RLP encoding of the block."""
raw: Bytes!
+
+ """
+ WithdrawalsRoot is the keccak256 hash of the root of the trie of withdrawals in this block.
+ If withdrawals are unavailable for this block, this field will be null.
+ """
+ withdrawalsRoot: Bytes32
+
+ """
+ Withdrawals is a list of withdrawals associated with this block. If
+ withdrawals are unavailable for this block, this field will be null.
+ """
+ withdrawals: [Withdrawal!]
}
"""
@@ -205,7 +217,7 @@ input BlockFilterCriteria {
of topics. Topics matches a prefix of that list. An empty element array matches any
topic. Non-empty elements represent an alternative that matches any of the
contained topics.
-
+
Examples:
- [] or nil matches any topic list
- [[A]] matches topic A in first position
@@ -296,7 +308,7 @@ input FilterCriteria {
of topics. Topics matches a prefix of that list. An empty element array matches any
topic. Non-empty elements represent an alternative that matches any of the
contained topics.
-
+
Examples:
- [] or nil matches any topic list
- [[A]] matches topic A in first position
@@ -310,7 +322,7 @@ input FilterCriteria {
"""Log is an Ethereum event log."""
type Log {
"""Index is the index of this log in the block."""
- index: Int!
+ index: Long!
"""
Account is the account which generated this log - this will always
@@ -328,7 +340,11 @@ type Log {
transaction: Transaction!
}
-"""Long is a 64 bit unsigned integer."""
+"""
+Long is a 64 bit unsigned integer. Input is accepted as either a JSON number or as a string.
+Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all
+0x-prefixed hexadecimal.
+"""
scalar Long
type Mutation {
@@ -339,13 +355,13 @@ type Mutation {
"""Pending represents the current pending state."""
type Pending {
"""TransactionCount is the number of transactions in the pending state."""
- transactionCount: Int!
+ transactionCount: Long!
"""Transactions is a list of transactions in the current pending state."""
transactions: [Transaction!]
"""Account fetches an Ethereum account for the pending state."""
- account(address: Address!): Account
+ account(address: Address!): Account!
"""Call executes a local call operation for the pending state."""
call(data: CallData!): CallResult
@@ -426,7 +442,7 @@ type Transaction {
Index is the index of this transaction in the parent block. This will
be null if the transaction has not yet been mined.
"""
- index: Int
+ index: Long
"""
From is the account that sent this transaction - this will always be
@@ -521,7 +537,7 @@ type Transaction {
v: BigInt!
"""Envelope transaction support"""
- type: Int
+ type: Long
accessList: [AccessTuple!]
"""
@@ -536,10 +552,21 @@ type Transaction {
this is equivalent to TxType || ReceiptEncoding.
"""
rawReceipt: Bytes!
+}
- """ IsPrivate is an indicator of a GoQuorum private transaction"""
- isPrivate: Boolean
- """ PrivateInputData is the actual payload of a GoQuorum private transaction"""
- privateInputData: Bytes
+"""EIP-4895"""
+type Withdrawal {
+ """
+ Index is a monotonically increasing identifier issued by consensus layer.
+ """
+ index: Long!
+ """Validator is index of the validator associated with withdrawal."""
+ validator: Long!
+
+ """Address recipient of the withdrawn amount."""
+ address: Address!
+
+ """Amount is the withdrawal value in Gwei."""
+ amount: Long!
}
\ No newline at end of file
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
index cb8c253ad..7f41af9ab 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
@@ -14,21 +14,14 @@
*/
package org.hyperledger.besu.ethereum.api.graphql;
-import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
-
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
-import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
-import org.hyperledger.besu.ethereum.core.Block;
-import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
-import org.hyperledger.besu.ethereum.core.BlockImporter;
+import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.core.DefaultSyncStatus;
-import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
-import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.EthProtocol;
@@ -36,31 +29,20 @@ import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
-import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
-import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
-import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
-import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
-import org.hyperledger.besu.ethereum.util.RawBlockIterator;
-import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
+import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.plugin.data.SyncStatus;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.testutil.BlockTestUtil;
-import java.net.URL;
-import java.nio.file.Paths;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
import graphql.GraphQL;
import io.vertx.core.Vertx;
import okhttp3.MediaType;
@@ -76,13 +58,7 @@ import org.mockito.Mockito;
public abstract class AbstractEthGraphQLHttpServiceTest {
@ClassRule public static final TemporaryFolder folder = new TemporaryFolder();
- private static ProtocolSchedule PROTOCOL_SCHEDULE;
-
- static List BLOCKS;
-
- private static Block GENESIS_BLOCK;
-
- private static GenesisState GENESIS_CONFIG;
+ private static BlockchainSetupUtil blockchainSetupUtil;
private final Vertx vertx = Vertx.vertx();
@@ -95,29 +71,12 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
protected static final MediaType GRAPHQL = MediaType.parse("application/graphql; charset=utf-8");
- private ProtocolContext context;
-
@BeforeClass
- public static void setupConstants() throws Exception {
- PROTOCOL_SCHEDULE = ProtocolScheduleFixture.MAINNET;
-
- final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl();
-
- final URL genesisJsonUrl = BlockTestUtil.getTestGenesisUrl();
-
- final BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions();
- BLOCKS = new ArrayList<>();
- try (final RawBlockIterator iterator =
- new RawBlockIterator(Paths.get(blocksUrl.toURI()), blockHeaderFunctions)) {
- while (iterator.hasNext()) {
- BLOCKS.add(iterator.next());
- }
- }
-
- final String genesisJson = Resources.toString(genesisJsonUrl, Charsets.UTF_8);
-
- GENESIS_BLOCK = BLOCKS.get(0);
- GENESIS_CONFIG = GenesisState.fromJson(genesisJson, PROTOCOL_SCHEDULE);
+ public static void setupConstants() {
+ blockchainSetupUtil =
+ BlockchainSetupUtil.createForEthashChain(
+ BlockTestUtil.getHiveTestChainResources(), DataStorageFormat.FOREST);
+ blockchainSetupUtil.importAllBlocks();
}
@Before
@@ -151,12 +110,9 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
.gasPrice(Wei.ONE)
.build())));
- final WorldStateArchive stateArchive = createInMemoryWorldStateArchive();
- GENESIS_CONFIG.writeStateTo(stateArchive.getMutable());
-
- final MutableBlockchain blockchain =
- InMemoryKeyValueStorageProvider.createInMemoryBlockchain(GENESIS_BLOCK);
- context = new ProtocolContext(blockchain, stateArchive, null);
+ final MutableBlockchain blockchain = blockchainSetupUtil.getBlockchain();
+ ProtocolContext context =
+ new ProtocolContext(blockchain, blockchainSetupUtil.getWorldArchive(), null);
final BlockchainQueries blockchainQueries =
new BlockchainQueries(
context.getBlockchain(),
@@ -185,7 +141,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
GraphQLContextType.BLOCKCHAIN_QUERIES,
blockchainQueries,
GraphQLContextType.PROTOCOL_SCHEDULE,
- PROTOCOL_SCHEDULE,
+ blockchainSetupUtil.getProtocolSchedule(),
GraphQLContextType.TRANSACTION_POOL,
transactionPoolMock,
GraphQLContextType.MINING_COORDINATOR,
@@ -206,11 +162,4 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
service.stop().join();
vertx.close();
}
-
- void importBlock(final int n) {
- final Block block = BLOCKS.get(n);
- final ProtocolSpec protocolSpec = PROTOCOL_SCHEDULE.getByBlockHeader(block.getHeader());
- final BlockImporter blockImporter = protocolSpec.getBlockImporter();
- blockImporter.importBlock(context, block, HeaderValidationMode.FULL);
- }
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java
index fbce73301..b41bb1754 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java
@@ -20,6 +20,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
+import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.EmptyAccountAdapter;
import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.NormalBlockAdapter;
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
@@ -36,10 +37,10 @@ import org.mockito.junit.MockitoJUnitRunner;
public class BlockDataFetcherTest extends AbstractDataFetcherTest {
@Test
- public void bothNumberAndHashThrows() throws Exception {
+ public void bothNumberAndHashThrows() {
final Hash fakedHash = Hash.hash(Bytes.of(1));
- when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L);
- when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(fakedHash);
+ when(environment.getArgument("number")).thenReturn(1L);
+ when(environment.getArgument("hash")).thenReturn(fakedHash);
assertThatThrownBy(() -> fetcher.get(environment)).isInstanceOf(GraphQLException.class);
}
@@ -47,8 +48,8 @@ public class BlockDataFetcherTest extends AbstractDataFetcherTest {
@Test
public void onlyNumber() throws Exception {
- when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L);
- when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(null);
+ when(environment.getArgument("number")).thenReturn(1L);
+ when(environment.getArgument("hash")).thenReturn(null);
when(environment.getGraphQlContext()).thenReturn(graphQLContext);
when(graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES)).thenReturn(query);
@@ -64,8 +65,8 @@ public class BlockDataFetcherTest extends AbstractDataFetcherTest {
// as null. The compromise is to report zeros and empty on query from a block.
final Address testAddress = Address.fromHexString("0xdeadbeef");
- when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L);
- when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(null);
+ when(environment.getArgument("number")).thenReturn(1L);
+ when(environment.getArgument("hash")).thenReturn(null);
when(environment.getGraphQlContext()).thenReturn(graphQLContext);
when(graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES)).thenReturn(query);
@@ -75,10 +76,10 @@ public class BlockDataFetcherTest extends AbstractDataFetcherTest {
final Optional maybeBlock = fetcher.get(environment);
assertThat(maybeBlock).isPresent();
- assertThat(maybeBlock.get().getMiner(environment)).isPresent();
- assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment).get()).getBalance())
- .isPresent();
- assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment).get()).getAddress())
- .contains(testAddress);
+ assertThat(maybeBlock.get().getMiner(environment)).isNotNull();
+ assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment)).getBalance())
+ .isGreaterThanOrEqualTo(Wei.ZERO);
+ assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment)).getAddress())
+ .isEqualTo(testAddress);
}
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java
index a2280923d..7beef9c52 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java
@@ -118,6 +118,11 @@ public class EthGraphQLHttpBySpecTest extends AbstractEthGraphQLHttpServiceTest
specs.add("graphql_variable_bytes32");
specs.add("graphql_variable_long");
+ specs.add("block_withdrawals_pre_shanghai");
+ specs.add("block_withdrawals");
+ specs.add("eth_getTransaction_type2");
+ specs.add("eth_getBlock_shanghai");
+
return specs;
}
@@ -142,7 +147,6 @@ public class EthGraphQLHttpBySpecTest extends AbstractEthGraphQLHttpServiceTest
JSON);
final Request request = new Request.Builder().post(requestBody).url(baseUrl).build();
- importBlocks(1, BLOCKS.size());
try (final Response resp = client.newCall(request).execute()) {
final JsonObject expectedRespBody = spec.getJsonObject("response");
final String resultStr = resp.body().string();
@@ -154,10 +158,4 @@ public class EthGraphQLHttpBySpecTest extends AbstractEthGraphQLHttpServiceTest
Assertions.assertThat(resp.code()).isEqualTo(expectedStatusCode);
}
}
-
- private void importBlocks(final int from, final int to) {
- for (int i = from; i < to; ++i) {
- importBlock(i);
- }
- }
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java
index 87153b490..b6f978892 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java
@@ -20,6 +20,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
+import graphql.language.FloatValue;
import graphql.language.StringValue;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -40,43 +45,83 @@ public class AddressScalarTest {
@Test
public void parseValueTest() {
- final Address result = (Address) scalar.getCoercing().parseValue(addrStr);
+ final Address result =
+ (Address)
+ scalar
+ .getCoercing()
+ .parseValue(addrStr, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(addr);
}
@Test
public void parseValueErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.4f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseValue(3.4f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingParseValueException.class);
}
@Test
public void serializeTest() {
- final String result = (String) scalar.getCoercing().serialize(addr);
+ final String result =
+ (String)
+ scalar
+ .getCoercing()
+ .serialize(addr, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(addrStr);
}
@Test
public void serializeErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().serialize(3.4f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .serialize(3.4f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingSerializeException.class);
}
@Test
public void parseLiteralTest() {
- final Address result = (Address) scalar.getCoercing().parseLiteral(addrValue);
+ final Address result =
+ (Address)
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ addrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH);
assertThat(result).isEqualTo(addr);
}
@Test
public void parseLiteralErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.4f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ FloatValue.of(3.4f),
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
@Test
public void parseLiteralErrorTest2() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidAddrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ invalidAddrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java
index 06fcfa42c..d1c4751bd 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java
@@ -19,6 +19,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
+import graphql.language.FloatValue;
import graphql.language.StringValue;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -38,43 +43,69 @@ public class BigIntScalarTest {
@Test
public void parseValueTest() {
- final String result = (String) scalar.getCoercing().parseValue(value);
+ final String result =
+ (String)
+ scalar
+ .getCoercing()
+ .parseValue(value, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(str);
}
@Test
public void parseValueErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseValue(3.2, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingParseValueException.class);
}
@Test
public void serializeTest() {
- final String result = (String) scalar.getCoercing().serialize(value);
+ final String result =
+ (String)
+ scalar
+ .getCoercing()
+ .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(str);
}
@Test
public void serializeErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .serialize(3.2, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingSerializeException.class);
}
- @Test
- public void parseLiteralTest() {
- final String result = (String) scalar.getCoercing().parseLiteral(value);
- assertThat(result).isEqualTo(str);
- }
-
@Test
public void parseLiteralErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ FloatValue.of(3.2),
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
@Test
public void parseLiteralErrorTest2() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ invalidStrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java
index 47e516c3b..4583ecac3 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java
@@ -19,6 +19,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
+import graphql.language.FloatValue;
import graphql.language.StringValue;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -39,43 +44,80 @@ public class Bytes32ScalarTest {
@Test
public void pareValueTest() {
- final var result = scalar.getCoercing().parseValue(str);
+ final var result =
+ scalar.getCoercing().parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(value);
}
@Test
public void parseValueErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseValue(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingParseValueException.class);
}
@Test
public void serializeTest() {
- final String result = (String) scalar.getCoercing().serialize(value);
+ final String result =
+ (String)
+ scalar
+ .getCoercing()
+ .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(str);
}
@Test
public void serializeErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .serialize(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingSerializeException.class);
}
@Test
public void parseLiteralTest() {
- final Bytes32 result = (Bytes32) scalar.getCoercing().parseLiteral(strValue);
+ final Bytes32 result =
+ (Bytes32)
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ strValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH);
assertThat(result).isEqualTo(value);
}
@Test
public void parseLiteralErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ FloatValue.of(3.2f),
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
@Test
public void parseLiteralErrorTest2() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ invalidStrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java
index 39ca321c3..ae7204833 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java
@@ -19,6 +19,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
+import graphql.language.FloatValue;
import graphql.language.StringValue;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -39,43 +44,80 @@ public class BytesScalarTest {
@Test
public void parseValueTest() {
- final var result = scalar.getCoercing().parseValue(str);
+ final var result =
+ scalar.getCoercing().parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(value);
}
@Test
public void parseValueErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseValue(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingParseValueException.class);
}
@Test
public void serializeTest() {
- final String result = (String) scalar.getCoercing().serialize(value);
+ final String result =
+ (String)
+ scalar
+ .getCoercing()
+ .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH);
assertThat(result).isEqualTo(str);
}
@Test
public void serializeErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .serialize(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingSerializeException.class);
}
@Test
public void parseLiteralTest() {
- final Bytes result = (Bytes) scalar.getCoercing().parseLiteral(strValue);
+ final Bytes result =
+ (Bytes)
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ strValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH);
assertThat(result).isEqualTo(value);
}
@Test
public void parseLiteralErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2f))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ FloatValue.of(3.2f),
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
@Test
public void parseLiteralErrorTest2() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ invalidStrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java
index d693d6e2c..119ce81ce 100644
--- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java
+++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java
@@ -19,6 +19,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars;
+import java.util.Locale;
+
+import graphql.GraphQLContext;
+import graphql.execution.CoercedVariables;
import graphql.language.StringValue;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
@@ -38,51 +42,101 @@ public class LongScalarTest {
@Test
public void parseLongValueTest() {
- assertThat(scalar.getCoercing().parseValue(value)).isEqualTo(value);
+ assertThat(
+ scalar
+ .getCoercing()
+ .parseValue(value, GraphQLContext.newContext().build(), Locale.ENGLISH))
+ .isEqualTo(value);
}
@Test
public void parseStringValueTest() {
- assertThat(scalar.getCoercing().parseValue(str)).isEqualTo(value);
+ assertThat(
+ scalar
+ .getCoercing()
+ .parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH))
+ .isEqualTo(value);
}
@Test
public void parseValueErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseValue(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseValue(
+ invalidStrValue, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingParseValueException.class);
}
@Test
public void serializeLongTest() {
- assertThat(scalar.getCoercing().serialize(value)).isEqualTo(value);
+ assertThat(
+ scalar
+ .getCoercing()
+ .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH))
+ .isEqualTo(value);
}
@Test
public void serializeStringTest() {
- assertThat(scalar.getCoercing().serialize(str)).isEqualTo(value);
+ assertThat(
+ scalar
+ .getCoercing()
+ .serialize(str, GraphQLContext.newContext().build(), Locale.ENGLISH))
+ .isEqualTo(value);
}
@Test
public void serializeErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().serialize(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .serialize(
+ invalidStrValue, GraphQLContext.newContext().build(), Locale.ENGLISH))
.isInstanceOf(CoercingSerializeException.class);
}
@Test
public void parseLiteralTest() {
- final Long result = (Long) scalar.getCoercing().parseLiteral(strValue);
+ final Long result =
+ (Long)
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ strValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH);
assertThat(result).isEqualTo(value);
}
@Test
- public void parseLiteralErrorTest() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(str))
- .isInstanceOf(CoercingParseLiteralException.class);
+ public void parseLiteralStringTest() {
+ final Long result =
+ (Long)
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ strValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH);
+ assertThat(result).isEqualTo(value);
}
@Test
public void parseLiteralErrorTest2() {
- assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue))
+ assertThatThrownBy(
+ () ->
+ scalar
+ .getCoercing()
+ .parseLiteral(
+ invalidStrValue,
+ CoercedVariables.emptyVariables(),
+ GraphQLContext.newContext().build(),
+ Locale.ENGLISH))
.isInstanceOf(CoercingParseLiteralException.class);
}
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json
new file mode 100644
index 000000000..024f465a3
--- /dev/null
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json
@@ -0,0 +1,20 @@
+{
+ "request":
+ "{ block (number: 33) { number withdrawalsRoot withdrawals { index amount validator address } } }",
+
+ "response": {
+ "data" : {
+ "block" : {
+ "number" : 33,
+ "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3",
+ "withdrawals": [{
+ "index": 0,
+ "amount": 10000000000,
+ "validator": 10,
+ "address": "0x0000000000000000000000000000000000000dad"
+ }]
+ }
+ }
+ },
+ "statusCode": 200
+}
\ No newline at end of file
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json
new file mode 100644
index 000000000..dd50acb5f
--- /dev/null
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json
@@ -0,0 +1,15 @@
+{
+ "request":
+ "{ block (number: 32) { number withdrawalsRoot withdrawals { index amount } } }",
+
+ "response": {
+ "data" : {
+ "block" : {
+ "number" : 32,
+ "withdrawalsRoot": null,
+ "withdrawals": null
+ }
+ }
+ },
+ "statusCode": 200
+}
\ No newline at end of file
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json
index b3b736185..b061e7e65 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json
@@ -5,7 +5,7 @@
"response": {
"data" : {
"block" : {
- "number" : 32
+ "number" : 33
}
}
},
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json
index 7478c29a7..7c4a16df7 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json
@@ -4,7 +4,7 @@
"response":{
"data" : {
"block" : {
- "number" : 32,
+ "number" : 33,
"call" : {
"data" : "0x0000000000000000000000000000000000000000000000000000000000000001",
"status" : 1
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json
index 1bafc66fd..9904c248c 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json
@@ -4,7 +4,7 @@
"response":{
"data" : {
"block" : {
- "number" : 32,
+ "number" : 33,
"call" : {
"data" : "0x",
"status" : 1
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json
index 816ab74aa..fda239251 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json
@@ -4,7 +4,7 @@
"response":{
"data" : {
"block" : {
- "estimateGas" : 111953
+ "estimateGas" : 127129
}
}
},
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json
index 4c3135d72..776b5e0be 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json
@@ -3,7 +3,7 @@
"response":{
"data" : {
"block" : {
- "estimateGas" : 21204
+ "estimateGas" : 21048
}
}
},
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json
index 251bd7ebe..60a6408ae 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json
@@ -3,7 +3,7 @@
"response":{
"data" : {
"block" : {
- "estimateGas" : 21000
+ "estimateGas" : 53000
}
}
},
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json
index b5e1f90cc..90c599967 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json
@@ -3,7 +3,9 @@
"response": {
"data": {
"pending": {
- "account": null
+ "account": {
+ "balance": "0x0"
+ }
}
}
},
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json
index bd1260f84..cbc24c848 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json
@@ -1,9 +1,9 @@
{
- "request": "{ block(number:\"0x21\") { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }",
+ "request": "{ block(number:\"0x22\") { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }",
"response": {
"errors": [
{
- "message": "Exception while fetching data (/block) : Block number 33 was not found",
+ "message": "Exception while fetching data (/block) : Block number 34 was not found",
"locations": [
{
"line": 1,
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json
new file mode 100644
index 000000000..099460a8e
--- /dev/null
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json
@@ -0,0 +1,29 @@
+{
+ "request": "{block (number : 33) { baseFeePerGas difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty withdrawalsRoot withdrawals { address amount index validator } }} ",
+ "response":{
+ "data" : {
+ "block" : {
+ "baseFeePerGas": "0x3b9aca00",
+ "difficulty": "0x0",
+ "extraData": "0x",
+ "miner": {
+ "address": "0x0000000000000000000000000000000000000000"
+ },
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "stateRoot": "0x0d3c456bb68669bad05da3a1a766daab236c9df1da8f74edf5ebe9383f00084c",
+ "totalDifficulty": "0x427c00",
+ "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3",
+ "withdrawals": [
+ {
+ "address": "0x0000000000000000000000000000000000000dad",
+ "amount": 10000000000,
+ "index": 0,
+ "validator": 10
+ }
+ ]
+ }
+ }
+ },
+ "statusCode": 200
+}
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json
index ab563cf8a..990fbf747 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json
@@ -5,7 +5,7 @@
"data" : {
"pending": {
"account" :{
- "transactionCount" : 32
+ "transactionCount" : 33
}
}
}
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json
new file mode 100644
index 000000000..b910e159c
--- /dev/null
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json
@@ -0,0 +1,19 @@
+{
+ "request": "{transaction (hash : \"0x3ecd2ca6cf26c864d0ea5f038a58d4cd4a46a3e242fe92f446f392fdc232dd98\") { accessList { address storageKeys } maxFeePerGas maxPriorityFeePerGas nonce type status } } ",
+ "response": {
+ "data": {
+ "transaction": {
+ "accessList": [{
+ "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
+ "storageKeys": ["0x0000000000000000000000000000000000000000000000000000000000000000"]
+ }],
+ "maxFeePerGas": "0xb2d05e00",
+ "maxPriorityFeePerGas": "0x3b9aca00",
+ "nonce": 32,
+ "type": 2,
+ "status": 1
+ }
+ }
+ },
+ "statusCode": 200
+}
\ No newline at end of file
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json
index 4e6c33d3f..7ba8b74a4 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json
@@ -11,6 +11,9 @@
},
{
"number": 32
+ },
+ {
+ "number": 33
}
]
}
diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json
index 46cad8c1c..c12410e10 100644
--- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json
+++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json
@@ -15,7 +15,7 @@
"account": {
"balance": "0x140"
},
- "estimateGas": 21000,
+ "estimateGas": 53000,
"call": {
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
"status": 1
diff --git a/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java b/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java
index 4975cbee0..d2909a84f 100644
--- a/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java
+++ b/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java
@@ -32,8 +32,14 @@ import com.google.common.io.Resources;
/** The Block test util. */
public final class BlockTestUtil {
+ private BlockTestUtil() {
+ throw new RuntimeException("Utility Class");
+ }
+
private static final Supplier testChainSupplier =
Suppliers.memoize(BlockTestUtil::supplyTestChainResources);
+ private static final Supplier hiveTestChainSupplier =
+ Suppliers.memoize(BlockTestUtil::supplyHiveTestChainResources);
private static final Supplier testChainLondonSupplier =
Suppliers.memoize(BlockTestUtil::supplyTestChainLondonResources);
private static final Supplier mainnetChainSupplier =
@@ -92,6 +98,15 @@ public final class BlockTestUtil {
return testChainSupplier.get();
}
+ /**
+ * Gets test chain resources for hive tests.
+ *
+ * @return the test chain resources
+ */
+ public static ChainResources getHiveTestChainResources() {
+ return hiveTestChainSupplier.get();
+ }
+
/**
* Gets test chain london resources.
*
@@ -148,6 +163,15 @@ public final class BlockTestUtil {
return new ChainResources(genesisURL, blocksURL);
}
+ private static ChainResources supplyHiveTestChainResources() {
+ final URL genesisURL =
+ ensureFileUrl(BlockTestUtil.class.getClassLoader().getResource("hive/testGenesis.json"));
+ final URL blocksURL =
+ ensureFileUrl(
+ BlockTestUtil.class.getClassLoader().getResource("hive/testBlockchain.blocks"));
+ return new ChainResources(genesisURL, blocksURL);
+ }
+
private static ChainResources supplyTestChainLondonResources() {
final URL genesisURL =
ensureFileUrl(
diff --git a/testutil/src/main/resources/hive/testBlockchain.blocks b/testutil/src/main/resources/hive/testBlockchain.blocks
new file mode 100644
index 000000000..480efc87d
Binary files /dev/null and b/testutil/src/main/resources/hive/testBlockchain.blocks differ
diff --git a/testutil/src/main/resources/hive/testGenesis.json b/testutil/src/main/resources/hive/testGenesis.json
new file mode 100644
index 000000000..248f0933d
--- /dev/null
+++ b/testutil/src/main/resources/hive/testGenesis.json
@@ -0,0 +1,22 @@
+{
+ "config": {
+ "chainId": 1,
+ "ethash": {
+ },
+ "londonBlock": 33,
+ "shanghaiTime": 1444660030
+ },
+ "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
+ "difficulty" : "0x020000",
+ "gasLimit" : "0x2fefd8",
+ "timestamp" : "0x54c98c81",
+ "extraData" : "0x42",
+ "mixHash" : "0x2c85bcbce56429100b2108254bb56906257582aeafcbd682bc9af67a9f5aee46",
+ "nonce" : "0x78cc16f7b4f65485",
+ "alloc" : {
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance" : "0x09184e72a000"
+ }
+ }
+}
\ No newline at end of file