diff --git a/build.gradle b/build.gradle index a8e02a8835..1adc3b992c 100644 --- a/build.gradle +++ b/build.gradle @@ -365,9 +365,65 @@ allprojects { options.addBooleanOption('Xdoclint/package:-org.hyperledger.besu.privacy.contracts.generated,' + '-org.hyperledger.besu.tests.acceptance.*,' + '-org.hyperledger.besu.tests.web3j.generated,' + - // TODO: these are temporary disabled (ethereum and sub modules), it should be removed in a future PR. - '-org.hyperledger.besu.ethereum.*,' + - '-org.hyperledger.besu.evmtool', + // TODO: these are temporary excluded from lint (ethereum sub modules), it should be removed in a future PR. + // ethereum api module + '-org.hyperledger.besu.ethereum.api.handlers,' + + '-org.hyperledger.besu.ethereum.api.jsonrpc,' + + '-org.hyperledger.besu.ethereum.api.jsonrpc.*,' + + '-org.hyperledger.besu.ethereum.api.query,' + + '-org.hyperledger.besu.ethereum.api.query.*,' + + '-org.hyperledger.besu.ethereum.api.tls,' + + '-org.hyperledger.besu.ethereum.api.util,' + + // ethereum blockcreation module + '-org.hyperledger.besu.ethereum.blockcreation,' + + '-org.hyperledger.besu.ethereum.blockcreation.*,' + + // ethereum core module + '-org.hyperledger.besu.ethereum.chain,' + + '-org.hyperledger.besu.ethereum.core,' + + '-org.hyperledger.besu.ethereum.core.*,' + + '-org.hyperledger.besu.ethereum.debug,' + + '-org.hyperledger.besu.ethereum.difficulty.fixed,' + + '-org.hyperledger.besu.ethereum.forkid,' + + '-org.hyperledger.besu.ethereum.mainnet,' + + '-org.hyperledger.besu.ethereum.mainnet.*,' + + '-org.hyperledger.besu.ethereum.privacy,' + + '-org.hyperledger.besu.ethereum.privacy.*,' + + '-org.hyperledger.besu.ethereum.processing,' + + '-org.hyperledger.besu.ethereum.proof,' + + '-org.hyperledger.besu.ethereum.storage,' + + '-org.hyperledger.besu.ethereum.storage.*,' + + '-org.hyperledger.besu.ethereum.transaction,' + + '-org.hyperledger.besu.ethereum.trie.*,' + + '-org.hyperledger.besu.ethereum.util,' + + '-org.hyperledger.besu.ethereum.vm,' + + '-org.hyperledger.besu.ethereum.worldstate,' + + // ethereum eth module + '-org.hyperledger.besu.ethereum.eth.*,' + + '-org.hyperledger.besu.ethereum.eth,' + + '-org.hyperledger.besu.consensus.merge,' + + // evmtool module + '-org.hyperledger.besu.evmtool,' + + // p2p module + '-org.hyperledger.besu.ethereum.p2p,' + + '-org.hyperledger.besu.ethereum.p2p.*,' + + // permissioning module + '-org.hyperledger.besu.ethereum.permissioning,' + + '-org.hyperledger.besu.ethereum.permissioning.*,' + + // referencetests module + '-org.hyperledger.besu.ethereum.referencetests,' + + // retesteth module + '-org.hyperledger.besu.ethereum.retesteth.methods,' + + '-org.hyperledger.besu.ethereum.retesteth,' + + //rlp module + '-org.hyperledger.besu.ethereum.rlp,' + + // stratum module + '-org.hyperledger.besu.ethereum.stratum,' + + // trie module + '-org.hyperledger.besu.ethereum.trie.*,' + + '-org.hyperledger.besu.ethereum.trie,' + + // verkle trie module + '-org.hyperledger.besu.ethereum.verkletrie,' + + '-org.hyperledger.besu.ethereum.verkletrie.*', true) options.addStringOption('Xmaxerrs','65535') options.addStringOption('Xmaxwarns','65535') diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java index 334b716900..e317845f84 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java @@ -18,58 +18,125 @@ import org.hyperledger.besu.datatypes.Wei; import org.immutables.value.Value; +/** + * The ApiConfiguration class provides configuration for the API. It includes default values for gas + * price, max logs range, gas cap, and other parameters. + */ @Value.Immutable @Value.Style(allParameters = true) public abstract class ApiConfiguration { + /** + * The default lower bound coefficient for gas and priority fee. This value is used as the default + * lower bound when calculating the gas and priority fee. + */ public static final long DEFAULT_LOWER_BOUND_GAS_AND_PRIORITY_FEE_COEFFICIENT = 0L; + + /** + * The default upper bound coefficient for gas and priority fee. This value is used as the default + * upper bound when calculating the gas and priority fee. + */ public static final long DEFAULT_UPPER_BOUND_GAS_AND_PRIORITY_FEE_COEFFICIENT = Long.MAX_VALUE; + /** Constructs a new ApiConfiguration with default values. */ + protected ApiConfiguration() {} + + /** + * Returns the number of blocks to consider for gas price calculations. Default value is 100. + * + * @return the number of blocks for gas price calculations + */ @Value.Default public long getGasPriceBlocks() { return 100; } + /** + * Returns the percentile to use for gas price calculations. Default value is 50.0. + * + * @return the percentile for gas price calculations + */ @Value.Default public double getGasPricePercentile() { return 50.0d; } + /** + * Returns the maximum gas price. Default value is 500 GWei. + * + * @return the maximum gas price + */ @Value.Default public Wei getGasPriceMax() { return Wei.of(500_000_000_000L); // 500 GWei } + /** + * Returns the fraction to use for gas price calculations. This is derived from the gas price + * percentile. + * + * @return the fraction for gas price calculations + */ @Value.Derived public double getGasPriceFraction() { return getGasPricePercentile() / 100.0; } + /** + * Returns the maximum range for logs. Default value is 5000. + * + * @return the maximum range for logs + */ @Value.Default public Long getMaxLogsRange() { return 5000L; } + /** + * Returns the gas cap. Default value is 0. + * + * @return the gas cap + */ @Value.Default public Long getGasCap() { return 0L; } + /** + * Returns whether gas and priority fee limiting is enabled. Default value is false. + * + * @return true if gas and priority fee limiting is enabled, false otherwise + */ @Value.Default public boolean isGasAndPriorityFeeLimitingEnabled() { return false; } + /** + * Returns the lower bound coefficient for gas and priority fee. Default value is 0. + * + * @return the lower bound coefficient for gas and priority fee + */ @Value.Default public Long getLowerBoundGasAndPriorityFeeCoefficient() { return DEFAULT_LOWER_BOUND_GAS_AND_PRIORITY_FEE_COEFFICIENT; } + /** + * Returns the upper bound coefficient for gas and priority fee. Default value is Long.MAX_VALUE. + * + * @return the upper bound coefficient for gas and priority fee + */ @Value.Default public Long getUpperBoundGasAndPriorityFeeCoefficient() { return DEFAULT_UPPER_BOUND_GAS_AND_PRIORITY_FEE_COEFFICIENT; } + /** + * Returns the maximum range for trace filter. Default value is 1000. + * + * @return the maximum range for trace filter + */ @Value.Default public Long getMaxTraceFilterRange() { return 1000L; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLConfiguration.java index 8c32b55288..a2829edb07 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLConfiguration.java @@ -26,17 +26,33 @@ import java.util.Objects; import com.google.common.base.MoreObjects; +/** + * Represents the configuration for GraphQL. This class is used to set and get the configuration + * details for GraphQL such as enabling GraphQL, setting the port and host, setting the allowed + * domains for CORS, setting the hosts allowlist, and setting the HTTP timeout. + */ public class GraphQLConfiguration { private static final String DEFAULT_GRAPHQL_HTTP_HOST = "127.0.0.1"; + + /** The default port number for the GraphQL HTTP server. */ public static final int DEFAULT_GRAPHQL_HTTP_PORT = 8547; private boolean enabled; private int port; private String host; private List corsAllowedDomains = Collections.emptyList(); - private List hostsAllowlist = Arrays.asList("localhost", "127.0.0.1"); + private List hostsAllowlist = Arrays.asList("localhost", DEFAULT_GRAPHQL_HTTP_HOST); private long httpTimeoutSec = TimeoutOptions.defaultOptions().getTimeoutSeconds(); + /** + * Creates a default configuration for GraphQL. + * + *

This method initializes a new GraphQLConfiguration object with default settings. The default + * settings are: - GraphQL is not enabled - The port is set to the default GraphQL HTTP port - The + * host is set to the default GraphQL HTTP host - The HTTP timeout is set to the default timeout + * + * @return a GraphQLConfiguration object with default settings + */ public static GraphQLConfiguration createDefault() { final GraphQLConfiguration config = new GraphQLConfiguration(); config.setEnabled(false); @@ -48,52 +64,112 @@ public class GraphQLConfiguration { private GraphQLConfiguration() {} + /** + * Checks if GraphQL is enabled. + * + * @return true if GraphQL is enabled, false otherwise + */ public boolean isEnabled() { return enabled; } + /** + * Sets the enabled status of GraphQL. + * + * @param enabled the status to set. true to enable GraphQL, false to disable it + */ public void setEnabled(final boolean enabled) { this.enabled = enabled; } + /** + * Retrieves the port number for the GraphQL HTTP server. + * + * @return the port number + */ public int getPort() { return port; } + /** + * Sets the port number for the GraphQL HTTP server. + * + * @param port the port number to set + */ public void setPort(final int port) { this.port = port; } + /** + * Retrieves the host for the GraphQL HTTP server. + * + * @return the host + */ public String getHost() { return host; } + /** + * Sets the host for the GraphQL HTTP server. + * + * @param host the host to set + */ public void setHost(final String host) { this.host = host; } + /** + * Retrieves the allowed domains for CORS. + * + * @return a collection of allowed domains for CORS + */ Collection getCorsAllowedDomains() { return corsAllowedDomains; } + /** + * Sets the allowed domains for CORS. + * + * @param corsAllowedDomains a list of allowed domains for CORS + */ public void setCorsAllowedDomains(final List corsAllowedDomains) { checkNotNull(corsAllowedDomains); this.corsAllowedDomains = corsAllowedDomains; } + /** + * Retrieves the hosts allowlist. + * + * @return a collection of hosts in the allowlist + */ Collection getHostsAllowlist() { return Collections.unmodifiableCollection(this.hostsAllowlist); } + /** + * Sets the hosts allowlist. + * + * @param hostsAllowlist a list of hosts to be added to the allowlist + */ public void setHostsAllowlist(final List hostsAllowlist) { checkNotNull(hostsAllowlist); this.hostsAllowlist = hostsAllowlist; } + /** + * Retrieves the HTTP timeout in seconds. + * + * @return the HTTP timeout in seconds + */ public Long getHttpTimeoutSec() { return httpTimeoutSec; } + /** + * Sets the HTTP timeout in seconds. + * + * @param httpTimeoutSec the HTTP timeout to set in seconds + */ public void setHttpTimeoutSec(final long httpTimeoutSec) { this.httpTimeoutSec = httpTimeoutSec; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java index 05752f813b..c12f7578c6 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java @@ -14,14 +14,33 @@ */ package org.hyperledger.besu.ethereum.api.graphql; -/** Internal GraphQL Context */ +/** + * Enum representing various context types for GraphQL. + * + *

These context types are used internally by GraphQL to manage different aspects of the system. + */ public enum GraphQLContextType { + /** Represents blockchain queries context. */ BLOCKCHAIN_QUERIES, + + /** Represents protocol schedule context. */ PROTOCOL_SCHEDULE, + + /** Represents transaction pool context. */ TRANSACTION_POOL, + + /** Represents mining coordinator context. */ MINING_COORDINATOR, + + /** Represents synchronizer context. */ SYNCHRONIZER, + + /** Represents is alive handler context. */ IS_ALIVE_HANDLER, + + /** Represents chain ID context. */ CHAIN_ID, + + /** Represents gas cap context. */ GAS_CAP } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContext.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContext.java index 0ccd8d2b1e..acebe95d11 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContext.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContext.java @@ -21,18 +21,56 @@ import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +/** + * Interface representing the context for a GraphQL data fetcher. + * + *

This context provides access to various components of the system such as the transaction pool, + * blockchain queries, mining coordinator, synchronizer, and protocol schedule. + */ public interface GraphQLDataFetcherContext { + /** + * Retrieves the transaction pool. + * + * @return the transaction pool + */ TransactionPool getTransactionPool(); + /** + * Retrieves the blockchain queries. + * + * @return the blockchain queries + */ BlockchainQueries getBlockchainQueries(); + /** + * Retrieves the mining coordinator. + * + * @return the mining coordinator + */ MiningCoordinator getMiningCoordinator(); + /** + * Retrieves the synchronizer. + * + * @return the synchronizer + */ Synchronizer getSynchronizer(); + /** + * Retrieves the protocol schedule. + * + * @return the protocol schedule + */ ProtocolSchedule getProtocolSchedule(); + /** + * Retrieves the is alive handler. + * + *

By default, this method returns a new IsAliveHandler instance with a status of true. + * + * @return the is alive handler + */ default IsAliveHandler getIsAliveHandler() { return new IsAliveHandler(true); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContextImpl.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContextImpl.java index 0e426ebf3a..1f5ed82d74 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContextImpl.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetcherContextImpl.java @@ -21,6 +21,12 @@ import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +/** + * Implementation of the GraphQLDataFetcherContext interface. + * + *

This class provides access to various components of the system such as the transaction pool, + * blockchain queries, mining coordinator, synchronizer, and protocol schedule. + */ public class GraphQLDataFetcherContextImpl implements GraphQLDataFetcherContext { private final BlockchainQueries blockchainQueries; @@ -30,6 +36,12 @@ public class GraphQLDataFetcherContextImpl implements GraphQLDataFetcherContext private final TransactionPool transactionPool; private final IsAliveHandler isAliveHandler; + /** + * Constructor that takes a GraphQLDataFetcherContext and an IsAliveHandler. + * + * @param context the GraphQLDataFetcherContext + * @param isAliveHandler the IsAliveHandler + */ public GraphQLDataFetcherContextImpl( final GraphQLDataFetcherContext context, final IsAliveHandler isAliveHandler) { this( @@ -41,6 +53,16 @@ public class GraphQLDataFetcherContextImpl implements GraphQLDataFetcherContext isAliveHandler); } + /** + * Constructor that takes a BlockchainQueries, ProtocolSchedule, TransactionPool, + * MiningCoordinator, and Synchronizer. + * + * @param blockchainQueries the BlockchainQueries + * @param protocolSchedule the ProtocolSchedule + * @param transactionPool the TransactionPool + * @param miningCoordinator the MiningCoordinator + * @param synchronizer the Synchronizer + */ public GraphQLDataFetcherContextImpl( final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule, @@ -56,6 +78,17 @@ public class GraphQLDataFetcherContextImpl implements GraphQLDataFetcherContext new IsAliveHandler(true)); } + /** + * Constructor that takes a BlockchainQueries, ProtocolSchedule, TransactionPool, + * MiningCoordinator, Synchronizer, and IsAliveHandler. + * + * @param blockchainQueries the BlockchainQueries + * @param protocolSchedule the ProtocolSchedule + * @param transactionPool the TransactionPool + * @param miningCoordinator the MiningCoordinator + * @param synchronizer the Synchronizer + * @param isAliveHandler the IsAliveHandler + */ public GraphQLDataFetcherContextImpl( final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java index 312491f5c3..0b97bdb2e9 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java @@ -61,10 +61,34 @@ import graphql.schema.DataFetcher; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +/** + * This class contains data fetchers for GraphQL queries. + * + *

Data fetchers are responsible for fetching data for a specific field. Each field in the schema + * is associated with a data fetcher. When the field is being processed during a query, the + * associated data fetcher is invoked to get the data for that field. + * + *

This class contains data fetchers for various fields such as protocol version, syncing state, + * pending state, gas price, chain ID, max priority fee per gas, range block, block, account, logs, + * and transaction. + * + *

Each data fetcher is a method that returns a `DataFetcher` object. The `DataFetcher` object + * defines how to fetch the data for the field. It takes a `DataFetchingEnvironment` object as input + * which contains all the context needed to fetch the data. + */ public class GraphQLDataFetchers { private final Integer highestEthVersion; + /** + * Constructs a new GraphQLDataFetchers instance. + * + *

This constructor takes a set of supported capabilities and determines the highest Ethereum + * protocol version supported by these capabilities. This version is then stored and can be + * fetched using the getProtocolVersionDataFetcher method. + * + * @param supportedCapabilities a set of capabilities supported by the Ethereum node + */ public GraphQLDataFetchers(final Set supportedCapabilities) { final OptionalInt version = supportedCapabilities.stream() @@ -74,10 +98,30 @@ public class GraphQLDataFetchers { highestEthVersion = version.isPresent() ? version.getAsInt() : null; } + /** + * Returns a DataFetcher that fetches the highest Ethereum protocol version supported by the node. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input and returns the highest Ethereum protocol version as an + * Optional. + * + * @return a DataFetcher that fetches the highest Ethereum protocol version + */ DataFetcher> getProtocolVersionDataFetcher() { return dataFetchingEnvironment -> Optional.of(highestEthVersion); } + /** + * Returns a DataFetcher that fetches the result of sending a raw transaction. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input and returns the hash of the transaction if it is valid + * and added to the transaction pool. If the transaction is invalid, it throws a GraphQLException + * with the invalid reason. If the raw transaction data cannot be read, it throws a + * GraphQLException with INVALID_PARAMS error. + * + * @return a DataFetcher that fetches the result of sending a raw transaction + */ DataFetcher> getSendRawTransactionDataFetcher() { return dataFetchingEnvironment -> { try { @@ -99,6 +143,19 @@ public class GraphQLDataFetchers { }; } + /** + * Returns a DataFetcher that fetches the syncing state of the Ethereum node. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input and returns the syncing state as an + * Optional. + * + *

The SyncStateAdapter is a wrapper around the SyncStatus of the Ethereum node. It provides + * information about the current syncing state of the node such as the current block, highest + * block, and starting block. + * + * @return a DataFetcher that fetches the syncing state of the Ethereum node + */ DataFetcher> getSyncingDataFetcher() { return dataFetchingEnvironment -> { final Synchronizer synchronizer = @@ -125,6 +182,15 @@ public class GraphQLDataFetchers { }; } + /** + * Returns a DataFetcher that fetches the chain ID of the Ethereum node. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input and returns the chain ID as an {@code + * Optional}. + * + * @return a DataFetcher that fetches the chain ID of the Ethereum node + */ public DataFetcher> getChainIdDataFetcher() { return dataFetchingEnvironment -> { final GraphQLContext graphQLContext = dataFetchingEnvironment.getGraphQlContext(); @@ -132,6 +198,15 @@ public class GraphQLDataFetchers { }; } + /** + * Returns a DataFetcher that fetches the maximum priority fee per gas of the Ethereum node. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input and returns the maximum priority fee per gas as a Wei + * object. If the maximum priority fee per gas is not available, it returns Wei.ZERO. + * + * @return a DataFetcher that fetches the maximum priority fee per gas of the Ethereum node + */ public DataFetcher getMaxPriorityFeePerGasDataFetcher() { return dataFetchingEnvironment -> { final BlockchainQueries blockchainQuery = @@ -167,6 +242,20 @@ public class GraphQLDataFetchers { }; } + /** + * Returns a DataFetcher that fetches a specific block in the Ethereum blockchain. + * + *

The DataFetcher is a functional interface. It has a single method that takes a + * DataFetchingEnvironment object as input. This method fetches a block based on either a block + * number or a block hash. If both a block number and a block hash are provided, it throws a + * GraphQLException with INVALID_PARAMS error. If neither a block number nor a block hash is + * provided, it fetches the latest block. + * + *

The fetched block is then wrapped in a {@link NormalBlockAdapter} and returned as an {@code + * Optional}. + * + * @return a DataFetcher that fetches a specific block in the Ethereum blockchain + */ public DataFetcher> getBlockDataFetcher() { return dataFetchingEnvironment -> { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpService.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpService.java index abbcdbf945..fc763a1e3b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpService.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpService.java @@ -68,6 +68,15 @@ import io.vertx.ext.web.handler.TimeoutHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * This class handles the HTTP service for GraphQL. It sets up the server, handles requests and + * responses, and manages the lifecycle of the server. + * + *

It is responsible for processing GraphQL requests, executing them using the provided GraphQL + * engine, and returning the results in the HTTP response. + * + *

It also handles errors and exceptions that may occur during the processing of a request. + */ public class GraphQLHttpService { private static final Logger LOG = LoggerFactory.getLogger(GraphQLHttpService.class); @@ -126,6 +135,15 @@ public class GraphQLHttpService { checkArgument(config.getHost() != null, "Required host is not configured."); } + /** + * Starts the GraphQL HTTP service. + * + *

This method initializes the HTTP server and sets up the necessary routes for handling + * GraphQL requests. It also validates the configuration and sets up the necessary handlers for + * different types of requests. + * + * @return a CompletableFuture that will be completed when the server is successfully started. + */ public CompletableFuture start() { LOG.info("Starting GraphQL HTTP service on {}:{}", config.getHost(), config.getPort()); // Create the HTTP server and a router object. @@ -230,6 +248,14 @@ public class GraphQLHttpService { } } + /** + * Stops the GraphQL HTTP service. + * + *

This method stops the HTTP server that was created and started by the start() method. If the + * server is not running, this method will do nothing. + * + * @return a CompletableFuture that will be completed when the server is successfully stopped. + */ public CompletableFuture stop() { if (httpServer == null) { return CompletableFuture.completedFuture(null); @@ -248,6 +274,15 @@ public class GraphQLHttpService { return resultFuture; } + /** + * Returns the socket address of the GraphQL HTTP service. + * + *

This method returns the socket address that the HTTP server is bound to. If the server is + * not running, it returns an empty socket address. + * + * @return the socket address of the HTTP server, or an empty socket address if the server is not + * running. + */ public InetSocketAddress socketAddress() { if (httpServer == null) { return EMPTY_SOCKET_ADDRESS; @@ -255,6 +290,14 @@ public class GraphQLHttpService { return new InetSocketAddress(config.getHost(), httpServer.actualPort()); } + /** + * Returns the URL of the GraphQL HTTP service. + * + *

This method constructs and returns the URL that the HTTP server is bound to. If the server + * is not running, it returns an empty string. + * + * @return the URL of the HTTP server, or an empty string if the server is not running. + */ @VisibleForTesting public String url() { if (httpServer == null) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLProvider.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLProvider.java index 7e62e39c05..2a3370572b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLProvider.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLProvider.java @@ -31,12 +31,30 @@ import graphql.schema.idl.SchemaParser; import graphql.schema.idl.TypeDefinitionRegistry; import graphql.schema.idl.TypeRuntimeWiring; +/** + * This class provides the GraphQL service. + * + *

It contains a method to build the GraphQL service with the provided data fetchers. + */ public class GraphQLProvider { + /** + * The maximum complexity allowed for a GraphQL query. + * + *

This constant is used to prevent overly complex queries from being executed. A query's + * complexity is calculated based on the number and type of fields it contains. + */ public static final int MAX_COMPLEXITY = 200; private GraphQLProvider() {} + /** + * Builds the GraphQL service with the provided data fetchers. + * + * @param graphQLDataFetchers the data fetchers to be used in the GraphQL service. + * @return the built GraphQL service. + * @throws IOException if there is an error reading the schema file. + */ public static GraphQL buildGraphQL(final GraphQLDataFetchers graphQLDataFetchers) throws IOException { final URL url = Resources.getResource("schema.graphqls"); 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 5762215bc5..9fbeae5fde 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 @@ -35,6 +35,13 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +/** + * The Scalars class provides methods for creating GraphQLScalarType objects. These objects + * represent the scalar types used in GraphQL, such as Address, BigInt, Bytes, Bytes32, and Long. + * Each method in this class returns a GraphQLScalarType object that has been configured with a + * specific Coercing implementation. The Coercing implementation defines how that type is + * serialized, deserialized and validated. + */ public class Scalars { private Scalars() {} @@ -366,6 +373,14 @@ public class Scalars { } }; + /** + * Creates a new GraphQLScalarType object for an Address. + * + *

The object is configured with a specific Coercing implementation that defines how the + * Address type is serialized, deserialized and validated. + * + * @return a GraphQLScalarType object for an Address. + */ public static GraphQLScalarType addressScalar() { return GraphQLScalarType.newScalar() .name("Address") @@ -374,6 +389,14 @@ public class Scalars { .build(); } + /** + * Creates a new GraphQLScalarType object for a BigInt. + * + *

The object is configured with a specific Coercing implementation that defines how the BigInt + * type is serialized, deserialized and validated. + * + * @return a GraphQLScalarType object for a BigInt. + */ public static GraphQLScalarType bigIntScalar() { return GraphQLScalarType.newScalar() .name("BigInt") @@ -382,6 +405,14 @@ public class Scalars { .build(); } + /** + * Creates a new GraphQLScalarType object for Bytes. + * + *

The object is configured with a specific Coercing implementation that defines how the Bytes + * type is serialized, deserialized and validated. + * + * @return a GraphQLScalarType object for Bytes. + */ public static GraphQLScalarType bytesScalar() { return GraphQLScalarType.newScalar() .name("Bytes") @@ -390,6 +421,14 @@ public class Scalars { .build(); } + /** + * Creates a new GraphQLScalarType object for Bytes32. + * + *

The object is configured with a specific Coercing implementation that defines how the + * Bytes32 type is serialized, deserialized and validated. + * + * @return a GraphQLScalarType object for Bytes32. + */ public static GraphQLScalarType bytes32Scalar() { return GraphQLScalarType.newScalar() .name("Bytes32") @@ -398,6 +437,14 @@ public class Scalars { .build(); } + /** + * Creates a new GraphQLScalarType object for a Long. + * + *

The object is configured with a specific Coercing implementation that defines how the Long + * type is serialized, deserialized and validated. + * + * @return a GraphQLScalarType object for a Long. + */ public static GraphQLScalarType longScalar() { return GraphQLScalarType.newScalar() .name("Long") diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccessListEntryAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccessListEntryAdapter.java index 10451dcc35..a0dc8743c8 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccessListEntryAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccessListEntryAdapter.java @@ -23,19 +23,40 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; +/** + * The AccessListEntryAdapter class extends the AdapterBase class. It provides methods to get the + * storage keys and address from an AccessListEntry. + */ @SuppressWarnings("unused") // reflected by GraphQL public class AccessListEntryAdapter extends AdapterBase { + + /** The AccessListEntry object that this adapter wraps. */ private final AccessListEntry accessListEntry; + /** + * Constructs a new AccessListEntryAdapter with the given AccessListEntry. + * + * @param accessListEntry the AccessListEntry to be adapted + */ public AccessListEntryAdapter(final AccessListEntry accessListEntry) { this.accessListEntry = accessListEntry; } + /** + * Returns the storage keys from the AccessListEntry. + * + * @return a list of storage keys + */ public List getStorageKeys() { final var storage = accessListEntry.storageKeys(); return new ArrayList<>(storage); } + /** + * Returns the address from the AccessListEntry. + * + * @return an Optional containing the address if it exists, otherwise an empty Optional + */ public Optional

getAddress() { return Optional.of(accessListEntry.address()); } 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 faf42aafc8..1b4c8323b6 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 @@ -28,6 +28,10 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +/** + * The AccountAdapter class extends the AdapterBase class. It provides methods to get the account + * details such as address, balance, transaction count, code, and storage. + */ @SuppressWarnings("unused") // reflected by GraphQL public class AccountAdapter extends AdapterBase { @@ -35,18 +39,42 @@ public class AccountAdapter extends AdapterBase { private final Address address; private final Optional blockNumber; + /** + * Constructs a new AccountAdapter with the given Account. + * + * @param account the Account to be adapted + */ public AccountAdapter(final Account account) { this(account == null ? null : account.getAddress(), account, Optional.empty()); } + /** + * Constructs a new AccountAdapter with the given Account and block number. + * + * @param account the Account to be adapted + * @param blockNumber the block number associated with the account + */ public AccountAdapter(final Account account, final Optional blockNumber) { this(account == null ? null : account.getAddress(), account, blockNumber); } + /** + * Constructs a new AccountAdapter with the given address and Account. + * + * @param address the address of the account + * @param account the Account to be adapted + */ public AccountAdapter(final Address address, final Account account) { this(address, account, Optional.empty()); } + /** + * Constructs a new AccountAdapter with the given address, Account, and block number. + * + * @param address the address of the account + * @param account the Account to be adapted + * @param blockNumber the block number associated with the account + */ public AccountAdapter( final Address address, final Account account, final Optional blockNumber) { this.account = Optional.ofNullable(account); @@ -54,18 +82,39 @@ public class AccountAdapter extends AdapterBase { this.blockNumber = blockNumber; } + /** + * Returns the address of the account. + * + * @return the address of the account + */ public Address getAddress() { return address; } + /** + * Returns the balance of the account. + * + * @return the balance of the account + */ public Wei getBalance() { return account.map(AccountState::getBalance).orElse(Wei.ZERO); } + /** + * Returns the transaction count of the account. + * + * @return the transaction count of the account + */ public Long getTransactionCount() { return account.map(AccountState::getNonce).orElse(0L); } + /** + * Returns the code of the account. + * + * @param environment the DataFetchingEnvironment + * @return the code of the account + */ public Bytes getCode(final DataFetchingEnvironment environment) { if (account.get() instanceof BonsaiAccount) { @@ -80,6 +129,12 @@ public class AccountAdapter extends AdapterBase { } } + /** + * Returns the storage of the account. + * + * @param environment the DataFetchingEnvironment + * @return the storage of the account + */ public Bytes32 getStorage(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Bytes32 slot = environment.getArgument("slot"); 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 96434ee375..6d5b696353 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 @@ -48,15 +48,30 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +/** + * The BlockAdapterBase class extends the AdapterBase class. It provides methods to get and + * manipulate block data. + */ @SuppressWarnings("unused") // reflected by GraphQL public class BlockAdapterBase extends AdapterBase { private final BlockHeader header; + /** + * Constructs a new BlockAdapterBase with the given BlockHeader. + * + * @param header the BlockHeader to be adapted + */ BlockAdapterBase(final BlockHeader header) { this.header = header; } + /** + * Returns the parent block of the current block. + * + * @param environment the DataFetchingEnvironment + * @return an Optional containing the parent block if it exists, otherwise an empty Optional + */ public Optional getParent(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Hash parentHash = header.getParentHash(); @@ -65,28 +80,59 @@ public class BlockAdapterBase extends AdapterBase { return block.map(NormalBlockAdapter::new); } + /** + * Returns the hash of the current block. + * + * @return the hash of the block + */ public Bytes32 getHash() { return header.getHash(); } + /** + * Returns the nonce of the current block. + * + * @return the nonce of the block + */ public Bytes getNonce() { final long nonce = header.getNonce(); final byte[] bytes = Longs.toByteArray(nonce); return Bytes.wrap(bytes); } + /** + * Returns the transactions root of the current block. + * + * @return the transactions root of the block + */ public Bytes32 getTransactionsRoot() { return header.getTransactionsRoot(); } + /** + * Returns the state root of the current block. + * + * @return the state root of the block + */ public Bytes32 getStateRoot() { return header.getStateRoot(); } + /** + * Returns the receipts root of the current block. + * + * @return the receipts root of the block + */ public Bytes32 getReceiptsRoot() { return header.getReceiptsRoot(); } + /** + * Returns the miner of the current block. + * + * @param environment the DataFetchingEnvironment + * @return an AccountAdapter instance representing the miner of the block + */ public AccountAdapter getMiner(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); @@ -102,46 +148,103 @@ public class BlockAdapterBase extends AdapterBase { .orElseGet(() -> new EmptyAccountAdapter(header.getCoinbase())); } + /** + * Returns the extra data of the current block. + * + * @return the extra data of the block + */ public Bytes getExtraData() { return header.getExtraData(); } + /** + * Returns the base fee per gas of the current block. + * + * @return the base fee per gas of the block + */ public Optional getBaseFeePerGas() { return header.getBaseFee(); } + /** + * Returns the gas limit of the current block. + * + * @return the gas limit of the block + */ public Long getGasLimit() { return header.getGasLimit(); } + /** + * Returns the gas used by the current block. + * + * @return the gas used by the block + */ public Long getGasUsed() { return header.getGasUsed(); } + /** + * Returns the timestamp of the current block. + * + * @return the timestamp of the block + */ public Long getTimestamp() { return header.getTimestamp(); } + /** + * Returns the logs bloom of the current block. + * + * @return the logs bloom of the block + */ public Bytes getLogsBloom() { return header.getLogsBloom(); } + /** + * Returns the mix hash of the current block. + * + * @return the mix hash of the block + */ public Bytes32 getMixHash() { return header.getMixHash(); } + /** + * Returns the difficulty of the current block. + * + * @return the difficulty of the block + */ public Difficulty getDifficulty() { return header.getDifficulty(); } + /** + * Returns the ommer hash of the current block. + * + * @return the ommer hash of the block + */ public Bytes32 getOmmerHash() { return header.getOmmersHash(); } + /** + * Returns the number of the current block. + * + * @return the number of the block + */ public Long getNumber() { return header.getNumber(); } + /** + * Returns an AccountAdapter instance for a given address at the current block. + * + * @param environment the DataFetchingEnvironment + * @return an AccountAdapter instance representing the account of the given address at the current + * block + */ public AccountAdapter getAccount(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final long bn = header.getNumber(); @@ -152,6 +255,13 @@ public class BlockAdapterBase extends AdapterBase { .get(); } + /** + * Returns a list of logs for the current block that match a given filter. + * + * @param environment the DataFetchingEnvironment + * @return a list of LogAdapter instances representing the logs of the current block that match + * the filter + */ public List getLogs(final DataFetchingEnvironment environment) { final Map filter = environment.getArgument("filter"); @@ -183,11 +293,24 @@ public class BlockAdapterBase extends AdapterBase { return results; } + /** + * Estimates the gas used for a call execution. + * + * @param environment the DataFetchingEnvironment + * @return the estimated gas used for the call execution + */ public Long getEstimateGas(final DataFetchingEnvironment environment) { final Optional result = executeCall(environment); return result.map(CallResult::getGasUsed).orElse(0L); } + /** + * Executes a call and returns the result. + * + * @param environment the DataFetchingEnvironment + * @return an Optional containing the result of the call execution if it exists, otherwise an + * empty Optional + */ public Optional getCall(final DataFetchingEnvironment environment) { return executeCall(environment); } @@ -259,12 +382,23 @@ public class BlockAdapterBase extends AdapterBase { header); } + /** + * Returns the raw header of the current block. + * + * @return the raw header of the block + */ Bytes getRawHeader() { final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); header.writeTo(rlpOutput); return rlpOutput.encoded(); } + /** + * Returns the raw data of the current block. + * + * @param environment the DataFetchingEnvironment + * @return the raw data of the block + */ Bytes getRaw(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); return query @@ -279,10 +413,22 @@ public class BlockAdapterBase extends AdapterBase { .orElse(Bytes.EMPTY); } + /** + * Returns the withdrawals root of the current block. + * + * @return an Optional containing the withdrawals root if it exists, otherwise an empty Optional + */ Optional getWithdrawalsRoot() { return header.getWithdrawalsRoot().map(Function.identity()); } + /** + * Returns a list of withdrawals for the current block. + * + * @param environment the DataFetchingEnvironment + * @return an Optional containing a list of WithdrawalAdapter instances representing the + * withdrawals of the current block if they exist, otherwise an empty Optional + */ Optional> getWithdrawals(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); return query @@ -295,10 +441,22 @@ public class BlockAdapterBase extends AdapterBase { .map(wl -> wl.stream().map(WithdrawalAdapter::new).toList())); } + /** + * Returns the blob gas used by the current block. + * + * @return an Optional containing the blob gas used by the current block if it exists, otherwise + * an empty Optional + */ public Optional getBlobGasUsed() { return header.getBlobGasUsed(); } + /** + * Returns the excess blob gas of the current block. + * + * @return an Optional containing the excess blob gas of the current block if it exists, otherwise + * an empty Optional + */ public Optional getExcessBlobGas() { return header.getExcessBlobGas().map(BlobGas::toLong); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/CallResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/CallResult.java index 78fa30d874..0a5c9a8f38 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/CallResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/CallResult.java @@ -16,26 +16,55 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter; import org.apache.tuweni.bytes.Bytes; +/** + * Represents the result of a call execution. This class is used to encapsulate the status, gas + * used, and data returned by a call execution. It is used in conjunction with the {@link + * org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.BlockAdapterBase} class. + * + * @see org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.BlockAdapterBase + */ @SuppressWarnings("unused") // reflected by GraphQL public class CallResult { private final Long status; private final Long gasUsed; private final Bytes data; + /** + * Constructs a new CallResult. + * + * @param status the status of the call execution + * @param gasUsed the amount of gas used by the call + * @param data the data returned by the call + */ CallResult(final Long status, final Long gasUsed, final Bytes data) { this.status = status; this.gasUsed = gasUsed; this.data = data; } + /** + * Returns the status of the call execution. + * + * @return the status of the call execution + */ public Long getStatus() { return status; } + /** + * Returns the amount of gas used by the call. + * + * @return the amount of gas used by the call + */ public Long getGasUsed() { return gasUsed; } + /** + * Returns the data returned by the call. + * + * @return the data returned by the call + */ public Bytes getData() { return data; } 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 4c19b997b6..775934fb1b 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 @@ -21,9 +21,22 @@ import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +/** + * Represents an empty account in the Ethereum blockchain. This class is used when an account does + * not exist at a specific address. It provides default values for the account's properties. It + * extends the {@link org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.AccountAdapter} + * class. + * + * @see org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.AccountAdapter + */ public class EmptyAccountAdapter extends AccountAdapter { private final Address address; + /** + * Constructs a new EmptyAccountAdapter. + * + * @param address the address of the account + */ public EmptyAccountAdapter(final Address address) { super(null); this.address = address; 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 6beab46fdc..012edbe512 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 @@ -28,27 +28,62 @@ import java.util.Optional; import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; +/** + * This class is an adapter for the LogWithMetadata class. + * + *

It extends the AdapterBase class and provides methods to get the index, topics, data, + * transaction, and account associated with a log. + */ @SuppressWarnings("unused") // reflected by GraphQL public class LogAdapter extends AdapterBase { private final LogWithMetadata logWithMetadata; + /** + * Constructor for LogAdapter. + * + *

It initializes the logWithMetadata field with the provided argument. + * + * @param logWithMetadata the log with metadata to be adapted. + */ public LogAdapter(final LogWithMetadata logWithMetadata) { this.logWithMetadata = logWithMetadata; } + /** + * Returns the index of the log. + * + * @return the index of the log. + */ public Integer getIndex() { return logWithMetadata.getLogIndex(); } + /** + * Returns the topics of the log. + * + * @return a list of topics of the log. + */ public List getTopics() { final List topics = logWithMetadata.getTopics(); return new ArrayList<>(topics); } + /** + * Returns the data of the log. + * + * @return the data of the log. + */ public Bytes getData() { return logWithMetadata.getData(); } + /** + * Returns the transaction associated with the log. + * + * @param environment the data fetching environment. + * @return a TransactionAdapter for the transaction associated with the log. + * @throws java.util.NoSuchElementException if the transaction is not found. + */ public TransactionAdapter getTransaction(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Hash hash = logWithMetadata.getTransactionHash(); @@ -56,6 +91,12 @@ public class LogAdapter extends AdapterBase { return tran.map(TransactionAdapter::new).orElseThrow(); } + /** + * Returns the account associated with the log. + * + * @param environment the data fetching environment. + * @return an AccountAdapter for the account associated with the log. + */ public AccountAdapter getAccount(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); long blockNumber = logWithMetadata.getBlockNumber(); 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 f54b3f0da0..fa75028a38 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 @@ -27,9 +27,24 @@ import java.util.Optional; import graphql.schema.DataFetchingEnvironment; +/** + * This class is an adapter for the BlockWithMetadata class. + * + *

It extends the BlockAdapterBase class and provides methods to get the transaction count, total + * difficulty, ommer count, ommers, transactions, and specific ommer and transaction at a given + * index associated with a block. + */ @SuppressWarnings("unused") // reflected by GraphQL public class NormalBlockAdapter extends BlockAdapterBase { + /** + * Constructor for NormalBlockAdapter. + * + *

It initializes the blockWithMetaData field with the provided argument and calls the parent + * constructor with the header of the provided blockWithMetaData. + * + * @param blockWithMetaData the block with metadata to be adapted. + */ public NormalBlockAdapter( final BlockWithMetadata blockWithMetaData) { super(blockWithMetaData.getHeader()); @@ -38,18 +53,39 @@ public class NormalBlockAdapter extends BlockAdapterBase { private final BlockWithMetadata blockWithMetaData; + /** + * Returns the transaction count of the block. + * + * @return the transaction count of the block. + */ public Optional getTransactionCount() { return Optional.of(blockWithMetaData.getTransactions().size()); } + /** + * Returns the total difficulty of the block. + * + * @return the total difficulty of the block. + */ public Difficulty getTotalDifficulty() { return blockWithMetaData.getTotalDifficulty(); } + /** + * Returns the ommer count of the block. + * + * @return the ommer count of the block. + */ public Optional getOmmerCount() { return Optional.of(blockWithMetaData.getOmmers().size()); } + /** + * Returns the ommers of the block. + * + * @param environment the data fetching environment. + * @return a list of UncleBlockAdapter for the ommers of the block. + */ public List getOmmers(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final List ommers = blockWithMetaData.getOmmers(); @@ -63,6 +99,12 @@ public class NormalBlockAdapter extends BlockAdapterBase { return results; } + /** + * Returns the ommer at a given index of the block. + * + * @param environment the data fetching environment. + * @return an UncleBlockAdapter for the ommer at the given index of the block. + */ public Optional getOmmerAt(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final int index = ((Number) environment.getArgument("index")).intValue(); @@ -75,6 +117,13 @@ public class NormalBlockAdapter extends BlockAdapterBase { return Optional.empty(); } + /** + * Returns a list of TransactionAdapter objects for the transactions in the block. + * + *

Each TransactionAdapter object is created by adapting a TransactionWithMetadata object. + * + * @return a list of TransactionAdapter objects for the transactions in the block. + */ public List getTransactions() { final List trans = blockWithMetaData.getTransactions(); final List results = new ArrayList<>(); @@ -84,6 +133,16 @@ public class NormalBlockAdapter extends BlockAdapterBase { return results; } + /** + * Returns a TransactionAdapter object for the transaction at the given index in the block. + * + *

The index is retrieved from the data fetching environment. If there is no transaction at the + * given index, an empty Optional is returned. + * + * @param environment the data fetching environment. + * @return an Optional containing a TransactionAdapter object for the transaction at the given + * index in the block, or an empty Optional if there is no transaction at the given index. + */ public Optional getTransactionAt(final DataFetchingEnvironment environment) { final int index = ((Number) environment.getArgument("index")).intValue(); final List trans = blockWithMetaData.getTransactions(); 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 0202db88f6..49f6bc890f 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 @@ -36,19 +36,41 @@ import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +/** + * This class represents the pending state of transactions in the Ethereum network. + * + *

It extends the AdapterBase class and provides methods to interact with the transaction pool. + */ @SuppressWarnings("unused") // reflected by GraphQL public class PendingStateAdapter extends AdapterBase { private final TransactionPool transactionPool; + /** + * Constructor for PendingStateAdapter. + * + *

It initializes the transactionPool field with the provided argument. + * + * @param transactionPool the transaction pool to be used. + */ public PendingStateAdapter(final TransactionPool transactionPool) { this.transactionPool = transactionPool; } + /** + * Returns the count of transactions in the transaction pool. + * + * @return the count of transactions in the transaction pool. + */ public Integer getTransactionCount() { return transactionPool.count(); } + /** + * Returns a list of TransactionAdapter objects for the transactions in the transaction pool. + * + * @return a list of TransactionAdapter objects for the transactions in the transaction pool. + */ public List getTransactions() { return transactionPool.getPendingTransactions().stream() .map(PendingTransaction::getTransaction) @@ -57,9 +79,17 @@ public class PendingStateAdapter extends AdapterBase { .toList(); } - // until the miner can expose the current "proposed block" we have no - // speculative environment, so estimate against latest. + /** + * Returns an AccountAdapter object for the account associated with the provided address. + * + *

The account state is estimated against the latest block. + * + * @param dataFetchingEnvironment the data fetching environment. + * @return an AccountAdapter object for the account associated with the provided address. + */ public AccountAdapter getAccount(final DataFetchingEnvironment dataFetchingEnvironment) { + // until the miner can expose the current "proposed block" we have no + // speculative environment, so estimate against latest. final BlockchainQueries blockchainQuery = dataFetchingEnvironment.getGraphQlContext().get(GraphQLContextType.BLOCKCHAIN_QUERIES); final Address addr = dataFetchingEnvironment.getArgument("address"); @@ -71,16 +101,39 @@ public class PendingStateAdapter extends AdapterBase { .orElseGet(() -> new AccountAdapter(null)); } - // until the miner can expose the current "proposed block" we have no - // speculative environment, so estimate against latest. + /** + * Estimates the gas required for a transaction. + * + *

This method calls the getCall method to simulate the transaction and then retrieves the gas + * used by the transaction. The gas estimation is done against the latest block as there is + * currently no way to expose the current "proposed block" for a speculative environment. + * + * @param environment the data fetching environment. + * @return an Optional containing the estimated gas for the transaction, or an empty Optional if + * the transaction simulation was not successful. + */ public Optional getEstimateGas(final DataFetchingEnvironment environment) { + // until the miner can expose the current "proposed block" we have no + // speculative environment, so estimate against latest. final Optional result = getCall(environment); return result.map(CallResult::getGasUsed); } - // until the miner can expose the current "proposed block" we have no - // speculative environment, so estimate against latest. + /** + * Simulates the execution of a transaction. + * + *

This method retrieves the transaction parameters from the data fetching environment, creates + * a CallParameter object, and then uses a TransactionSimulator to simulate the execution of the + * transaction. The simulation is done against the latest block as there is currently no way to + * expose the current "proposed block" for a speculative environment. + * + * @param environment the data fetching environment. + * @return an Optional containing the result of the transaction simulation, or an empty Optional + * if the transaction simulation was not successful. + */ public Optional getCall(final DataFetchingEnvironment environment) { + // until the miner can expose the current "proposed block" we have no + // speculative environment, so estimate against latest. final Map callData = environment.getArgument("data"); final Address from = (Address) callData.get("from"); final Address to = (Address) callData.get("to"); 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 0a8dcbbf97..2c3876fe36 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,22 +16,52 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter; import org.hyperledger.besu.plugin.data.SyncStatus; +/** + * The SyncStateAdapter class provides methods to retrieve the synchronization status of the + * blockchain. + * + *

This class is used to adapt a SyncStatus object into a format that can be used by GraphQL. The + * SyncStatus object is provided at construction time. + * + *

The class provides methods to retrieve the starting block, current block, and highest block of + * the synchronization status. + */ @SuppressWarnings("unused") // reflected by GraphQL public class SyncStateAdapter { private final SyncStatus syncStatus; + /** + * Constructs a new SyncStateAdapter object. + * + * @param syncStatus the SyncStatus object to adapt. + */ public SyncStateAdapter(final SyncStatus syncStatus) { this.syncStatus = syncStatus; } + /** + * Returns the starting block of the synchronization status. + * + * @return the starting block of the synchronization status. + */ public Long getStartingBlock() { return syncStatus.getStartingBlock(); } + /** + * Returns the current block of the synchronization status. + * + * @return the current block of the synchronization status. + */ public Long getCurrentBlock() { return syncStatus.getCurrentBlock(); } + /** + * Returns the highest block of the synchronization status. + * + * @return the highest block of the synchronization status. + */ 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 6e98afc90e..d5eacf8e35 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 @@ -38,11 +38,28 @@ import javax.annotation.Nonnull; import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; +/** + * The TransactionAdapter class provides methods to retrieve the transaction details. + * + *

This class is used to adapt a TransactionWithMetadata object into a format that can be used by + * GraphQL. The TransactionWithMetadata object is provided at construction time. + * + *

The class provides methods to retrieve the hash, type, nonce, index, from, to, value, gas + * price, max fee per gas, max priority fee per gas, max fee per blob gas, effective tip, gas, input + * data, block, status, gas used, cumulative gas used, effective gas price, blob gas used, blob gas + * price, created contract, logs, R, S, V, Y parity, access list, raw, raw receipt, and blob + * versioned hashes of the transaction. + */ @SuppressWarnings("unused") // reflected by GraphQL public class TransactionAdapter extends AdapterBase { private final TransactionWithMetadata transactionWithMetadata; private Optional transactionReceiptWithMetadata; + /** + * Constructs a new TransactionAdapter object. + * + * @param transactionWithMetadata the TransactionWithMetadata object to adapt. + */ public TransactionAdapter(final @Nonnull TransactionWithMetadata transactionWithMetadata) { this.transactionWithMetadata = transactionWithMetadata; } @@ -65,22 +82,53 @@ public class TransactionAdapter extends AdapterBase { return transactionReceiptWithMetadata; } + /** + * Returns the hash of the transaction. + * + * @return the hash of the transaction. + */ public Hash getHash() { return transactionWithMetadata.getTransaction().getHash(); } + /** + * Returns the type of the transaction. + * + * @return the type of the transaction. + */ public Optional getType() { return Optional.of(transactionWithMetadata.getTransaction().getType().ordinal()); } + /** + * Returns the nonce of the transaction. + * + * @return the nonce of the transaction. + */ public Long getNonce() { return transactionWithMetadata.getTransaction().getNonce(); } + /** + * Returns the index of the transaction. + * + * @return the index of the transaction. + */ public Optional getIndex() { return transactionWithMetadata.getTransactionIndex(); } + /** + * Retrieves the sender of the transaction. + * + *

This method uses the BlockchainQueries to get the block number and then retrieves the sender + * of the transaction. It then uses the getAndMapWorldState method to get the state of the + * sender's account at the given block number. + * + * @param environment the data fetching environment. + * @return an AccountAdapter object representing the sender's account state at the given block + * number. + */ public AccountAdapter getFrom(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Long blockNumber = @@ -96,6 +144,18 @@ public class TransactionAdapter extends AdapterBase { .orElse(new EmptyAccountAdapter(addr)); } + /** + * Retrieves the recipient of the transaction. + * + *

This method uses the BlockchainQueries to get the block number and then retrieves the + * recipient of the transaction. It then uses the getAndMapWorldState method to get the state of + * the recipient's account at the given block number. + * + * @param environment the data fetching environment. + * @return an Optional containing an AccountAdapter object representing the recipient's account + * state at the given block number, or an empty Optional if the transaction does not have a + * recipient (i.e., it is a contract creation transaction). + */ public Optional getTo(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Long blockNumber = @@ -115,39 +175,95 @@ public class TransactionAdapter extends AdapterBase { .or(() -> Optional.of(new EmptyAccountAdapter(address)))); } + /** + * Retrieves the value of the transaction. + * + * @return a Wei object representing the value of the transaction. + */ public Wei getValue() { return transactionWithMetadata.getTransaction().getValue(); } + /** + * Retrieves the gas price of the transaction. + * + * @return a Wei object representing the gas price of the transaction. If the transaction does not + * specify a gas price, this method returns zero. + */ public Wei getGasPrice() { return transactionWithMetadata.getTransaction().getGasPrice().orElse(Wei.ZERO); } + /** + * Retrieves the maximum fee per gas of the transaction. + * + * @return an Optional containing a Wei object representing the maximum fee per gas of the + * transaction, or an empty Optional if the transaction does not specify a maximum fee per + * gas. + */ public Optional getMaxFeePerGas() { return transactionWithMetadata.getTransaction().getMaxFeePerGas(); } + /** + * Retrieves the maximum priority fee per gas of the transaction. + * + * @return an Optional containing a Wei object representing the maximum priority fee per gas of + * the transaction, or an empty Optional if the transaction does not specify a maximum + * priority fee per gas. + */ public Optional getMaxPriorityFeePerGas() { return transactionWithMetadata.getTransaction().getMaxPriorityFeePerGas(); } + /** + * Retrieves the maximum fee per blob gas of the transaction. + * + * @return an Optional containing a Wei object representing the maximum fee per blob gas of the + * transaction, or an empty Optional if the transaction does not specify a maximum fee per + * blob gas. + */ public Optional getMaxFeePerBlobGas() { return transactionWithMetadata.getTransaction().getMaxFeePerBlobGas(); } + /** + * Retrieves the effective tip of the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Wei object representing the effective tip of the transaction, + * or an empty Optional if the transaction does not specify an effective tip. + */ public Optional getEffectiveTip(final DataFetchingEnvironment environment) { return getReceipt(environment) .map(rwm -> rwm.getTransaction().getEffectivePriorityFeePerGas(rwm.getBaseFee())); } + /** + * Retrieves the gas limit of the transaction. + * + * @return a Long object representing the gas limit of the transaction. + */ public Long getGas() { return transactionWithMetadata.getTransaction().getGasLimit(); } + /** + * Retrieves the input data of the transaction. + * + * @return a Bytes object representing the input data of the transaction. + */ public Bytes getInputData() { return transactionWithMetadata.getTransaction().getPayload(); } + /** + * Retrieves the block of the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a NormalBlockAdapter object representing the block of the + * transaction, or an empty Optional if the transaction does not specify a block. + */ public Optional getBlock(final DataFetchingEnvironment environment) { return transactionWithMetadata .getBlockHash() @@ -155,6 +271,17 @@ public class TransactionAdapter extends AdapterBase { .map(NormalBlockAdapter::new); } + /** + * Retrieves the status of the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then checks + * the status of the receipt. If the status is -1, it returns an empty Optional. Otherwise, it + * returns an Optional containing the status of the receipt. + * + * @param environment the data fetching environment. + * @return an Optional containing a Long object representing the status of the transaction, or an + * empty Optional if the status of the receipt is -1. + */ public Optional getStatus(final DataFetchingEnvironment environment) { return getReceipt(environment) .map(TransactionReceiptWithMetadata::getReceipt) @@ -165,27 +292,87 @@ public class TransactionAdapter extends AdapterBase { : Optional.of((long) receipt.getStatus())); } + /** + * Retrieves the gas used by the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then + * returns an Optional containing the gas used by the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Long object representing the gas used by the transaction. + */ public Optional getGasUsed(final DataFetchingEnvironment environment) { return getReceipt(environment).map(TransactionReceiptWithMetadata::getGasUsed); } + /** + * Retrieves the cumulative gas used by the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then + * returns an Optional containing the cumulative gas used by the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Long object representing the cumulative gas used by the + * transaction. + */ public Optional getCumulativeGasUsed(final DataFetchingEnvironment environment) { return getReceipt(environment).map(rpt -> rpt.getReceipt().getCumulativeGasUsed()); } + /** + * Retrieves the effective gas price of the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then + * returns an Optional containing the effective gas price of the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Wei object representing the effective gas price of the + * transaction. + */ public Optional getEffectiveGasPrice(final DataFetchingEnvironment environment) { return getReceipt(environment) .map(rwm -> rwm.getTransaction().getEffectiveGasPrice(rwm.getBaseFee())); } + /** + * Retrieves the blob gas used by the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then + * returns an Optional containing the blob gas used by the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Long object representing the blob gas used by the transaction. + */ public Optional getBlobGasUsed(final DataFetchingEnvironment environment) { return getReceipt(environment).flatMap(TransactionReceiptWithMetadata::getBlobGasUsed); } + /** + * Retrieves the blob gas price of the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then + * returns an Optional containing the blob gas price of the transaction. + * + * @param environment the data fetching environment. + * @return an Optional containing a Wei object representing the blob gas price of the transaction. + */ public Optional getBlobGasPrice(final DataFetchingEnvironment environment) { return getReceipt(environment).flatMap(TransactionReceiptWithMetadata::getBlobGasPrice); } + /** + * Retrieves the contract created by the transaction. + * + *

This method checks if the transaction is a contract creation transaction. If it is, it + * retrieves the address of the created contract. It then uses the BlockchainQueries to get the + * block number and then retrieves the state of the created contract's account at the given block + * number. + * + * @param environment the data fetching environment. + * @return an Optional containing an AccountAdapter object representing the created contract's + * account state at the given block number, or an empty Optional if the transaction is not a + * contract creation transaction or if the block number is not specified. + */ public Optional getCreatedContract(final DataFetchingEnvironment environment) { final boolean contractCreated = transactionWithMetadata.getTransaction().isContractCreation(); if (contractCreated) { @@ -208,6 +395,17 @@ public class TransactionAdapter extends AdapterBase { return Optional.empty(); } + /** + * Retrieves the logs of the transaction. + * + *

This method uses the BlockchainQueries to get the block header and the receipt of the + * transaction. It then retrieves the logs of the transaction and adapts them into a format that + * can be used by GraphQL. + * + * @param environment the data fetching environment. + * @return a List of LogAdapter objects representing the logs of the transaction. If the + * transaction does not have a receipt, this method returns an empty list. + */ public List getLogs(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final ProtocolSchedule protocolSchedule = @@ -240,14 +438,34 @@ public class TransactionAdapter extends AdapterBase { return results; } + /** + * Retrieves the R component of the transaction's signature. + * + * @return a BigInteger object representing the R component of the transaction's signature. + */ public BigInteger getR() { return transactionWithMetadata.getTransaction().getR(); } + /** + * Retrieves the S component of the transaction's signature. + * + * @return a BigInteger object representing the S component of the transaction's signature. + */ public BigInteger getS() { return transactionWithMetadata.getTransaction().getS(); } + /** + * Retrieves the V component of the transaction's signature. + * + *

If the transaction type is less than the BLOB transaction type and V is null, it returns the + * Y parity of the transaction. Otherwise, it returns V. + * + * @return an Optional containing a BigInteger object representing the V component of the + * transaction's signature, or an Optional containing the Y parity of the transaction if V is + * null and the transaction type is less than the BLOB transaction type. + */ public Optional getV() { BigInteger v = transactionWithMetadata.getTransaction().getV(); return Optional.ofNullable( @@ -258,10 +476,22 @@ public class TransactionAdapter extends AdapterBase { : v); } + /** + * Retrieves the Y parity of the transaction's signature. + * + * @return an Optional containing a BigInteger object representing the Y parity of the + * transaction's signature. + */ public Optional getYParity() { return Optional.ofNullable(transactionWithMetadata.getTransaction().getYParity()); } + /** + * Retrieves the access list of the transaction. + * + * @return a List of AccessListEntryAdapter objects representing the access list of the + * transaction. + */ public List getAccessList() { return transactionWithMetadata .getTransaction() @@ -270,12 +500,30 @@ public class TransactionAdapter extends AdapterBase { .orElse(List.of()); } + /** + * Retrieves the raw transaction data. + * + *

This method uses the writeTo method of the transaction to write the transaction data to a + * BytesValueRLPOutput object. It then encodes the BytesValueRLPOutput object and returns it. + * + * @return an Optional containing a Bytes object representing the raw transaction data. + */ public Optional getRaw() { final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); transactionWithMetadata.getTransaction().writeTo(rlpOutput); return Optional.of(rlpOutput.encoded()); } + /** + * Retrieves the raw receipt of the transaction. + * + *

This method uses the getReceipt method to get the receipt of the transaction. It then writes + * the receipt data to a BytesValueRLPOutput object using the writeToForNetwork method of the + * receipt. It then encodes the BytesValueRLPOutput object and returns it. + * + * @param environment the data fetching environment. + * @return an Optional containing a Bytes object representing the raw receipt of the transaction. + */ public Optional getRawReceipt(final DataFetchingEnvironment environment) { return getReceipt(environment) .map( @@ -286,6 +534,11 @@ public class TransactionAdapter extends AdapterBase { }); } + /** + * Retrieves the versioned hashes of the transaction. + * + * @return a List of VersionedHash objects representing the versioned hashes of the transaction. + */ public List getBlobVersionedHashes() { return transactionWithMetadata.getTransaction().getVersionedHashes().orElse(List.of()); } 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 index e8454fcdb5..85ec69b0dd 100644 --- 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 @@ -17,26 +17,60 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.plugin.data.Withdrawal; +/** + * The WithdrawalAdapter class provides methods to retrieve the withdrawal details. + * + *

This class is used to adapt a Withdrawal object into a format that can be used by GraphQL. The + * Withdrawal object is provided at construction time. + * + *

The class provides methods to retrieve the index, validator, address, and amount of the + * withdrawal. + */ public class WithdrawalAdapter { Withdrawal withdrawal; + /** + * Constructs a new WithdrawalAdapter object. + * + * @param withdrawal the Withdrawal object to adapt. + */ public WithdrawalAdapter(final Withdrawal withdrawal) { this.withdrawal = withdrawal; } + /** + * Returns the index of the withdrawal. + * + * @return the index of the withdrawal. + */ public Long getIndex() { return withdrawal.getIndex().toLong(); } + /** + * Returns the validator of the withdrawal. + * + * @return the validator of the withdrawal. + */ public Long getValidator() { return withdrawal.getValidatorIndex().toLong(); } + /** + * Returns the address of the withdrawal. + * + * @return the address of the withdrawal. + */ public Address getAddress() { return withdrawal.getAddress(); } + /** + * Returns the amount of the withdrawal. + * + * @return the amount of the withdrawal. + */ public Long getAmount() { return withdrawal.getAmount().getAsBigInteger().longValue(); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLError.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLError.java index e4aeacd92f..f370df8dcf 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLError.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLError.java @@ -19,30 +19,96 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonGetter; +/** + * Enum representing various types of GraphQL errors. + * + *

Each error is associated with a specific code and message. The code is an integer that + * uniquely identifies the error. The message is a string that provides a human-readable description + * of the error. + * + *

This enum includes standard errors such as INVALID_PARAMS and INTERNAL_ERROR, transaction + * validation failures such as NONCE_TOO_LOW and INVALID_TRANSACTION_SIGNATURE, and private + * transaction errors such as PRIVATE_TRANSACTION_FAILED and PRIVATE_NONCE_TOO_LOW. + * + *

The {@code of} method is used to map a {@code TransactionInvalidReason} to a corresponding + * {@code GraphQLError}. + */ @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum GraphQLError { // Standard errors + /** Error code -32602. This error occurs when the parameters provided are invalid. */ INVALID_PARAMS(-32602, "Invalid params"), + + /** Error code -32603. This error occurs when there is an internal error. */ INTERNAL_ERROR(-32603, "Internal error"), // Transaction validation failures + /** Error code -32001. This error occurs when the nonce value is too low. */ NONCE_TOO_LOW(-32001, "Nonce too low"), + + /** Error code -32002. This error occurs when the transaction signature is invalid. */ INVALID_TRANSACTION_SIGNATURE(-32002, "Invalid signature"), + + /** Error code -32003. This error occurs when the intrinsic gas exceeds the gas limit. */ INTRINSIC_GAS_EXCEEDS_LIMIT(-32003, "Intrinsic gas exceeds gas limit"), + + /** + * Error code -32004. This error occurs when the upfront cost of the transaction exceeds the + * account balance. + */ TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE(-32004, "Upfront cost exceeds account balance"), + + /** + * Error code -32005. This error occurs when the transaction gas limit exceeds the block gas + * limit. + */ EXCEEDS_BLOCK_GAS_LIMIT(-32005, "Transaction gas limit exceeds block gas limit"), + + /** Error code -32006. This error occurs when the nonce value is too high. */ INCORRECT_NONCE(-32006, "Nonce too high"), + + /** + * Error code -32007. This error occurs when the sender account is not authorized to send + * transactions. + */ TX_SENDER_NOT_AUTHORIZED(-32007, "Sender account not authorized to send transactions"), + + /** Error code -32008. This error occurs when the initial sync is still in progress. */ CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE(-32008, "Initial sync is still in progress"), + + /** + * Error code -32009. This error occurs when the gas price is below the configured minimum gas + * price. + */ GAS_PRICE_TOO_LOW(-32009, "Gas price below configured minimum gas price"), + + /** + * Error code -32000. This error occurs when the Chain ID in the transaction signature is wrong. + */ WRONG_CHAIN_ID(-32000, "Wrong Chain ID in transaction signature"), + + /** + * Error code -32000. This error occurs when signatures with replay protection are not supported. + */ REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED( -32000, "Signatures with replay protection are not supported"), + + /** Error code -32000. This error occurs when the transaction fee cap is exceeded. */ TX_FEECAP_EXCEEDED(-32000, "Transaction fee cap exceeded"), // Private Transaction Errors + /** Error code -32000. This error occurs when a private transaction fails. */ PRIVATE_TRANSACTION_FAILED(-32000, "Private transaction failed"), + + /** + * Error code -50100. This error occurs when the nonce value for a private transaction is too low. + */ PRIVATE_NONCE_TOO_LOW(-50100, "Private transaction nonce too low"), + + /** + * Error code -50100. This error occurs when the nonce value for a private transaction is + * incorrect. + */ INCORRECT_PRIVATE_NONCE(-50100, "Private transaction nonce is incorrect"); private final int code; @@ -53,49 +119,52 @@ public enum GraphQLError { this.message = message; } + /** + * Returns the error code associated with this GraphQL error. + * + * @return the error code as an integer. + */ @JsonGetter("code") public int getCode() { return code; } + /** + * Returns the error message associated with this GraphQL error. + * + * @return the error message as a string. + */ @JsonGetter("message") public String getMessage() { return message; } + /** + * Maps a {@code TransactionInvalidReason} to a corresponding {@code GraphQLError}. + * + *

This method is used to convert a transaction invalid reason to a GraphQL error, which can be + * used to provide more detailed error information to the client. + * + * @param transactionInvalidReason the transaction invalid reason to be converted. + * @return the corresponding GraphQL error. + */ public static GraphQLError of(final TransactionInvalidReason transactionInvalidReason) { - switch (transactionInvalidReason) { - case WRONG_CHAIN_ID: - return WRONG_CHAIN_ID; - case REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED: - return REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED; - case INVALID_SIGNATURE: - return INVALID_TRANSACTION_SIGNATURE; - case UPFRONT_COST_EXCEEDS_BALANCE: - return TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE; - case NONCE_TOO_LOW: - case PRIVATE_NONCE_TOO_LOW: - return NONCE_TOO_LOW; - case NONCE_TOO_HIGH: - case PRIVATE_NONCE_TOO_HIGH: - return INCORRECT_NONCE; - case INTRINSIC_GAS_EXCEEDS_GAS_LIMIT: - return INTRINSIC_GAS_EXCEEDS_LIMIT; - case EXCEEDS_BLOCK_GAS_LIMIT: - return EXCEEDS_BLOCK_GAS_LIMIT; - case TX_SENDER_NOT_AUTHORIZED: - return TX_SENDER_NOT_AUTHORIZED; - case CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE: - return CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE; + return switch (transactionInvalidReason) { + case WRONG_CHAIN_ID -> WRONG_CHAIN_ID; + case REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED -> REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED; + case INVALID_SIGNATURE -> INVALID_TRANSACTION_SIGNATURE; + case UPFRONT_COST_EXCEEDS_BALANCE -> TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE; + case NONCE_TOO_LOW, PRIVATE_NONCE_TOO_LOW -> NONCE_TOO_LOW; + case NONCE_TOO_HIGH, PRIVATE_NONCE_TOO_HIGH -> INCORRECT_NONCE; + case INTRINSIC_GAS_EXCEEDS_GAS_LIMIT -> INTRINSIC_GAS_EXCEEDS_LIMIT; + case EXCEEDS_BLOCK_GAS_LIMIT -> EXCEEDS_BLOCK_GAS_LIMIT; + case TX_SENDER_NOT_AUTHORIZED -> TX_SENDER_NOT_AUTHORIZED; + case CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE -> CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE; // Private Transaction Invalid Reasons - case PRIVATE_TRANSACTION_FAILED: - return PRIVATE_TRANSACTION_FAILED; - case GAS_PRICE_TOO_LOW: - return GAS_PRICE_TOO_LOW; - case TX_FEECAP_EXCEEDED: - return TX_FEECAP_EXCEEDED; - default: - return INTERNAL_ERROR; - } + case PRIVATE_TRANSACTION_FAILED -> PRIVATE_TRANSACTION_FAILED; + case GAS_PRICE_TOO_LOW -> GAS_PRICE_TOO_LOW; + case TX_FEECAP_EXCEEDED -> TX_FEECAP_EXCEEDED; + default -> INTERNAL_ERROR; + }; } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLErrorResponse.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLErrorResponse.java index faf129311c..8204fad075 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLErrorResponse.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLErrorResponse.java @@ -16,12 +16,26 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.response; import com.fasterxml.jackson.annotation.JsonIgnore; +/** + * Represents a GraphQL error response. This class extends the GraphQLResponse class and overrides + * the getType method to return ERROR. + */ public class GraphQLErrorResponse extends GraphQLResponse { + /** + * Constructs a new GraphQLErrorResponse with the specified errors. + * + * @param errors the errors to be included in the response. + */ public GraphQLErrorResponse(final Object errors) { super(errors); } + /** + * Returns the type of this GraphQL response. + * + * @return GraphQLResponseType.ERROR, indicating that this is an error response. + */ @Override @JsonIgnore public GraphQLResponseType getType() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLJsonRequest.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLJsonRequest.java index 4a0755fad3..899e08a7f0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLJsonRequest.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLJsonRequest.java @@ -19,36 +19,77 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonSetter; +/** + * This class represents a GraphQL JSON request. + * + *

It contains the query, operation name, and variables for a GraphQL request. The query is a + * string that represents the GraphQL query. The operation name is a string that represents the + * operation to be performed. The variables is a map that contains the variables for the GraphQL + * query. + */ public class GraphQLJsonRequest { private String query; private String operationName; private Map variables; + /** Default constructor for GraphQLJsonRequest. */ + public GraphQLJsonRequest() {} + + /** + * Gets the query of the GraphQL request. + * + * @return the query of the GraphQL request. + */ @JsonGetter public String getQuery() { return query; } + /** + * Sets the query of the GraphQL request. + * + * @param query the query of the GraphQL request. + */ @JsonSetter public void setQuery(final String query) { this.query = query; } + /** + * Gets the operation name of the GraphQL request. + * + * @return the operation name of the GraphQL request. + */ @JsonGetter public String getOperationName() { return operationName; } + /** + * Sets the operation name of the GraphQL request. + * + * @param operationName the operation name of the GraphQL request. + */ @JsonSetter public void setOperationName(final String operationName) { this.operationName = operationName; } + /** + * Gets the variables of the GraphQL request. + * + * @return the variables of the GraphQL request. + */ @JsonGetter public Map getVariables() { return variables; } + /** + * Sets the variables of the GraphQL request. + * + * @param variables the variables of the GraphQL request. + */ @JsonSetter public void setVariables(final Map variables) { this.variables = variables; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLNoResponse.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLNoResponse.java index abc0725107..2891ed1922 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLNoResponse.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLNoResponse.java @@ -14,8 +14,20 @@ */ package org.hyperledger.besu.ethereum.api.graphql.internal.response; +/** + * This class represents a GraphQL response with no content. + * + *

It extends the GraphQLResponse class and overrides the getType method to return + * GraphQLResponseType.NONE. + */ public class GraphQLNoResponse extends GraphQLResponse { + /** + * Default constructor for GraphQLNoResponse. + * + *

It calls the parent constructor with null as the argument, indicating no content for this + * response. + */ public GraphQLNoResponse() { super(null); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponse.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponse.java index 21bc17d31a..6612162549 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponse.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponse.java @@ -16,15 +16,35 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.response; import java.util.Objects; +/** + * Represents a GraphQL response. This abstract class provides a structure for different types of + * GraphQL responses. + */ public abstract class GraphQLResponse { - public abstract GraphQLResponseType getType(); private final Object result; + /** + * Constructs a new GraphQLResponse with the specified result. + * + * @param result the result to be included in the response. + */ GraphQLResponse(final Object result) { this.result = result; } + /** + * Returns the type of this GraphQL response. + * + * @return the type of this GraphQL response as a GraphQLResponseType. + */ + public abstract GraphQLResponseType getType(); + + /** + * Returns the result of this GraphQL response. + * + * @return the result of this GraphQL response as an Object. + */ public Object getResult() { return result; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponseType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponseType.java index ddd5170c37..655d5bc11a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponseType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLResponseType.java @@ -16,8 +16,15 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.response; /** Various types of responses that the JSON-RPC component may produce. */ public enum GraphQLResponseType { + /** Represents a response type where there is no content. */ NONE, + + /** Represents a successful response type. */ SUCCESS, + + /** Represents an error response type. */ ERROR, + + /** Represents an unauthorized response type. */ UNAUTHORIZED } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLSuccessResponse.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLSuccessResponse.java index c5a709c37a..0721f7d276 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLSuccessResponse.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/response/GraphQLSuccessResponse.java @@ -16,12 +16,33 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.response; import com.fasterxml.jackson.annotation.JsonIgnore; +/** + * This class represents a successful GraphQL response. + * + *

It extends the GraphQLResponse class and overrides the getType method to return + * GraphQLResponseType.SUCCESS. + */ public class GraphQLSuccessResponse extends GraphQLResponse { + /** + * Constructor for GraphQLSuccessResponse. + * + *

It calls the parent constructor with the provided data as the argument. + * + * @param data the data to be included in the successful response. + */ public GraphQLSuccessResponse(final Object data) { super(data); } + /** + * Returns the type of the GraphQL response. + * + *

This method is overridden to return GraphQLResponseType.SUCCESS, indicating a successful + * response. + * + * @return GraphQLResponseType.SUCCESS + */ @Override @JsonIgnore public GraphQLResponseType getType() { diff --git a/ethereum/mock-p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/testing/MockNetwork.java b/ethereum/mock-p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/testing/MockNetwork.java index b443afe9f9..d7a3c2b506 100644 --- a/ethereum/mock-p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/testing/MockNetwork.java +++ b/ethereum/mock-p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/testing/MockNetwork.java @@ -55,6 +55,11 @@ public final class MockNetwork { private final Map nodes = new HashMap<>(); private final List capabilities; + /** + * Constructs a new MockNetwork with the specified capabilities. + * + * @param capabilities a list of capabilities that the mock network should have. + */ public MockNetwork(final List capabilities) { this.capabilities = capabilities; }