diff --git a/e2e/qgb/deployer_test.go b/e2e/qgb/deployer_test.go index 0920a6d902..e98241f6c1 100644 --- a/e2e/qgb/deployer_test.go +++ b/e2e/qgb/deployer_test.go @@ -38,9 +38,9 @@ func TestDeployer(t *testing.T) { HandleNetworkError(t, network, err, false) // FIXME should we use the evm client here or go for raw queries? - evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC) + evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC, orchestrator.DEFAULTEVMGASLIMIT) eventNonce, err := evmClient.StateLastEventNonce(&bind.CallOpts{Context: network.Context}) assert.NoError(t, err) - assert.Equal(t, uint64(0), eventNonce) + assert.Equal(t, uint64(1), eventNonce) } diff --git a/e2e/qgb/docker-compose.yml b/e2e/qgb/docker-compose.yml index 1ee89c401e..cd4c475725 100644 --- a/e2e/qgb/docker-compose.yml +++ b/e2e/qgb/docker-compose.yml @@ -195,6 +195,7 @@ services: "--host=0.0.0.0", "--networkId=1234", "--chainId=1234", + "--gasLimit=30000000", "--account=\"0x0e9688e585562e828dcbd4f402d5eddf686f947fb6bf75894a85bf008b017401,0x90000000000000000000000\"" ] ports: @@ -217,6 +218,7 @@ services: - CELESTIA_GRPC=core0:9090 - EVM_CHAIN_ID=1234 - EVM_ENDPOINT=http://ganache:8545 + - STARTING_NONCE=earliest entrypoint: [ "/bin/bash" ] diff --git a/e2e/qgb/full_test.go b/e2e/qgb/full_test.go index 8ebdc8164d..36b7831645 100644 --- a/e2e/qgb/full_test.go +++ b/e2e/qgb/full_test.go @@ -48,7 +48,7 @@ func TestFullLongBehaviour(t *testing.T) { bridge, err := network.GetLatestDeployedQGBContract(network.Context) HandleNetworkError(t, network, err, false) - evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC) + evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC, orchestrator.DEFAULTEVMGASLIMIT) // check whether the relayer relayed all attestations eventNonce, err := evmClient.StateLastEventNonce(&bind.CallOpts{Context: network.Context}) diff --git a/e2e/qgb/relayer_test.go b/e2e/qgb/relayer_test.go index 6f3f2ed253..11a8c539fc 100644 --- a/e2e/qgb/relayer_test.go +++ b/e2e/qgb/relayer_test.go @@ -38,7 +38,7 @@ func TestRelayerWithOneValidator(t *testing.T) { err = network.WaitForRelayerToStart(network.Context, bridge) HandleNetworkError(t, network, err, false) - evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC) + evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC, orchestrator.DEFAULTEVMGASLIMIT) vsNonce, err := evmClient.StateLastEventNonce(&bind.CallOpts{Context: ctx}) assert.NoError(t, err) @@ -88,7 +88,7 @@ func TestRelayerWithTwoValidators(t *testing.T) { HandleNetworkError(t, network, err, false) // FIXME should we use the evm client here or go for raw queries? - evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC) + evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC, orchestrator.DEFAULTEVMGASLIMIT) dcNonce, err := evmClient.StateLastEventNonce(&bind.CallOpts{Context: ctx}) assert.NoError(t, err) @@ -144,7 +144,7 @@ func TestRelayerWithMultipleValidators(t *testing.T) { HandleNetworkError(t, network, err, false) // FIXME should we use the evm client here or go for raw queries? - evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC) + evmClient := orchestrator.NewEvmClient(nil, bridge, nil, network.EVMRPC, orchestrator.DEFAULTEVMGASLIMIT) dcNonce, err := evmClient.StateLastEventNonce(&bind.CallOpts{Context: ctx}) assert.NoError(t, err) diff --git a/e2e/qgb/scripts/deploy_qgb_contract.sh b/e2e/qgb/scripts/deploy_qgb_contract.sh index b5bf7389cb..2e52b4fe0d 100644 --- a/e2e/qgb/scripts/deploy_qgb_contract.sh +++ b/e2e/qgb/scripts/deploy_qgb_contract.sh @@ -12,10 +12,10 @@ fi # check if environment variables are set if [[ -z "${EVM_CHAIN_ID}" || -z "${PRIVATE_KEY}" ]] || \ [[ -z "${TENDERMINT_RPC}" || -z "${CELESTIA_GRPC}" ]] || \ - [[ -z "${EVM_ENDPOINT}" ]] + [[ -z "${EVM_ENDPOINT}" || -z "${STARTING_NONCE}" ]] then echo "Environment not setup correctly. Please set:" - echo "EVM_CHAIN_ID, PRIVATE_KEY, TENDERMINT_RPC, CELESTIA_GRPC, EVM_ENDPOINT variables" + echo "EVM_CHAIN_ID, PRIVATE_KEY, TENDERMINT_RPC, CELESTIA_GRPC, EVM_ENDPOINT, STARTING_NONCE variables" exit 1 fi @@ -59,6 +59,7 @@ echo "deploying QGB contract..." -t ${TENDERMINT_RPC} \ -c ${CELESTIA_GRPC} \ -z ${EVM_CHAIN_ID} \ + -n ${STARTING_NONCE} \ -e ${EVM_ENDPOINT} > /opt/output echo $(cat /opt/output) diff --git a/e2e/qgb/scripts/start_relayer.sh b/e2e/qgb/scripts/start_relayer.sh index 36bc9a7243..1d4511f22a 100644 --- a/e2e/qgb/scripts/start_relayer.sh +++ b/e2e/qgb/scripts/start_relayer.sh @@ -31,6 +31,7 @@ done if [[ -z "${QGB_CONTRACT}" ]] then export DEPLOY_NEW_CONTRACT=true + export STARTING_NONCE=earliest # expects the script to be mounted to this directory /bin/bash /opt/deploy_qgb_contract.sh fi diff --git a/x/qgb/orchestrator/config.go b/x/qgb/orchestrator/config.go index ab1f1ee81b..8e3b1eff1b 100644 --- a/x/qgb/orchestrator/config.go +++ b/x/qgb/orchestrator/config.go @@ -4,12 +4,11 @@ import ( "crypto/ecdsa" "errors" "fmt" + "github.com/spf13/cobra" "log" "os" "path/filepath" - "github.com/spf13/cobra" - ethcmn "github.com/ethereum/go-ethereum/common" ethcrypto "github.com/ethereum/go-ethereum/crypto" ) @@ -40,7 +39,10 @@ const ( tendermintRPCFlag = "celes-http-rpc" evmRPCFlag = "evm-rpc" - contractAddressFlag = "contract-address" + contractAddressFlag = "contract-address" + startingNonceFlag = "starting-nonce" + evmGasLimitFlag = "evm-gas-limit" + celestiaGasLimitFlag = "celestia-gas-limit" ) func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { @@ -61,6 +63,7 @@ func addOrchestratorFlags(cmd *cobra.Command) *cobra.Command { "", "Specify the ECDSA private key used to sign orchestrator commitments in hex", ) + cmd.Flags().Uint64P(celestiaGasLimitFlag, "l", DEFAULTCELESTIAGASLIMIT, "Specify the celestia gas limit") return cmd } @@ -69,6 +72,7 @@ type orchestratorConfig struct { keyringBackend, keyringPath, keyringAccount string celestiaChainID, celesGRPC, tendermintRPC string privateKey *ecdsa.PrivateKey + celestiaGasLimit uint64 } func parseOrchestratorFlags(cmd *cobra.Command) (orchestratorConfig, error) { @@ -107,15 +111,20 @@ func parseOrchestratorFlags(cmd *cobra.Command) (orchestratorConfig, error) { if err != nil { return orchestratorConfig{}, err } + celestiaGasLimit, err := cmd.Flags().GetUint64(celestiaGasLimitFlag) + if err != nil { + return orchestratorConfig{}, err + } return orchestratorConfig{ - keyringBackend: keyringBackend, - keyringPath: keyringPath, - keyringAccount: keyringAccount, - privateKey: ethPrivKey, - celestiaChainID: chainID, - celesGRPC: celesGRPC, - tendermintRPC: tendermintRPC, + keyringBackend: keyringBackend, + keyringPath: keyringPath, + keyringAccount: keyringAccount, + privateKey: ethPrivKey, + celestiaChainID: chainID, + celesGRPC: celesGRPC, + tendermintRPC: tendermintRPC, + celestiaGasLimit: celestiaGasLimit, }, nil } @@ -126,6 +135,7 @@ func addRelayerFlags(cmd *cobra.Command) *cobra.Command { cmd.Flags().StringP(tendermintRPCFlag, "t", "http://localhost:26657", "Specify the rest rpc address") cmd.Flags().StringP(evmRPCFlag, "e", "http://localhost:8545", "Specify the ethereum rpc address") cmd.Flags().StringP(contractAddressFlag, "a", "", "Specify the contract at which the qgb is deployed") + cmd.Flags().Uint64P(evmGasLimitFlag, "l", DEFAULTEVMGASLIMIT, "Specify the evm gas limit") return cmd } @@ -135,6 +145,7 @@ type relayerConfig struct { evmRPC, celesGRPC, tendermintRPC string privateKey *ecdsa.PrivateKey contractAddr ethcmn.Address + evmGasLimit uint64 } func parseRelayerFlags(cmd *cobra.Command) (relayerConfig, error) { @@ -172,7 +183,11 @@ func parseRelayerFlags(cmd *cobra.Command) (relayerConfig, error) { return relayerConfig{}, fmt.Errorf("valid contract address flag is required: %s", contractAddressFlag) } address := ethcmn.HexToAddress(contractAddr) - ethRpc, err := cmd.Flags().GetString(evmRPCFlag) + ethRPC, err := cmd.Flags().GetString(evmRPCFlag) + if err != nil { + return relayerConfig{}, err + } + evmGasLimit, err := cmd.Flags().GetUint64(evmGasLimitFlag) if err != nil { return relayerConfig{}, err } @@ -183,7 +198,8 @@ func parseRelayerFlags(cmd *cobra.Command) (relayerConfig, error) { celesGRPC: celesGRPC, tendermintRPC: tendermintRPC, contractAddr: address, - evmRPC: ethRpc, + evmRPC: ethRPC, + evmGasLimit: evmGasLimit, }, nil } @@ -194,6 +210,16 @@ func addDeployFlags(cmd *cobra.Command) *cobra.Command { cmd.Flags().StringP(celesGRPCFlag, "c", "localhost:9090", "Specify the grpc address") cmd.Flags().StringP(tendermintRPCFlag, "t", "http://localhost:26657", "Specify the rest rpc address") cmd.Flags().StringP(evmRPCFlag, "e", "http://localhost:8545", "Specify the ethereum rpc address") + cmd.Flags().StringP( + startingNonceFlag, + "n", + "latest", + "Specify the nonce to start the QGB contract from. "+ + "\"earliest\": for genesis, "+ + "\"latest\": for latest valset nonce, "+ + "\"nonce\": for the latest valset before the provided nonce, provided nonce included.", + ) + cmd.Flags().Uint64P(evmGasLimitFlag, "l", DEFAULTEVMGASLIMIT, "Specify the evm gas limit") return cmd } @@ -203,6 +229,8 @@ type deployConfig struct { evmRPC, celesGRPC, tendermintRPC string evmChainID uint64 privateKey *ecdsa.PrivateKey + startingNonce string + evmGasLimit uint64 } func parseDeployFlags(cmd *cobra.Command) (deployConfig, error) { @@ -237,6 +265,14 @@ func parseDeployFlags(cmd *cobra.Command) (deployConfig, error) { if err != nil { return deployConfig{}, err } + startingNonce, err := cmd.Flags().GetString(startingNonceFlag) + if err != nil { + return deployConfig{}, err + } + evmGasLimit, err := cmd.Flags().GetUint64(evmGasLimitFlag) + if err != nil { + return deployConfig{}, err + } return deployConfig{ privateKey: ethPrivKey, @@ -245,5 +281,7 @@ func parseDeployFlags(cmd *cobra.Command) (deployConfig, error) { celesGRPC: celesGRPC, tendermintRPC: tendermintRPC, evmRPC: evmRPC, + startingNonce: startingNonce, + evmGasLimit: evmGasLimit, }, nil } diff --git a/x/qgb/orchestrator/deploy_command.go b/x/qgb/orchestrator/deploy_command.go index 0911a4563b..746c941214 100644 --- a/x/qgb/orchestrator/deploy_command.go +++ b/x/qgb/orchestrator/deploy_command.go @@ -1,8 +1,11 @@ package orchestrator import ( - "fmt" + "context" + "github.com/celestiaorg/celestia-app/x/qgb/types" + "github.com/cosmos/cosmos-sdk/types/errors" "os" + "strconv" "github.com/spf13/cobra" tmlog "github.com/tendermint/tendermint/libs/log" @@ -25,13 +28,11 @@ func DeployCmd() *cobra.Command { return err } - // TODO change to get the current valaset - // get the first valset - vs, err := querier.QueryValsetByNonce(cmd.Context(), 1) + vs, err := getStartingValset(cmd.Context(), querier, config.startingNonce) if err != nil { - return fmt.Errorf( + return errors.Wrap( + err, "cannot initialize the QGB contract without having a valset request: %s", - err.Error(), ) } @@ -40,13 +41,14 @@ func DeployCmd() *cobra.Command { nil, config.privateKey, config.evmRPC, + config.evmGasLimit, ) // the deploy QGB contract will handle the logging of the address _, _, _, err = evmClient.DeployQGBContract( cmd.Context(), *vs, - 0, + vs.Nonce, config.evmChainID, true, false, @@ -61,3 +63,32 @@ func DeployCmd() *cobra.Command { } return addDeployFlags(command) } + +func getStartingValset(ctx context.Context, q *querier, snonce string) (*types.Valset, error) { + switch snonce { + case "latest": + return q.QueryLatestValset(ctx) + case "earliest": + return q.QueryValsetByNonce(ctx, 1) + default: + nonce, err := strconv.ParseUint(snonce, 10, 0) + if err != nil { + return nil, err + } + attestation, err := q.QueryAttestationByNonce(ctx, nonce) + if err != nil { + return nil, err + } + if attestation == nil { + return nil, types.ErrNilAttestation + } + if attestation.Type() == types.ValsetRequestType { + value, ok := attestation.(*types.Valset) + if !ok { + return nil, ErrUnmarshallValset + } + return value, nil + } + return q.QueryLastValsetBeforeNonce(ctx, nonce) + } +} diff --git a/x/qgb/orchestrator/evm_client.go b/x/qgb/orchestrator/evm_client.go index 116cda7ed0..1a620f7f4b 100644 --- a/x/qgb/orchestrator/evm_client.go +++ b/x/qgb/orchestrator/evm_client.go @@ -16,6 +16,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ) +const DEFAULTEVMGASLIMIT = uint64(25000000) + var _ EVMClient = &evmClient{} type EVMClient interface { @@ -50,6 +52,7 @@ type evmClient struct { wrapper *wrapper.QuantumGravityBridge privateKey *ecdsa.PrivateKey evmRPC string + gasLimit uint64 } // NewEvmClient Creates a new EVM Client that can be used to deploy the QGB contract and @@ -60,12 +63,14 @@ func NewEvmClient( wrapper *wrapper.QuantumGravityBridge, privateKey *ecdsa.PrivateKey, evmRPC string, + gasLimit uint64, ) *evmClient { return &evmClient{ logger: logger, wrapper: wrapper, privateKey: privateKey, evmRPC: evmRPC, + gasLimit: gasLimit, } } @@ -137,8 +142,7 @@ func (ec *evmClient) UpdateValidatorSet( ) error { // TODO in addition to the nonce, log more interesting information ec.logger.Info("relaying valset", "nonce", newNonce) - // TODO gasLimit ? - opts, err := ec.NewTransactOpts(ctx, 1000000) + opts, err := ec.NewTransactOpts(ctx, ec.gasLimit) if err != nil { return err } @@ -195,7 +199,7 @@ func (ec *evmClient) SubmitDataRootTupleRoot( sigs []wrapper.Signature, waitToBeMined bool, ) error { - opts, err := ec.NewTransactOpts(ctx, 1000000) + opts, err := ec.NewTransactOpts(ctx, ec.gasLimit) if err != nil { return err } diff --git a/x/qgb/orchestrator/orchestrator.go b/x/qgb/orchestrator/orchestrator.go index 0e2479df26..d91b205d04 100644 --- a/x/qgb/orchestrator/orchestrator.go +++ b/x/qgb/orchestrator/orchestrator.go @@ -370,6 +370,8 @@ func CommitmentQueryByRange(beginBlock uint64, endBlock uint64) string { ) } +const DEFAULTCELESTIAGASLIMIT = 100000 + var _ BroadcasterI = &Broadcaster{} type BroadcasterI interface { @@ -377,21 +379,23 @@ type BroadcasterI interface { } type Broadcaster struct { - mutex *sync.Mutex - signer *paytypes.KeyringSigner - qgbGrpc *grpc.ClientConn + mutex *sync.Mutex + signer *paytypes.KeyringSigner + qgbGrpc *grpc.ClientConn + celestiaGasLimit uint64 } -func NewBroadcaster(qgbGrpcAddr string, signer *paytypes.KeyringSigner) (*Broadcaster, error) { +func NewBroadcaster(qgbGrpcAddr string, signer *paytypes.KeyringSigner, celestiaGasLimit uint64) (*Broadcaster, error) { qgbGrpc, err := grpc.Dial(qgbGrpcAddr, grpc.WithInsecure()) if err != nil { return nil, err } return &Broadcaster{ - mutex: &sync.Mutex{}, // investigate if this is needed - signer: signer, - qgbGrpc: qgbGrpc, + mutex: &sync.Mutex{}, // investigate if this is needed + signer: signer, + qgbGrpc: qgbGrpc, + celestiaGasLimit: celestiaGasLimit, }, nil } @@ -404,8 +408,7 @@ func (bc *Broadcaster) BroadcastTx(ctx context.Context, msg sdk.Msg) (string, er } builder := bc.signer.NewTxBuilder() - // TODO make gas limit configurable - builder.SetGasLimit(9999999999999) + builder.SetGasLimit(bc.celestiaGasLimit) // TODO: update this api // via https://github.com/celestiaorg/celestia-app/pull/187/commits/37f96d9af30011736a3e6048bbb35bad6f5b795c tx, err := bc.signer.BuildSignedTx(builder, msg) diff --git a/x/qgb/orchestrator/orchestrator_command.go b/x/qgb/orchestrator/orchestrator_command.go index e30a4e2c00..a8a0f7e548 100644 --- a/x/qgb/orchestrator/orchestrator_command.go +++ b/x/qgb/orchestrator/orchestrator_command.go @@ -46,7 +46,7 @@ func OrchestratorCmd() *cobra.Command { config.celestiaChainID, ) - broadcaster, err := NewBroadcaster(config.celesGRPC, signer) + broadcaster, err := NewBroadcaster(config.celesGRPC, signer, config.celestiaGasLimit) if err != nil { panic(err) } diff --git a/x/qgb/orchestrator/relayer.go b/x/qgb/orchestrator/relayer.go index 33951bc061..6b352d363b 100644 --- a/x/qgb/orchestrator/relayer.go +++ b/x/qgb/orchestrator/relayer.go @@ -85,7 +85,6 @@ func (r *Relayer) processEvents(ctx context.Context) error { return err } - // todo: make gas limit configurable valset, err := r.querier.QueryLastValsetBeforeNonce(ctx, dc.Nonce) if err != nil { return err diff --git a/x/qgb/orchestrator/relayer_command.go b/x/qgb/orchestrator/relayer_command.go index a987c0c28f..2ea17fc1fd 100644 --- a/x/qgb/orchestrator/relayer_command.go +++ b/x/qgb/orchestrator/relayer_command.go @@ -44,6 +44,7 @@ func RelayerCmd() *cobra.Command { qgbWrapper, config.privateKey, config.evmRPC, + config.evmGasLimit, ), logger, )