Skip to content

Commit

Permalink
dry run
Browse files Browse the repository at this point in the history
  • Loading branch information
mmsqe committed Jun 3, 2024
1 parent 7c6a10d commit 4344f05
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 87 deletions.
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,8 @@ func New(
tracer,
evmS,
[]evmkeeper.CustomContractFn{
func(_ sdk.Context, rules ethparams.Rules) vm.PrecompiledContract {
return cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec, rules, app.Logger())
func(ctx sdk.Context, rules ethparams.Rules) vm.PrecompiledContract {
return cronosprecompiles.NewRelayerContract(ctx, txConfig, app.IBCKeeper, app.Simulate, appCodec, rules, app.Logger())
},
func(ctx sdk.Context, rules ethparams.Rules) vm.PrecompiledContract {
return cronosprecompiles.NewIcaContract(ctx, &app.ICAAuthKeeper, &app.CronosKeeper, appCodec, gasConfig)
Expand Down
202 changes: 120 additions & 82 deletions x/cronos/keeper/precompiles/relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import (

"cosmossdk.io/log"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/gogoproto/proto"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
Expand All @@ -24,7 +29,6 @@ var (
irelayerABI abi.ABI
relayerContractAddress = common.BytesToAddress([]byte{101})
relayerMethodNamedByMethod = map[[4]byte]string{}
relayerGasRequiredByMethod = map[[4]byte]uint64{}
)

const (
Expand All @@ -46,72 +50,37 @@ const (
Acknowledgement = "acknowledgement"
Timeout = "timeout"
TimeoutOnClose = "timeoutOnClose"

GasWhenReceiverChainIsSource = 121578
GasWhenReceiverChainIsNotSource = 215038
AnteCost = 69843
)

func init() {
if err := irelayerABI.UnmarshalJSON([]byte(relayer.RelayerFunctionsMetaData.ABI)); err != nil {
panic(err)
}
for methodName := range irelayerABI.Methods {
var methodID [4]byte
copy(methodID[:], irelayerABI.Methods[methodName].ID[:4])
switch methodName {
case CreateClient:
relayerGasRequiredByMethod[methodID] = 114990
case UpdateClient:
relayerGasRequiredByMethod[methodID] = 109689
case UpgradeClient:
relayerGasRequiredByMethod[methodID] = 400000
case ConnectionOpenInit:
relayerGasRequiredByMethod[methodID] = 89589
case ConnectionOpenTry:
relayerGasRequiredByMethod[methodID] = 108323
case ConnectionOpenAck:
relayerGasRequiredByMethod[methodID] = 99446
case ConnectionOpenConfirm:
relayerGasRequiredByMethod[methodID] = 82735
case ChannelOpenInit:
relayerGasRequiredByMethod[methodID] = 138568
case ChannelOpenTry:
relayerGasRequiredByMethod[methodID] = 140432
case ChannelOpenAck:
relayerGasRequiredByMethod[methodID] = 92000
case ChannelOpenConfirm:
relayerGasRequiredByMethod[methodID] = 91060
case ChannelCloseConfirm:
relayerGasRequiredByMethod[methodID] = 101072
case RecvPacket:
relayerGasRequiredByMethod[methodID] = GasWhenReceiverChainIsNotSource
case Acknowledgement:
relayerGasRequiredByMethod[methodID] = 131657
case Timeout:
relayerGasRequiredByMethod[methodID] = 174147
default:
relayerGasRequiredByMethod[methodID] = 100000
}
relayerMethodNamedByMethod[methodID] = methodName
}
}

type SimulateFn func(txBytes []byte) (sdk.GasInfo, *sdk.Result, error)

type RelayerContract struct {
BaseContract

ctx sdk.Context
cdc codec.Codec
txConfig client.TxConfig
ibcKeeper types.IbcKeeper
simulate SimulateFn
logger log.Logger
isHomestead bool
isIstanbul bool
isShanghai bool
}

func NewRelayerContract(ibcKeeper types.IbcKeeper, cdc codec.Codec, rules params.Rules, logger log.Logger) vm.PrecompiledContract {
func NewRelayerContract(ctx sdk.Context, txConfig client.TxConfig, ibcKeeper types.IbcKeeper, simulate SimulateFn, cdc codec.Codec, rules params.Rules, logger log.Logger) vm.PrecompiledContract {
return &RelayerContract{
BaseContract: NewBaseContract(relayerContractAddress),
ctx: ctx,
txConfig: txConfig,
ibcKeeper: ibcKeeper,
simulate: simulate,
cdc: cdc,
isHomestead: rules.IsHomestead,
isIstanbul: rules.IsIstanbul,
Expand Down Expand Up @@ -144,59 +113,128 @@ func unpackInput(input []byte) ([][]byte, abi.Type, error) {
// RequiredGas calculates the contract gas use
// `max(0, len(input) * DefaultTxSizeCostPerByte + requiredGasTable[methodPrefix] - intrinsicGas)`
func (bc *RelayerContract) RequiredGas(input []byte) (finalGas uint64) {
baseCost := uint64(15500)
inputs, _, err := unpackInput(input)

Check warning on line 117 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L115-L117

Added lines #L115 - L117 were not covered by tests
if err != nil {
panic(err)
}

for i, input := range inputs {
// base cost to prevent large input size
inputLen := len(input)
baseCost := uint64(inputLen) * authtypes.DefaultTxSizeCostPerByte
var msgs []proto.Message
var signer sdk.AccAddress
intrinsicGasTotal := uint64(0)
for _, input := range inputs {
var methodID [4]byte
copy(methodID[:], input[:4])
requiredGas, ok := relayerGasRequiredByMethod[methodID]
method, err := irelayerABI.MethodById(methodID[:])
if err != nil {
panic(err)

Check warning on line 130 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L122-L130

Added lines #L122 - L130 were not covered by tests
}
if method.Name == RecvPacket {
args, err := method.Inputs.Unpack(input[4:])
if err != nil {
panic(err)
}
i := args[0].([]byte)
var msg channeltypes.MsgRecvPacket
if err = bc.cdc.Unmarshal(i, &msg); err != nil {
panic(err)
}
var data ibctransfertypes.FungibleTokenPacketData
if err = ibctransfertypes.ModuleCdc.UnmarshalJSON(msg.Packet.GetData(), &data); err != nil {
panic(err)
}
if ibctransfertypes.ReceiverChainIsSource(msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), data.Denom) {
requiredGas = GasWhenReceiverChainIsSource
}
args, err := method.Inputs.Unpack(input[4:])
if err != nil {
panic(err)
}
if i > 0 {
requiredGas -= AnteCost
i := args[0].([]byte)

e := &Executor{
cdc: bc.cdc,
input: i,

Check warning on line 140 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L138-L140

Added lines #L138 - L140 were not covered by tests
}
intrinsicGas, _ := core.IntrinsicGas(input, nil, false, bc.isHomestead, bc.isIstanbul, bc.isShanghai)
if !ok {
requiredGas = 0
var msg NativeMessage
switch method.Name {
case CreateClient:
msg, err = extractMsg[clienttypes.MsgCreateClient](e)
case UpdateClient:
msg, err = extractMsg[clienttypes.MsgUpdateClient](e)
case UpgradeClient:
msg, err = extractMsg[clienttypes.MsgUpgradeClient](e)
case ConnectionOpenInit:
msg, err = extractMsg[connectiontypes.MsgConnectionOpenInit](e)
case ConnectionOpenTry:
msg, err = extractMsg[connectiontypes.MsgConnectionOpenTry](e)
case ConnectionOpenAck:
msg, err = extractMsg[connectiontypes.MsgConnectionOpenAck](e)
case ConnectionOpenConfirm:
msg, err = extractMsg[connectiontypes.MsgConnectionOpenConfirm](e)
case ChannelOpenInit:
msg, err = extractMsg[channeltypes.MsgChannelOpenInit](e)
case ChannelOpenTry:
msg, err = extractMsg[channeltypes.MsgChannelOpenTry](e)
case ChannelOpenAck:
msg, err = extractMsg[channeltypes.MsgChannelOpenAck](e)
case ChannelOpenConfirm:
msg, err = extractMsg[channeltypes.MsgChannelOpenConfirm](e)
case ChannelCloseInit:
msg, err = extractMsg[channeltypes.MsgChannelCloseInit](e)
case ChannelCloseConfirm:
msg, err = extractMsg[channeltypes.MsgChannelCloseConfirm](e)
case RecvPacket:
msg, err = extractMsg[channeltypes.MsgRecvPacket](e)
case Acknowledgement:
msg, err = extractMsg[channeltypes.MsgAcknowledgement](e)
case Timeout:
msg, err = extractMsg[channeltypes.MsgTimeout](e)
case TimeoutOnClose:
msg, err = extractMsg[channeltypes.MsgTimeoutOnClose](e)
default:
panic(fmt.Errorf("unknown method: %s", method.Name))

Check warning on line 179 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L142-L179

Added lines #L142 - L179 were not covered by tests
}
gas := requiredGas + baseCost
if gas < intrinsicGas {
gas = 0
} else {
gas -= intrinsicGas
finalGas += gas
if err != nil {

Check warning on line 181 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L181

Added line #L181 was not covered by tests
panic(err)
}

msgs = append(msgs, msg)
if signer == nil {
signers := msg.GetSigners()
if len(signers) != 1 {
panic(errors.New("don't support multi-signers message"))

Check warning on line 189 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L185-L189

Added lines #L185 - L189 were not covered by tests
}
signer = signers[0]

Check warning on line 191 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L191

Added line #L191 was not covered by tests
}
intrinsicGas, _ := core.IntrinsicGas(input, nil, false, bc.isHomestead, bc.isIstanbul, bc.isShanghai)

Check warning on line 193 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L193

Added line #L193 was not covered by tests
methodName := relayerMethodNamedByMethod[methodID]
bc.logger.Debug("required", "gas", gas, "method", methodName, "len", inputLen, "intrinsic", intrinsicGas)
bc.logger.Debug("required", "method", methodName, "intrinsic", intrinsicGas)
intrinsicGasTotal += intrinsicGas

Check warning on line 196 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L195-L196

Added lines #L195 - L196 were not covered by tests
}
i, err := bc.buildSimTx(msgs...)
if err != nil {
panic(err)

Check warning on line 200 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L198-L200

Added lines #L198 - L200 were not covered by tests
}
g, _, err := bc.simulate(i)
if err != nil {
panic(err)

Check warning on line 204 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L202-L204

Added lines #L202 - L204 were not covered by tests
}
if g.GasUsed+baseCost < intrinsicGasTotal {

Check warning on line 206 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L206

Added line #L206 was not covered by tests
return 0
}
return g.GasUsed + baseCost - intrinsicGasTotal

Check warning on line 209 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L209

Added line #L209 was not covered by tests
}

// buildSimTx creates an unsigned tx with an empty single signature and returns
// the encoded transaction or an error if the unsigned transaction cannot be built.
func (bc *RelayerContract) buildSimTx(msgs ...sdk.Msg) ([]byte, error) {
txf := tx.Factory{}.
WithChainID(bc.ctx.ChainID()).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
WithTxConfig(bc.txConfig)

Check warning on line 218 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L214-L218

Added lines #L214 - L218 were not covered by tests

txb, err := txf.BuildUnsignedTx(msgs...)
if err != nil {
return nil, err

Check warning on line 222 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L220-L222

Added lines #L220 - L222 were not covered by tests
}

// Create an empty signature literal as the ante handler will populate with a
// sentinel pubkey.
sig := signing.SignatureV2{
Data: &signing.SingleSignatureData{
SignMode: txf.SignMode(),
},
Sequence: 1,

Check warning on line 231 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L227-L231

Added lines #L227 - L231 were not covered by tests
}
if err = txb.SetSignatures(sig); err != nil {
return nil, err

Check warning on line 234 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L233-L234

Added lines #L233 - L234 were not covered by tests
}
return finalGas
txEncoder := bc.txConfig.TxEncoder()
return txEncoder(txb.GetTx())

Check warning on line 237 in x/cronos/keeper/precompiles/relayer.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/relayer.go#L236-L237

Added lines #L236 - L237 were not covered by tests
}

func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
Expand Down
19 changes: 16 additions & 3 deletions x/cronos/keeper/precompiles/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ type Executor struct {
converter statedb.EventConverter
}

func extractMsg[Req any, PReq interface {
*Req
NativeMessage
}](
e *Executor,
) (PReq, error) {
msg := PReq(new(Req))
if err := e.cdc.Unmarshal(e.input, msg); err != nil {
return nil, fmt.Errorf("fail to Unmarshal %T %w", msg, err)

Check warning on line 37 in x/cronos/keeper/precompiles/utils.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/utils.go#L34-L37

Added lines #L34 - L37 were not covered by tests
}
return msg, nil

Check warning on line 39 in x/cronos/keeper/precompiles/utils.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/utils.go#L39

Added line #L39 was not covered by tests
}

// exec is a generic function that executes the given action in statedb, and marshal/unmarshal the input/output
func exec[Req any, PReq interface {
*Req
Expand All @@ -34,9 +47,9 @@ func exec[Req any, PReq interface {
e *Executor,
action func(context.Context, PReq) (Resp, error),
) ([]byte, error) {
msg := PReq(new(Req))
if err := e.cdc.Unmarshal(e.input, msg); err != nil {
return nil, fmt.Errorf("fail to Unmarshal %T %w", msg, err)
msg, err := extractMsg[Req, PReq](e)
if err != nil {
return nil, err

Check warning on line 52 in x/cronos/keeper/precompiles/utils.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/keeper/precompiles/utils.go#L50-L52

Added lines #L50 - L52 were not covered by tests
}

signers := msg.GetSigners()
Expand Down

0 comments on commit 4344f05

Please sign in to comment.