Skip to content

[RelayMiner] Use gas for claim and proof txs #1018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 2 additions & 60 deletions e2e/tests/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package e2e
import (
"bytes"
"fmt"
"net"
"net/url"
"os"
"os/exec"
Expand All @@ -26,11 +25,6 @@ var (
defaultHome = os.Getenv("POKTROLLD_HOME")
// defaultPathURL used by curl commands to send relay requests
defaultPathURL = os.Getenv("PATH_URL")
// defaultPathHostOverride overrides the host in the URL used to send requests
// Since the current DevNet infrastructure does not support arbitrary subdomains,
// this is used to specify the host to connect to and the full host (with the service as a subdomain)
// will be sent in the "Host" request header.
defaultPathHostOverride = os.Getenv("PATH_HOST_OVERRIDE")
// defaultDebugOutput provides verbose output on manipulations with binaries (cli command, stdout, stderr)
defaultDebugOutput = os.Getenv("E2E_DEBUG_OUTPUT")
)
Expand Down Expand Up @@ -189,22 +183,6 @@ func (p *pocketdBin) runCurlCmd(rpcBaseURL, service, method, path, appAddr, data
return nil, err
}

// Get the virtual host that will be sent in the "Host" request header
virtualHost := getVirtualHostFromUrlForService(rpcUrl, service)

// TODO_HACK: As of PR #879, the DevNet infrastructure does not support routing
// requests to arbitrary subdomains due to TLS certificate-related complexities.
// In such environment, defaultPathHostOverride (which contains no subdomain)
// is used as:
// 1. The gateway's 'host:port' to connect to
// 2. A base to which the service is added as a subdomain then set as the "Host" request header.
// (i.e. Host: <service>.<defaultPathHostOverride>)
//
// Override the actual connection address if the environment requires it.
if defaultPathHostOverride != "" {
rpcUrl.Host = defaultPathHostOverride
}

// Ensure that if a path is provided, it starts with a "/".
// This is required for RESTful APIs that use a path to identify resources.
// For JSON-RPC APIs, the resource path should be empty, so empty paths are allowed.
Expand All @@ -225,8 +203,9 @@ func (p *pocketdBin) runCurlCmd(rpcBaseURL, service, method, path, appAddr, data
"-v", // verbose output
"-sS", // silent with error
"-H", `Content-Type: application/json`, // HTTP headers
"-H", fmt.Sprintf("Host: %s", virtualHost), // Add virtual host header
"-H", fmt.Sprintf("Host: %s", rpcUrl.Host), // Add virtual host header
"-H", fmt.Sprintf("X-App-Address: %s", appAddr),
"-H", fmt.Sprintf("target-service-id: %s", service),
rpcUrl.String(),
}

Expand Down Expand Up @@ -262,40 +241,3 @@ func (p *pocketdBin) runCurlCmd(rpcBaseURL, service, method, path, appAddr, data

return r, err
}

// formatURLString returns RESTful or JSON-RPC API endpoint URL depending
// on the parameters provided.
func formatURLString(serviceAlias, rpcUrl, path string) string {
// For JSON-RPC APIs, the path should be empty
if len(path) == 0 {
return fmt.Sprintf("http://%s.%s/v1", serviceAlias, rpcUrl)
}

// For RESTful APIs, the path should not be empty.
// We remove the leading / to make the format string below easier to read.
if path[0] == '/' {
path = path[1:]
}
return fmt.Sprintf("http://%s.%s/v1/%s", serviceAlias, rpcUrl, path)
}

// getVirtualHostFromUrlForService returns a virtual host taking into consideration
// the URL's host and the service if it's non-empty.
// Specifically, it:
// 1. Extract's the host from the rpcURL
// 2. Prefixes the service as a subdomain to (1) the given rpcUrl host stripped of the port
//
// TODO_HACK: This is needed as of PR #879 because the DevNet infrastructure does
// not support arbitrary subdomains due to TLS certificate-related complexities.
func getVirtualHostFromUrlForService(rpcUrl *url.URL, service string) string {
// Strip port if it exists and add service prefix
host, _, err := net.SplitHostPort(rpcUrl.Host)
if err != nil {
// err is non-nil if rpcUrl.Host does not have a port.
// Use the entire host as is
host = rpcUrl.Host
}
virtualHost := fmt.Sprintf("%s.%s", service, host)

return virtualHost
}
4 changes: 2 additions & 2 deletions makefiles/relay.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
send_relay_path_JSONRPC: test_e2e_env ## Send a JSONRPC relay through PATH to a local anvil (test ETH) node
curl -X POST -H "Content-Type: application/json" \
-H "X-App-Address: pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4" \
-H "target-service-id: anvil" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://anvil.localhost:3000/v1
# $(subst http://,http://anvil.,$(PATH_URL))/v1
http://localhost:3000/v1/

# TODO_MAINNET(@red-0ne): Re-enable this once PATH Gateway supports REST.
# See https://github.com/buildwithgrove/path/issues/87
Expand Down
7 changes: 7 additions & 0 deletions pkg/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ type TxContext interface {

// GetClientCtx returns the cosmos-sdk client context associated with the transaction context.
GetClientCtx() cosmosclient.Context

// GetSimulatedTxGas returns the estimated gas for the given messages.
GetSimulatedTxGas(
ctx context.Context,
signingKeyName string,
msgs ...cosmostypes.Msg,
) (uint64, error)
}

// Block is an interface which abstracts the details of a block to its minimal
Expand Down
9 changes: 7 additions & 2 deletions pkg/client/tx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ func (txnClient *txClient) SignAndBroadcast(
return either.SyncErr(validationErrs)
}

// Simulate the transaction to calculate the gas limit.
gasLimit, simErr := txnClient.txCtx.GetSimulatedTxGas(ctx, txnClient.signingKeyName, msgs...)
if simErr != nil {
return either.SyncErr(simErr)
}

// Construct the transactions using cosmos' transactions builder.
txBuilder := txnClient.txCtx.NewTxBuilder()
if err := txBuilder.SetMsgs(msgs...); err != nil {
Expand All @@ -240,8 +246,7 @@ func (txnClient *txClient) SignAndBroadcast(
timeoutHeight := txnClient.blockClient.LastBlock(ctx).
Height() + txnClient.commitTimeoutHeightOffset

// TODO_TECHDEBT: this should be configurable
txBuilder.SetGasLimit(690000042)
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetTimeoutHeight(uint64(timeoutHeight))

// sign transactions
Expand Down
40 changes: 39 additions & 1 deletion pkg/client/tx/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ func (txCtx cosmosTxContext) EncodeTx(txBuilder cosmosclient.TxBuilder) ([]byte,
// ABCI operation completes and returns a TxResponse of the transaction status at that point in time.
func (txCtx cosmosTxContext) BroadcastTx(txBytes []byte) (*cosmostypes.TxResponse, error) {
clientCtx := cosmosclient.Context(txCtx.clientCtx)
return clientCtx.BroadcastTxAsync(txBytes)
// BroadcastTxSync is used to capture any transaction error that occurs during
// the check-tx ABCI operation, otherwise errors would be returned.
return clientCtx.BroadcastTxSync(txBytes)
}

// QueryTx queries the transaction based on its hash and optionally provides proof
Expand All @@ -103,3 +105,39 @@ func (txCtx cosmosTxContext) QueryTx(
func (txCtx cosmosTxContext) GetClientCtx() cosmosclient.Context {
return cosmosclient.Context(txCtx.clientCtx)
}

// GetSimulatedTxGas calculates the gas for the given messages using the simulation mode.
func (txCtx cosmosTxContext) GetSimulatedTxGas(
ctx context.Context,
signingKeyName string,
msgs ...cosmostypes.Msg,
) (uint64, error) {
clientCtx := cosmosclient.Context(txCtx.clientCtx)
keyRecord, err := txCtx.GetKeyring().Key(signingKeyName)
if err != nil {
return 0, err
}

accAddress, err := keyRecord.GetAddress()
if err != nil {
return 0, err
}

accountRetriever := txCtx.clientCtx.AccountRetriever
_, seq, err := accountRetriever.GetAccountNumberSequence(clientCtx, accAddress)
if err != nil {
return 0, err
}

txf := txCtx.txFactory.
WithSimulateAndExecute(true).
WithFromName(signingKeyName).
WithSequence(seq)

_, gas, err := cosmostx.CalculateGas(txCtx.GetClientCtx(), txf, msgs...)
if err != nil {
return 0, err
}

return gas, nil
}
3 changes: 3 additions & 0 deletions pkg/relayer/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ for such operations.`,
cmd.Flags().Bool(cosmosflags.FlagGRPCInsecure, true, "Used to initialize the Cosmos query context with grpc security options. It can be used to override the `QueryNodeGRPCInsecure` field in the config file if specified.")
cmd.Flags().String(cosmosflags.FlagChainID, "poktroll", "The network chain ID")
cmd.Flags().StringVar(&flagLogLevel, cosmosflags.FlagLogLevel, "debug", "The logging level (debug|info|warn|error)")
cmd.Flags().Float64(cosmosflags.FlagGasAdjustment, 1.5, "The adjustment factor to be multiplied by the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored")
cmd.Flags().String(cosmosflags.FlagGasPrices, "0.0001upokt", "Set the gas prices in upokt")
cmd.Flags().String(cosmosflags.FlagGas, cosmosflags.GasFlagAuto, fmt.Sprintf("gas limit to set per-transaction; set to auto to calculate sufficient gas automatically. Note: %q option doesn't always report accurate results - can adjust %q to allow more room for error in the simulation", cosmosflags.GasFlagAuto, cosmosflags.FlagGasAdjustment))

return cmd
}
Expand Down
4 changes: 4 additions & 0 deletions testutil/testclient/testtx/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ func NewOneTimeErrTxTimeoutTxContext(
},
).Times(1)

txCtxMock.EXPECT().GetSimulatedTxGas(gomock.Any(), gomock.Any(), gomock.Any()).
Return(uint64(0), nil).
Times(1)

txCtxMock.EXPECT().QueryTx(
gomock.AssignableToTypeOf(context.Background()),
gomock.AssignableToTypeOf([]byte{}),
Expand Down
Loading