Skip to content
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

chain simulation script #461

Draft
wants to merge 4 commits into
base: v25.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 14 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@
"console": "integratedTerminal",
"justMyCode": true,
"python": "${workspaceFolder}/tests/venv/bin/python3"
}
},
{
"name": "Launch Simulate",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/tests/chainsimulate",
"env": {
"SQS_TOKEN_OUT": "1000uion",
"SQS_TOKEN_IN_DENOM": "uosmo",
"SQS_CHAIN_ADDRESS": "osmo1q8709l2656zjtg567xnrxjr6j35a2pvwhxxms2",
},
"cwd": "${workspaceFolder}"
},
]
}
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ e2e-install-requirements:
e2e-update-requirements:
pip freeze > tests/requirements.txt

e2e-run-chainsimulate:
SQS_TOKEN_OUT=10000uion SQS_TOKEN_IN_DENOM=uosmo SQS_CHAIN_ADDRESS=osmo1q8709l2656zjtg567xnrxjr6j35a2pvwhxxms2 go run tests/chainsimulate/*.go

# Set DATADOG_API_KEY in the environment
datadog-agent-start:
export DATADOG_API_KEY=@@REDACTED@@; \
Expand Down
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"worker-min-pool-liquidity-cap": 1
},
"passthrough":{
"numia-url": "https://public-osmosis-api.numia.xyz",
"numia-url": "https://public-osmosis-api.numia.dev",
"timeseries-url": "https://stage-proxy-data-api.osmosis-labs.workers.dev",
"apr-fetch-interval-minutes": 5,
"pool-fees-fetch-interval-minutes": 5
Expand Down
146 changes: 146 additions & 0 deletions domain/chainsimulate/chain_simulate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package chainsimulatedomain

import (
"context"
"encoding/json"
"io"
"log"
"net"
"net/http"
"strconv"
"time"

"github.com/cosmos/cosmos-sdk/client/tx"
gogogrpc "github.com/cosmos/gogoproto/grpc"
"github.com/cosmos/ibc-go/v7/testing/simapp"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

sdk "github.com/cosmos/cosmos-sdk/types"

txtypes "github.com/cosmos/cosmos-sdk/types/tx"
)

type AccountInfo struct {
Sequence string `json:"sequence"`
AccountNumber string `json:"account_number"`
}

type AccountResult struct {
Account AccountInfo `json:"account"`
}

var client = &http.Client{
Timeout: 10 * time.Second, // Adjusted timeout to 10 seconds
Transport: otelhttp.NewTransport(http.DefaultTransport),
}

const (
chainID = "osmosis-1"
gasAdjustment = 1.02
)

var (
encodingConfig = simapp.MakeTestEncodingConfig()
)

// SimulateMsgs simulates the execution of a transaction and returns the
// simulation response obtained by the query and the adjusted gas amount.
func SimulateMsgs(ctx context.Context, clientCtx gogogrpc.ClientConn, lcd, address string, msgs []sdk.Msg) (*txtypes.SimulateResponse, uint64, error) {
accSeq, accNum := GetInitialSequence(ctx, lcd, address)

txFactory := tx.Factory{}
txFactory = txFactory.WithTxConfig(encodingConfig.TxConfig)
txFactory = txFactory.WithAccountNumber(accNum)
txFactory = txFactory.WithSequence(accSeq)
txFactory = txFactory.WithChainID(chainID)
txFactory = txFactory.WithGasAdjustment(gasAdjustment)

// Estimate transaction
gasResult, adjustedGasUsed, err := CalculateGas(ctx, clientCtx, txFactory, msgs...)
if err != nil {
return nil, adjustedGasUsed, err
}

return gasResult, adjustedGasUsed, nil
}

// CalculateGas simulates the execution of a transaction and returns the
// simulation response obtained by the query and the adjusted gas amount.
func CalculateGas(
ctx context.Context,
clientCtx gogogrpc.ClientConn, txf tx.Factory, msgs ...sdk.Msg,
) (*txtypes.SimulateResponse, uint64, error) {
txBytes, err := txf.BuildSimTx(msgs...)
if err != nil {
return nil, 0, err
}

txSvcClient := txtypes.NewServiceClient(clientCtx)
simRes, err := txSvcClient.Simulate(ctx, &txtypes.SimulateRequest{
TxBytes: txBytes,
})
if err != nil {
return nil, 0, err
}

return simRes, uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed)), nil
}

// GetInitialSequence fetches the initial sequence and account number for a given address
// from the LCD endpoint. It returns the sequence and account number as uint64 values.
func GetInitialSequence(ctx context.Context, lcd string, address string) (uint64, uint64) {
resp, err := httpGet(ctx, lcd+"/cosmos/auth/v1beta1/accounts/"+address)
if err != nil {
log.Printf("Failed to get initial sequence: %v", err)
return 0, 0
}

var accountRes AccountResult
err = json.Unmarshal(resp, &accountRes)
if err != nil {
log.Printf("Failed to unmarshal account result: %v", err)
return 0, 0
}

seqint, err := strconv.ParseUint(accountRes.Account.Sequence, 10, 64)
if err != nil {
log.Printf("Failed to convert sequence to int: %v", err)
return 0, 0
}

accnum, err := strconv.ParseUint(accountRes.Account.AccountNumber, 10, 64)
if err != nil {
log.Printf("Failed to convert account number to int: %v", err)
return 0, 0
}

return seqint, accnum
}

// httpGet performs an HTTP GET request to the specified URL and returns the response body.
func httpGet(ctx context.Context, url string) ([]byte, error) {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}

resp, err := client.Do(req)
if err != nil {
netErr, ok := err.(net.Error)
if ok && netErr.Timeout() {
log.Printf("Request to %s timed out, continuing...", url)
return nil, nil
}
return nil, err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ require (
cosmossdk.io/api v0.3.1
cosmossdk.io/core v0.5.1 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.0 // indirect
cosmossdk.io/tools/rosetta v0.2.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
Expand Down Expand Up @@ -90,7 +90,7 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/gogoproto v1.4.11 // indirect
github.com/cosmos/gogoproto v1.4.11
github.com/cosmos/iavl v1.1.2-0.20240405173644-e52f7630d3b7 // indirect
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 // indirect
github.com/cosmos/ibc-apps/modules/async-icq/v7 v7.1.1 // indirect
Expand Down Expand Up @@ -218,7 +218,7 @@ require (
go.etcd.io/bbolt v1.3.8 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0
go.uber.org/multierr v1.11.0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/sqs/domain"
chainsimulatedomain "github.com/osmosis-labs/sqs/domain/chainsimulate"
"github.com/osmosis-labs/sqs/domain/keyring"
"github.com/osmosis-labs/sqs/domain/mvc"
orderbookplugindomain "github.com/osmosis-labs/sqs/domain/orderbook/plugin"
Expand Down Expand Up @@ -344,7 +345,7 @@ func (o *orderbookFillerIngestPlugin) tryFill(ctx blockctx.BlockCtxI) error {

// Simulate transaction messages
sdkMsgs := txCtx.GetSDKMsgs()
_, adjustedGasAmount, err := o.simulateMsgs(ctx.AsGoCtx(), sdkMsgs)
_, adjustedGasAmount, err := chainsimulatedomain.SimulateMsgs(ctx.AsGoCtx(), o.passthroughGRPCClient.GetChainGRPCClient(), LCD, o.keyring.GetAddress().String(), sdkMsgs)
if err != nil {
return err
}
Expand Down
Loading
Loading