From 67d251cc90692b2d78d0ca0c81b029980835ffd2 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Fri, 13 Dec 2024 15:17:26 -0600 Subject: [PATCH 01/15] Add ICT Local Image --- .github/workflows/wormchain-icts.yml | 32 ++++++++++++++++++++++ wormchain/Dockerfile.ict | 40 ++++++++++++++++++++++++++++ wormchain/Makefile | 4 +++ wormchain/interchaintest/setup.go | 4 +++ 4 files changed, 80 insertions(+) create mode 100644 wormchain/Dockerfile.ict diff --git a/.github/workflows/wormchain-icts.yml b/.github/workflows/wormchain-icts.yml index 7c71430a85..68615c2eea 100644 --- a/.github/workflows/wormchain-icts.yml +++ b/.github/workflows/wormchain-icts.yml @@ -14,13 +14,45 @@ permissions: env: GO_VERSION: 1.21 + TAR_PATH: /tmp/wormchain-docker-image.tar + IMAGE_NAME: wormchain-docker-image concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: + build-docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: wormchain/interchaintest/go.sum + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and export + uses: docker/build-push-action@v5 + with: + context: . + file: wormchain/Dockerfile.ict + tags: wormchain:local + outputs: type=docker,dest=${{ env.TAR_PATH }} + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ env.IMAGE_NAME }} + path: ${{ env.TAR_PATH }} + e2e-tests: + needs: build-docker runs-on: ubuntu-latest strategy: matrix: diff --git a/wormchain/Dockerfile.ict b/wormchain/Dockerfile.ict new file mode 100644 index 0000000000..f186b286cc --- /dev/null +++ b/wormchain/Dockerfile.ict @@ -0,0 +1,40 @@ +FROM golang:1.22.5@sha256:86a3c48a61915a8c62c0e1d7594730399caa3feb73655dfe96c7bc17710e96cf AS builder + +WORKDIR /app + +# Install dependencies +RUN apt update && \ + apt-get install -y \ + build-essential \ + ca-certificates \ + curl + +# Enable faster module downloading. +ENV GOPROXY https://proxy.golang.org + +COPY ./wormchain/go.mod . +COPY ./wormchain/go.sum . +COPY ./sdk /sdk +RUN go mod download + +COPY ./wormchain . + +RUN make build/wormchaind + +FROM golang:1.22.5@sha256:86a3c48a61915a8c62c0e1d7594730399caa3feb73655dfe96c7bc17710e96cf + +WORKDIR /home/heighliner + +COPY --from=builder /app/build/wormchaind /usr/bin + +# copy over c bindings (libwasmvm.x86_64.so, etc) +COPY --from=builder /go/pkg/mod/github.com/!cosm!wasm/wasmvm@v1.1.1/internal/api/* /usr/lib + +EXPOSE 26657 +EXPOSE 26656 +EXPOSE 6060 +EXPOSE 9090 +EXPOSE 1317 +EXPOSE 4500 + +ENTRYPOINT [ "wormchaind" ] \ No newline at end of file diff --git a/wormchain/Makefile b/wormchain/Makefile index 8252663763..62642ff6f9 100644 --- a/wormchain/Makefile +++ b/wormchain/Makefile @@ -83,6 +83,10 @@ clean: ## INTERCHAINTESTS ## ##################### +# Generate Wormchain Image +local-image: build/wormchaind + docker build -t wormchain:local -f Dockerfile.ict .. + # Individual Tests ($$ is interpreted as $) rm-testcache: go clean -testcache diff --git a/wormchain/interchaintest/setup.go b/wormchain/interchaintest/setup.go index 0ae366dac7..1302f76cd2 100644 --- a/wormchain/interchaintest/setup.go +++ b/wormchain/interchaintest/setup.go @@ -69,6 +69,10 @@ func CreateChains(t *testing.T, wormchainVersion string, guardians guardians.Val numWormchainVals := len(guardians.Vals) wormchainConfig.Images[0].Version = wormchainVersion + if wormchainVersion == "local" { + wormchainConfig.Images[0].Repository = "wormchain" + } + // Create chain factory with wormchain wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians) From f3e27d038327684f6ab77a0be92f325a0abbafa3 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Mon, 18 Nov 2024 14:12:18 -0600 Subject: [PATCH 02/15] Ref Slashing Keeper in Wormhole Keeper --- sdk/vaa/payloads.go | 11 +++++----- wormchain/app/app.go | 2 ++ wormchain/x/wormhole/keeper/keeper.go | 20 +++++++++++++------ .../msg_server_execute_governance_vaa.go | 6 ++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/sdk/vaa/payloads.go b/sdk/vaa/payloads.go index bf86d32280..f15b23745e 100644 --- a/sdk/vaa/payloads.go +++ b/sdk/vaa/payloads.go @@ -69,11 +69,12 @@ type GovernanceAction uint8 var ( // Wormhole core governance actions // See e.g. GovernanceStructs.sol for semantic meaning of these - ActionContractUpgrade GovernanceAction = 1 - ActionGuardianSetUpdate GovernanceAction = 2 - ActionCoreSetMessageFee GovernanceAction = 3 - ActionCoreTransferFees GovernanceAction = 4 - ActionCoreRecoverChainId GovernanceAction = 5 + ActionContractUpgrade GovernanceAction = 1 + ActionGuardianSetUpdate GovernanceAction = 2 + ActionCoreSetMessageFee GovernanceAction = 3 + ActionCoreTransferFees GovernanceAction = 4 + ActionCoreRecoverChainId GovernanceAction = 5 + ActionSlashingParamsUpdate GovernanceAction = 6 // Wormchain cosmwasm/middleware governance actions ActionStoreCode GovernanceAction = 1 diff --git a/wormchain/app/app.go b/wormchain/app/app.go index 40463085ec..131f89a77d 100644 --- a/wormchain/app/app.go +++ b/wormchain/app/app.go @@ -388,6 +388,8 @@ func New( app.SlashingKeeper = slashingkeeper.NewKeeper( appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName), ) + app.WormholeKeeper.SetSlashingKeeper(app.SlashingKeeper) + app.CrisisKeeper = crisiskeeper.NewKeeper( app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName, ) diff --git a/wormchain/x/wormhole/keeper/keeper.go b/wormchain/x/wormhole/keeper/keeper.go index a3eb4652c1..8967c3627d 100644 --- a/wormchain/x/wormhole/keeper/keeper.go +++ b/wormchain/x/wormhole/keeper/keeper.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/wormhole-foundation/wormchain/x/wormhole/types" ) @@ -17,13 +18,15 @@ type ( storeKey sdk.StoreKey memKey sdk.StoreKey - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper - wasmdKeeper types.WasmdKeeper - upgradeKeeper upgradekeeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + wasmdKeeper types.WasmdKeeper + upgradeKeeper upgradekeeper.Keeper + slashingKeeper slashingkeeper.Keeper - setWasmd bool - setUpgrade bool + setWasmd bool + setUpgrade bool + setSlashing bool } ) @@ -59,6 +62,11 @@ func (k *Keeper) SetUpgradeKeeper(keeper upgradekeeper.Keeper) { k.setUpgrade = true } +func (k *Keeper) SetSlashingKeeper(keeper slashingkeeper.Keeper) { + k.slashingKeeper = keeper + k.setSlashing = true +} + func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go index d4d7e05a39..e474151523 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go @@ -5,6 +5,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/wormhole-foundation/wormchain/x/wormhole/types" "github.com/wormhole-foundation/wormhole/sdk/vaa" ) @@ -59,6 +60,11 @@ func (k msgServer) ExecuteGovernanceVAA(goCtx context.Context, msg *types.MsgExe if err != nil { return nil, err } + case vaa.ActionSlashingParamsUpdate: + + // TODO: JOEL + k.slashingKeeper.SetParams(ctx, slashingtypes.Params{}) + default: return nil, types.ErrUnknownGovernanceAction From d01a0c04873f781b9cff6ff8f5c03424efa693a6 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Tue, 19 Nov 2024 15:09:16 -0600 Subject: [PATCH 03/15] Add Payload & Test --- sdk/vaa/payloads.go | 27 +++++++++ sdk/vaa/payloads_test.go | 22 ++++++++ .../msg_server_execute_governance_vaa.go | 27 ++++++++- .../msg_server_execute_governance_vaa_test.go | 55 +++++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) diff --git a/sdk/vaa/payloads.go b/sdk/vaa/payloads.go index f15b23745e..b62b1ba4d1 100644 --- a/sdk/vaa/payloads.go +++ b/sdk/vaa/payloads.go @@ -128,6 +128,14 @@ type ( NewIndex uint32 } + BodySlashingParamsUpdate struct { + SignedBlocksWindow uint64 + MinSignedPerWindow uint64 + DowntimeJailDuration uint64 + SlashFractionDoubleSign uint64 + SlashFractionDowntime uint64 + } + // BodyTokenBridgeRegisterChain is a governance message to register a chain on the token bridge BodyTokenBridgeRegisterChain struct { Module string @@ -284,6 +292,25 @@ func (b BodyGuardianSetUpdate) Serialize() ([]byte, error) { return buf.Bytes(), nil } +func (b BodySlashingParamsUpdate) Serialize() ([]byte, error) { + buf := new(bytes.Buffer) + + // Module + buf.Write(CoreModule) + // // Action + MustWrite(buf, binary.BigEndian, ActionSlashingParamsUpdate) + // // ChainID - 0 for universal + MustWrite(buf, binary.BigEndian, uint16(0)) + + MustWrite(buf, binary.BigEndian, b.SignedBlocksWindow) + MustWrite(buf, binary.BigEndian, b.MinSignedPerWindow) + MustWrite(buf, binary.BigEndian, b.DowntimeJailDuration) + MustWrite(buf, binary.BigEndian, b.SlashFractionDoubleSign) + MustWrite(buf, binary.BigEndian, b.SlashFractionDowntime) + + return buf.Bytes(), nil +} + func (r BodyTokenBridgeRegisterChain) Serialize() ([]byte, error) { payload := &bytes.Buffer{} MustWrite(payload, binary.BigEndian, r.ChainID) diff --git a/sdk/vaa/payloads_test.go b/sdk/vaa/payloads_test.go index 1ce46166c8..23d8284cd0 100644 --- a/sdk/vaa/payloads_test.go +++ b/sdk/vaa/payloads_test.go @@ -6,6 +6,7 @@ import ( "errors" "reflect" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" @@ -73,6 +74,27 @@ func TestBodyGuardianSetUpdateSerialize(t *testing.T) { assert.Equal(t, expected, hex.EncodeToString(serializedBodyGuardianSetUpdate)) } +func TestBodySlashingParamsUpdateSerialize(t *testing.T) { + signedBlocksWindow := uint64(100) + minSignedPerWindow := uint64(500000000000000000) + downtimeJailDuration := uint64(600 * time.Second) + slashFractionDoubleSign := uint64(50000000000000000) + slashFractionDowntime := uint64(10000000000000000) + + bodySlashingParamsUpdate := BodySlashingParamsUpdate{ + SignedBlocksWindow: signedBlocksWindow, + MinSignedPerWindow: minSignedPerWindow, + DowntimeJailDuration: downtimeJailDuration, + SlashFractionDoubleSign: slashFractionDoubleSign, + SlashFractionDowntime: slashFractionDowntime, + } + serializedBody, err := bodySlashingParamsUpdate.Serialize() + require.NoError(t, err) + + expected := "00000000000000000000000000000000000000000000000000000000436f7265060000000000000000006406f05b59d3b200000000008bb2c9700000b1a2bc2ec50000002386f26fc10000" + assert.Equal(t, expected, hex.EncodeToString(serializedBody)) +} + func TestBodyTokenBridgeRegisterChainSerialize(t *testing.T) { module := "test" tests := []struct { diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go index e474151523..f6d23023e9 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go @@ -3,6 +3,7 @@ package keeper import ( "context" "encoding/binary" + "time" sdk "github.com/cosmos/cosmos-sdk/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" @@ -61,10 +62,32 @@ func (k msgServer) ExecuteGovernanceVAA(goCtx context.Context, msg *types.MsgExe return nil, err } case vaa.ActionSlashingParamsUpdate: + // Ensure payload is 45 bytes to store 5 int64 values + if len(payload) != 40 { + return nil, types.ErrInvalidGovernancePayloadLength + } + + // Extract params from payload + signedBlocksWindow := int64(binary.BigEndian.Uint64(payload[:8])) + minSignedPerWindow := int64(binary.BigEndian.Uint64(payload[8:16])) + downtimeJailDuration := int64(binary.BigEndian.Uint64(payload[16:24])) + slashFractionDoubleSign := int64(binary.BigEndian.Uint64(payload[24:32])) + slashFractionDowntime := int64(binary.BigEndian.Uint64(payload[32:40])) - // TODO: JOEL - k.slashingKeeper.SetParams(ctx, slashingtypes.Params{}) + // Update slashing params + params := slashingtypes.NewParams( + signedBlocksWindow, + sdk.NewDecWithPrec(minSignedPerWindow, 18), + time.Duration(downtimeJailDuration), + sdk.NewDecWithPrec(slashFractionDoubleSign, 18), + sdk.NewDecWithPrec(slashFractionDowntime, 18), + ) + // Set the new params + err := k.slashingKeeper.SetParams(ctx, params) + if err != nil { + return nil, err + } default: return nil, types.ErrUnknownGovernanceAction diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go index 462a6dd46c..636f41451e 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "encoding/binary" "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" @@ -107,3 +108,57 @@ func TestExecuteGovernanceVAA(t *testing.T) { new_index2 := k.GetLatestGuardianSetIndex(ctx) assert.Equal(t, new_set.Index+1, new_index2) } + +func createSlashingParamsUpdatePayload() []byte { + // 5 int64 values + slashingParams := make([]byte, 40) + + signedBlocksWindow := uint64(100) + minSignedPerWindow := sdk.NewDecWithPrec(5, 1).BigInt().Uint64() + downtimeJailDuration := uint64(600 * time.Second) + slashFractionDoubleSign := sdk.NewDecWithPrec(5, 2).BigInt().Uint64() + slashFractionDowntime := sdk.NewDecWithPrec(1, 2).BigInt().Uint64() + + binary.BigEndian.PutUint64(slashingParams, signedBlocksWindow) + binary.BigEndian.PutUint64(slashingParams[8:], minSignedPerWindow) + binary.BigEndian.PutUint64(slashingParams[16:], downtimeJailDuration) + binary.BigEndian.PutUint64(slashingParams[24:], slashFractionDoubleSign) + binary.BigEndian.PutUint64(slashingParams[32:], slashFractionDowntime) + + // governance message with sha3 of wasmBytes as the payload + module := [32]byte{} + copy(module[:], vaa.CoreModule) + gov_msg := types.NewGovernanceMessage(module, byte(vaa.ActionSlashingParamsUpdate), uint16(vaa.ChainIDWormchain), slashingParams) + + return gov_msg.MarshalBinary() +} + +func TestExecuteSlashingParamsUpdate(t *testing.T) { + k, ctx := keepertest.WormholeKeeper(t) + guardians, privateKeys := createNGuardianValidator(k, ctx, 10) + _ = privateKeys + k.SetConfig(ctx, types.Config{ + GovernanceEmitter: vaa.GovernanceEmitter[:], + GovernanceChain: uint32(vaa.GovernanceChain), + ChainId: uint32(vaa.ChainIDWormchain), + GuardianSetExpiration: 86400, + }) + signer_bz := [20]byte{} + signer := sdk.AccAddress(signer_bz[:]) + + set := createNewGuardianSet(k, ctx, guardians) + k.SetConsensusGuardianSetIndex(ctx, types.ConsensusGuardianSetIndex{Index: set.Index}) + + context := sdk.WrapSDKContext(ctx) + msgServer := keeper.NewMsgServerImpl(*k) + + // create governance to update guardian set with extra guardian + payload := createSlashingParamsUpdatePayload() + v := generateVaa(set.Index, privateKeys, vaa.ChainID(vaa.GovernanceChain), payload) + vBz, _ := v.Marshal() + _, err := msgServer.ExecuteGovernanceVAA(context, &types.MsgExecuteGovernanceVAA{ + Signer: signer.String(), + Vaa: vBz, + }) + assert.NoError(t, err) +} From d0596f4dc2129f4e67ed35e8ef87521ebf89dcd5 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Wed, 20 Nov 2024 11:00:24 -0600 Subject: [PATCH 04/15] Add Generate Slashing Params Update Vaa Cmd --- wormchain/x/wormhole/client/cli/genesis.go | 107 +++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/wormchain/x/wormhole/client/cli/genesis.go b/wormchain/x/wormhole/client/cli/genesis.go index 2d43fcc9e8..5d55a37bc5 100644 --- a/wormchain/x/wormhole/client/cli/genesis.go +++ b/wormchain/x/wormhole/client/cli/genesis.go @@ -38,6 +38,11 @@ const FLAG_ACTION = "action" const FLAG_CHAIN = "chain" const FLAG_PUBLIC_KEY = "public-key" const FLAG_NEXT_INDEX = "next-index" +const FLAG_SIGNED_BLOCKS_WINDOW = "signed-blocks-window" +const FLAG_MIN_SIGNED_PER_WINDOW = "min-signed-per-window" +const FLAG_DOWNTIME_JAIL_DURATION = "downtime-jail-duration" +const FLAG_SLASH_FRACTION_DOUBLE_SIGN = "slash-fraction-double-sign" +const FLAG_SLASH_FRACTION_DOWNTIME = "slash-fraction-downtime" // GetGenesisCmd returns the genesis related commands for this module func GetGenesisCmd() *cobra.Command { @@ -54,6 +59,7 @@ func GetGenesisCmd() *cobra.Command { cmd.AddCommand(CmdGenerateVaa()) cmd.AddCommand(CmdGenerateGovernanceVaa()) cmd.AddCommand(CmdGenerateGuardianSetUpdatea()) + cmd.AddCommand(CmdGenerateSlashingParamsUpdateVaa()) cmd.AddCommand(CmdTestSignAddress()) return cmd @@ -216,6 +222,7 @@ func addVaaFlags(cmd *cobra.Command) { cmd.Flags().Uint64(FLAG_SEQUENCE, 0, "sequence number") cmd.Flags().Uint32(FLAG_NONCE, 0, "nonce") cmd.Flags().String(FLAG_PAYLOAD, "", "payload (hex format)") + } func addGovVaaFlags(cmd *cobra.Command) { cmd.Flags().String(FLAG_MODULE, "", "module (ascii string)") @@ -405,6 +412,106 @@ func CmdGenerateGuardianSetUpdatea() *cobra.Command { return cmd } +func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { + cmd := &cobra.Command{ + Use: "generate-slashing-params-update-vaa", + Short: "generate and sign a governance vaa to update the slashing params", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + + privateKeys := []*ecdsa.PrivateKey{} + privateKeysFiles, err := cmd.Flags().GetStringArray(FLAG_KEY) + if err != nil { + return err + } + for _, privFile := range privateKeysFiles { + priv, err := ImportKeyFromFile(privFile) + if err != nil { + return err + } + privateKeys = append(privateKeys, priv) + } + v, err := parseVaaFromFlags(cmd) + if err != nil { + return err + } + + signedBlocksWindow, err := cmd.Flags().GetUint64(FLAG_SIGNED_BLOCKS_WINDOW) + if err != nil { + return err + } + + minSignedPerWindow, err := cmd.Flags().GetString(FLAG_MIN_SIGNED_PER_WINDOW) + if err != nil { + return err + } + minSignedPerWindowDec, err := sdk.NewDecFromStr(minSignedPerWindow) + if err != nil { + return err + } + + downtimeJailDuration, err := cmd.Flags().GetUint64(FLAG_DOWNTIME_JAIL_DURATION) + if err != nil { + return err + } + + slashFractionDoubleSign, err := cmd.Flags().GetString(FLAG_SLASH_FRACTION_DOUBLE_SIGN) + if err != nil { + return err + } + slashFractionDoubleSignDec, err := sdk.NewDecFromStr(slashFractionDoubleSign) + if err != nil { + return err + } + + slashFractionDowntime, err := cmd.Flags().GetString(FLAG_SLASH_FRACTION_DOWNTIME) + if err != nil { + return err + } + slashFractionDowntimeDec, err := sdk.NewDecFromStr(slashFractionDowntime) + if err != nil { + return err + } + + slashingUpdate := make([]byte, 40) + binary.BigEndian.PutUint64(slashingUpdate[:8], signedBlocksWindow) + binary.BigEndian.PutUint64(slashingUpdate[8:16], minSignedPerWindowDec.BigInt().Uint64()) + binary.BigEndian.PutUint64(slashingUpdate[16:24], downtimeJailDuration*uint64(time.Second)) + binary.BigEndian.PutUint64(slashingUpdate[24:32], slashFractionDoubleSignDec.BigInt().Uint64()) + binary.BigEndian.PutUint64(slashingUpdate[32:40], slashFractionDowntimeDec.BigInt().Uint64()) + + action := vaa.ActionSlashingParamsUpdate + chain := 3104 + module := [32]byte{} + copy(module[:], vaa.CoreModule) + msg := types.NewGovernanceMessage(module, byte(action), uint16(chain), slashingUpdate) + v.Payload = msg.MarshalBinary() + v.EmitterChain = 1 + + for i, key := range privateKeys { + v.AddSignature(key, uint8(i)) + } + + v_bz, err := v.Marshal() + if err != nil { + return err + } + fmt.Println(hex.EncodeToString(v_bz)) + + return nil + }, + } + + addVaaFlags(cmd) + cmd.Flags().Uint64(FLAG_SIGNED_BLOCKS_WINDOW, 100, "signed blocks window") + cmd.Flags().String(FLAG_MIN_SIGNED_PER_WINDOW, "0.500000000000000000", "min signed per window") + cmd.Flags().Uint64(FLAG_DOWNTIME_JAIL_DURATION, uint64(600*time.Second), "downtime jail duration (seconds)") + cmd.Flags().String(FLAG_SLASH_FRACTION_DOUBLE_SIGN, "0.050000000000000000", "slash fraction double sign") + cmd.Flags().String(FLAG_SLASH_FRACTION_DOWNTIME, "0.010000000000000000", "slash fraction downtime") + + return cmd +} + func CmdTestSignAddress() *cobra.Command { cmd := &cobra.Command{ Use: "test-sign-address", From 6935fd07562fa08a3c1640545c57bf8a7de00ce9 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Wed, 20 Nov 2024 16:08:43 -0600 Subject: [PATCH 05/15] Add ICT Tests --- .github/workflows/wormchain-icts.yml | 1 + wormchain/Makefile | 5 +- .../slashing_params_update_vaa_test.go | 155 ++++++++++++++++++ .../msg_server_execute_governance_vaa.go | 1 - .../msg_server_execute_governance_vaa_test.go | 2 +- 5 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 wormchain/interchaintest/slashing_params_update_vaa_test.go diff --git a/.github/workflows/wormchain-icts.yml b/.github/workflows/wormchain-icts.yml index 68615c2eea..b31d58367c 100644 --- a/.github/workflows/wormchain-icts.yml +++ b/.github/workflows/wormchain-icts.yml @@ -59,6 +59,7 @@ jobs: # names of `make` commands to run tests test: - "ictest-cancel-upgrade" + - "ictest-slashing-params-update-vaa" - "ictest-upgrade" - "ictest-wormchain" - "ictest-ibc-receiver" diff --git a/wormchain/Makefile b/wormchain/Makefile index 62642ff6f9..629a3e21b8 100644 --- a/wormchain/Makefile +++ b/wormchain/Makefile @@ -97,6 +97,9 @@ ictest-cancel-upgrade: rm-testcache ictest-malformed-payload: rm-testcache cd interchaintest && go test -race -v -run ^TestMalformedPayload$$ ./... +ictest-slashing-params-update-vaa: rm-testcache + cd interchaintest && go test -race -v -run ^TestSlashingParamsUpdateVaa$$ ./... + ictest-upgrade-failure: rm-testcache cd interchaintest && go test -race -v -run ^TestUpgradeFailure$$ ./... @@ -109,4 +112,4 @@ ictest-wormchain: rm-testcache ictest-ibc-receiver: rm-testcache cd interchaintest && go test -race -v -run ^TestIbcReceiver ./... -.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver \ No newline at end of file +.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-slashing-params-update-vaa ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver diff --git a/wormchain/interchaintest/slashing_params_update_vaa_test.go b/wormchain/interchaintest/slashing_params_update_vaa_test.go new file mode 100644 index 0000000000..ce97e5185a --- /dev/null +++ b/wormchain/interchaintest/slashing_params_update_vaa_test.go @@ -0,0 +1,155 @@ +package ictest + +import ( + "context" + "encoding/binary" + "encoding/hex" + "encoding/json" + "strconv" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/strangelove-ventures/interchaintest/v4/chain/cosmos" + "github.com/stretchr/testify/require" + "github.com/wormhole-foundation/wormchain/interchaintest/guardians" + "github.com/wormhole-foundation/wormchain/interchaintest/helpers" + types "github.com/wormhole-foundation/wormchain/x/wormhole/types" + "github.com/wormhole-foundation/wormhole/sdk/vaa" +) + +// Params is the slashing params response from the chain +type Params struct { + SignedBlocksWindow string `json:"signed_blocks_window"` + MinSignedPerWindow string `json:"min_signed_per_window"` + DowntimeJailDuration string `json:"downtime_jail_duration"` + SlashFractionDoubleSign string `json:"slash_fraction_double_sign"` + SlashFractionDowntime string `json:"slash_fraction_downtime"` +} + +// createSlashingParamsUpdate creates a slashing params update VAA +// that can be executed on chain via the governance module +func createSlashingParamsUpdate( + signedBlocksWindow uint64, + minSignedPerWindow string, + downtimeJailDurationSeconds uint64, + slashFractionDoubleSign string, + slashFractionDowntime string, +) ([]byte, error) { + var coreModule [32]byte + copy(coreModule[:], vaa.CoreModule[:]) + + minSignedWindow, err := sdk.NewDecFromStr(minSignedPerWindow) + if err != nil { + return nil, err + } + + downtimeJailDurationSeconds = downtimeJailDurationSeconds * uint64(time.Second) + + slashFractionDoubleSignDec, err := sdk.NewDecFromStr(slashFractionDoubleSign) + if err != nil { + return nil, err + } + + slashFractionDowntimeDec, err := sdk.NewDecFromStr(slashFractionDowntime) + if err != nil { + return nil, err + } + + payload := make([]byte, 40) + binary.BigEndian.PutUint64(payload[0:8], signedBlocksWindow) + binary.BigEndian.PutUint64(payload[8:16], minSignedWindow.BigInt().Uint64()) + binary.BigEndian.PutUint64(payload[16:24], downtimeJailDurationSeconds) + binary.BigEndian.PutUint64(payload[24:32], slashFractionDoubleSignDec.BigInt().Uint64()) + binary.BigEndian.PutUint64(payload[32:40], slashFractionDowntimeDec.BigInt().Uint64()) + + gov_msg := types.NewGovernanceMessage(coreModule, byte(vaa.ActionSlashingParamsUpdate), uint16(vaa.ChainIDWormchain), + payload) + + return gov_msg.MarshalBinary(), nil +} + +// querySlashingParams queries the slashing params from the chain +func querySlashingParams(ctx context.Context, wormchain *cosmos.CosmosChain) (params slashingtypes.Params, err error) { + // query the slashing params + res, _, err := wormchain.GetNode().ExecQuery(ctx, "slashing", "params") + if err != nil { + return + } + + var slashingParams Params + err = json.Unmarshal(res, &slashingParams) + if err != nil { + return + } + + params.SignedBlocksWindow, err = strconv.ParseInt(slashingParams.SignedBlocksWindow, 10, 64) + if err != nil { + return + } + + params.MinSignedPerWindow, err = sdk.NewDecFromStr(slashingParams.MinSignedPerWindow) + if err != nil { + return + } + + params.DowntimeJailDuration, err = time.ParseDuration(slashingParams.DowntimeJailDuration) + if err != nil { + return + } + + params.SlashFractionDoubleSign, err = sdk.NewDecFromStr(slashingParams.SlashFractionDoubleSign) + if err != nil { + return + } + + params.SlashFractionDowntime, err = sdk.NewDecFromStr(slashingParams.SlashFractionDowntime) + if err != nil { + return + } + + return +} + +// TestSlashingParamsUpdateVaa tests the execution of a slashing params update VAA +// and verifies that the governance module correctly updates the slashing params +func TestSlashingParamsUpdateVaa(t *testing.T) { + if testing.Short() { + t.Skip() + } + + t.Parallel() + + // Base setup + guardians := guardians.CreateValSet(t, 2) + chains := CreateLocalChain(t, *guardians) + ic, ctx, _, _, _, _ := BuildInterchain(t, chains) + require.NotNil(t, ic) + require.NotNil(t, ctx) + + wormchain := chains[0].(*cosmos.CosmosChain) + + // Create a governance VAA + payloadBytes, err := createSlashingParamsUpdate(200, "0.1", 300, "0.2", "0.3") + require.NoError(t, err) + + v := helpers.GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBytes) + vBz, err := v.Marshal() + require.NoError(t, err) + vHex := hex.EncodeToString(vBz) + + _, err = wormchain.FullNodes[0].ExecTx(ctx, "faucet", "wormhole", "execute-governance-vaa", vHex) + require.NoError(t, err) + + // query the slashing params + slashingParams, err := querySlashingParams(ctx, wormchain) + require.NoError(t, err) + + // validate the slashing params changed + require.Equal(t, int64(200), slashingParams.SignedBlocksWindow) + require.Equal(t, "0.100000000000000000", slashingParams.MinSignedPerWindow.String()) + require.Equal(t, 300*time.Second, slashingParams.DowntimeJailDuration) + require.Equal(t, "0.200000000000000000", slashingParams.SlashFractionDoubleSign.String()) + require.Equal(t, "0.300000000000000000", slashingParams.SlashFractionDowntime.String()) +} diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go index f6d23023e9..a94ca322df 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go @@ -62,7 +62,6 @@ func (k msgServer) ExecuteGovernanceVAA(goCtx context.Context, msg *types.MsgExe return nil, err } case vaa.ActionSlashingParamsUpdate: - // Ensure payload is 45 bytes to store 5 int64 values if len(payload) != 40 { return nil, types.ErrInvalidGovernancePayloadLength } diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go index 636f41451e..9e876db5ab 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go @@ -152,7 +152,7 @@ func TestExecuteSlashingParamsUpdate(t *testing.T) { context := sdk.WrapSDKContext(ctx) msgServer := keeper.NewMsgServerImpl(*k) - // create governance to update guardian set with extra guardian + // create governance to update slashing params payload := createSlashingParamsUpdatePayload() v := generateVaa(set.Index, privateKeys, vaa.ChainID(vaa.GovernanceChain), payload) vBz, _ := v.Marshal() From 7eac4e282d16e5d74f481467df5b1ed28b421882 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Fri, 13 Dec 2024 16:41:07 -0600 Subject: [PATCH 06/15] Finish ICTs --- wormchain/.gitignore | 2 +- .../helpers/gateway_governance_vaa.go | 6 +- .../interchaintest/helpers/ibc_translator.go | 6 +- .../helpers/instantiate_contract.go | 2 +- .../helpers/migrate_contract.go | 2 +- .../interchaintest/helpers/store_contract.go | 2 +- .../interchaintest/helpers/token_bridge.go | 4 +- wormchain/interchaintest/helpers/vaa.go | 2 +- .../slashing_params_update_vaa_test.go | 111 +++++++++++++++--- .../msg_server_execute_governance_vaa.go | 9 +- 10 files changed, 111 insertions(+), 35 deletions(-) diff --git a/wormchain/.gitignore b/wormchain/.gitignore index 252784af5f..632f13a987 100644 --- a/wormchain/.gitignore +++ b/wormchain/.gitignore @@ -6,7 +6,7 @@ release/ testing/js/node_modules !build build/wormhole-chaind -build/wormchaind +build/wormchaind* build/data devnet/wormchain-*/data devnet/wormchain-*/config/*.toml diff --git a/wormchain/interchaintest/helpers/gateway_governance_vaa.go b/wormchain/interchaintest/helpers/gateway_governance_vaa.go index c2f1feb561..4828b41232 100644 --- a/wormchain/interchaintest/helpers/gateway_governance_vaa.go +++ b/wormchain/interchaintest/helpers/gateway_governance_vaa.go @@ -41,7 +41,7 @@ func SetMiddlewareContract( } payloadBz, err := payload.Serialize() require.NoError(t, err) - v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) + v := GenerateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) @@ -67,7 +67,7 @@ func ScheduleUpgrade( } payloadBz, err := payload.Serialize() require.NoError(t, err) - v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBz) + v := GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBz) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) @@ -87,7 +87,7 @@ func CancelUpgrade( payloadBz, err := vaa.EmptyPayloadVaa(vaa.GatewayModuleStr, vaa.ActionCancelUpgrade, vaa.ChainIDWormchain) require.NoError(t, err) - v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) + v := GenerateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) diff --git a/wormchain/interchaintest/helpers/ibc_translator.go b/wormchain/interchaintest/helpers/ibc_translator.go index 56edd9cf5c..ff7ba88e6b 100644 --- a/wormchain/interchaintest/helpers/ibc_translator.go +++ b/wormchain/interchaintest/helpers/ibc_translator.go @@ -39,7 +39,7 @@ func SubmitAllowlistInstantiateContract( } payloadBz, err := payload.Serialize(vaa.ActionAddWasmInstantiateAllowlist) require.NoError(t, err) - v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) + v := GenerateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) @@ -83,7 +83,7 @@ func SubmitUpdateChainToChannelMapMsg(t *testing.T, allowlistChainID uint16, all payload.Write(channelPadded.Bytes()) vaa.MustWrite(payload, binary.BigEndian, allowlistChainID) - v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payload.Bytes()) + v := GenerateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payload.Bytes()) vBz, err := v.Marshal() require.NoError(t, err) @@ -162,7 +162,7 @@ func IbcTranslatorCompleteTransferAndConvertMsg(t *testing.T, emitterChainID uin emitterBz[eIndex-1] = emitterAddr[i-1] eIndex-- } - v := generateVaa(0, guardians, vaa.ChainID(emitterChainID), vaa.Address(emitterBz), payload) + v := GenerateVaa(0, guardians, vaa.ChainID(emitterChainID), vaa.Address(emitterBz), payload) vBz, err := v.Marshal() require.NoError(t, err) diff --git a/wormchain/interchaintest/helpers/instantiate_contract.go b/wormchain/interchaintest/helpers/instantiate_contract.go index e627f02865..b3c7a31f81 100644 --- a/wormchain/interchaintest/helpers/instantiate_contract.go +++ b/wormchain/interchaintest/helpers/instantiate_contract.go @@ -47,7 +47,7 @@ func InstantiateContract( code_id, err := strconv.ParseUint(codeId, 10, 64) require.NoError(t, err) payload := createWasmInstantiatePayload(code_id, label, message) - v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) + v := GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) diff --git a/wormchain/interchaintest/helpers/migrate_contract.go b/wormchain/interchaintest/helpers/migrate_contract.go index b488f462ee..0ffd4b8996 100644 --- a/wormchain/interchaintest/helpers/migrate_contract.go +++ b/wormchain/interchaintest/helpers/migrate_contract.go @@ -42,7 +42,7 @@ func MigrateContract( code_id, err := strconv.ParseUint(codeId, 10, 64) require.NoError(t, err) payload := createWasmMigrationPayload(code_id, contractAddr, message) - v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) + v := GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) vBz, err := v.Marshal() require.NoError(t, err) vHex := hex.EncodeToString(vBz) diff --git a/wormchain/interchaintest/helpers/store_contract.go b/wormchain/interchaintest/helpers/store_contract.go index 5151ebadd1..548b635f13 100644 --- a/wormchain/interchaintest/helpers/store_contract.go +++ b/wormchain/interchaintest/helpers/store_contract.go @@ -79,7 +79,7 @@ func StoreContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, } payload := createWasmStoreCodePayload(content) - v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) + v := GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) vBz, err := v.Marshal() require.NoError(t, err) diff --git a/wormchain/interchaintest/helpers/token_bridge.go b/wormchain/interchaintest/helpers/token_bridge.go index bd30134008..337fa11328 100644 --- a/wormchain/interchaintest/helpers/token_bridge.go +++ b/wormchain/interchaintest/helpers/token_bridge.go @@ -69,7 +69,7 @@ func TbRegisterChainMsg(t *testing.T, chainID uint16, emitterAddr string, guardi payload, err := bodyTbRegisterChain.Serialize() require.NoError(t, err) - v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) + v := GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload) vBz, err := v.Marshal() require.NoError(t, err) @@ -106,7 +106,7 @@ func TbRegisterForeignAsset(t *testing.T, tokenAddr string, chainID uint16, emit emitterBz[eIndex-1] = emitterAddr[i-1] eIndex-- } - v := generateVaa(0, guardians, vaa.ChainID(chainID), vaa.Address(emitterBz), payload.Bytes()) + v := GenerateVaa(0, guardians, vaa.ChainID(chainID), vaa.Address(emitterBz), payload.Bytes()) vBz, err := v.Marshal() require.NoError(t, err) diff --git a/wormchain/interchaintest/helpers/vaa.go b/wormchain/interchaintest/helpers/vaa.go index 093b84e920..a8de3430c0 100644 --- a/wormchain/interchaintest/helpers/vaa.go +++ b/wormchain/interchaintest/helpers/vaa.go @@ -17,7 +17,7 @@ func signVaa(vaaToSign vaa.VAA, signers *guardians.ValSet) vaa.VAA { return vaaToSign } -func generateVaa(index uint32, signers *guardians.ValSet, emitterChain vaa.ChainID, emitterAddr vaa.Address, payload []byte) vaa.VAA { +func GenerateVaa(index uint32, signers *guardians.ValSet, emitterChain vaa.ChainID, emitterAddr vaa.Address, payload []byte) vaa.VAA { v := vaa.VAA{ Version: uint8(1), GuardianSetIndex: index, diff --git a/wormchain/interchaintest/slashing_params_update_vaa_test.go b/wormchain/interchaintest/slashing_params_update_vaa_test.go index ce97e5185a..5ba532dbbb 100644 --- a/wormchain/interchaintest/slashing_params_update_vaa_test.go +++ b/wormchain/interchaintest/slashing_params_update_vaa_test.go @@ -73,7 +73,7 @@ func createSlashingParamsUpdate( // querySlashingParams queries the slashing params from the chain func querySlashingParams(ctx context.Context, wormchain *cosmos.CosmosChain) (params slashingtypes.Params, err error) { // query the slashing params - res, _, err := wormchain.GetNode().ExecQuery(ctx, "slashing", "params") + res, _, err := wormchain.GetFullNode().ExecQuery(ctx, "slashing", "params") if err != nil { return } @@ -112,6 +112,36 @@ func querySlashingParams(ctx context.Context, wormchain *cosmos.CosmosChain) (pa return } +// createAndExecuteVaa creates and executes a governance VAA on the wormchain +func createAndExecuteVaa(ctx context.Context, guardians *guardians.ValSet, wormchain *cosmos.CosmosChain, payloadBytes []byte) error { + v := helpers.GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBytes) + vBz, err := v.Marshal() + if err != nil { + return err + } + vHex := hex.EncodeToString(vBz) + + _, err = wormchain.FullNodes[0].ExecTx(ctx, "faucet", "wormhole", "execute-governance-vaa", vHex) + if err != nil { + return err + } + + return nil +} + +func verifyParams(t *testing.T, ctx context.Context, wormchain *cosmos.CosmosChain) { + // query the slashing params + slashingParams, err := querySlashingParams(ctx, wormchain) + require.NoError(t, err) + + // validate the slashing params did not change + require.Equal(t, int64(200), slashingParams.SignedBlocksWindow) + require.Equal(t, "0.100000000000000000", slashingParams.MinSignedPerWindow.String()) + require.Equal(t, 300*time.Second, slashingParams.DowntimeJailDuration) + require.Equal(t, "0.200000000000000000", slashingParams.SlashFractionDoubleSign.String()) + require.Equal(t, "0.300000000000000000", slashingParams.SlashFractionDowntime.String()) +} + // TestSlashingParamsUpdateVaa tests the execution of a slashing params update VAA // and verifies that the governance module correctly updates the slashing params func TestSlashingParamsUpdateVaa(t *testing.T) { @@ -121,35 +151,80 @@ func TestSlashingParamsUpdateVaa(t *testing.T) { t.Parallel() - // Base setup + // base setup guardians := guardians.CreateValSet(t, 2) - chains := CreateLocalChain(t, *guardians) - ic, ctx, _, _, _, _ := BuildInterchain(t, chains) - require.NotNil(t, ic) + chains := CreateChains(t, "local", *guardians) + ctx, _, _, _ := BuildInterchain(t, chains) require.NotNil(t, ctx) wormchain := chains[0].(*cosmos.CosmosChain) - // Create a governance VAA + // ------------------------------ + + // create a governance VAA -- happy path payloadBytes, err := createSlashingParamsUpdate(200, "0.1", 300, "0.2", "0.3") require.NoError(t, err) - v := helpers.GenerateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBytes) - vBz, err := v.Marshal() + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) require.NoError(t, err) - vHex := hex.EncodeToString(vBz) - _, err = wormchain.FullNodes[0].ExecTx(ctx, "faucet", "wormhole", "execute-governance-vaa", vHex) + // verify the slashing params + verifyParams(t, ctx, wormchain) + + // ------------------------------ + + // create a governance VAA - invalid signed blocks window + payloadBytes, err = createSlashingParamsUpdate(0, "0.1", 300, "0.2", "0.3") require.NoError(t, err) - // query the slashing params - slashingParams, err := querySlashingParams(ctx, wormchain) + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) + // TODO: ON COSMOS SDK V0.47 - WILL ERROR require.NoError(t, err) - // validate the slashing params changed - require.Equal(t, int64(200), slashingParams.SignedBlocksWindow) - require.Equal(t, "0.100000000000000000", slashingParams.MinSignedPerWindow.String()) - require.Equal(t, 300*time.Second, slashingParams.DowntimeJailDuration) - require.Equal(t, "0.200000000000000000", slashingParams.SlashFractionDoubleSign.String()) - require.Equal(t, "0.300000000000000000", slashingParams.SlashFractionDowntime.String()) + // verify the slashing params + verifyParams(t, ctx, wormchain) + + // ------------------------------ + + // create a governance VAA - invalid downtime jail duration + payloadBytes, err = createSlashingParamsUpdate(200, "0.1", 0, "0.2", "0.3") + require.NoError(t, err) + + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) + // TODO: ON COSMOS SDK V0.47 - WILL ERROR + require.NoError(t, err) + + // verify the slashing params + verifyParams(t, ctx, wormchain) + + // ------------------------------ + + // create a governance VAA - invalid slash fraction double sign + payloadBytes, err = createSlashingParamsUpdate(200, "0.1", 300, "2.0", "0.3") + require.NoError(t, err) + + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) + // TODO: ON COSMOS SDK V0.47 - WILL ERROR + require.NoError(t, err) + + // verify the slashing params + verifyParams(t, ctx, wormchain) + + // ------------------------------ + + // create a governance VAA - invalid slash fraction downtime + payloadBytes, err = createSlashingParamsUpdate(200, "0.1", 300, "0.2", "2.0") + require.NoError(t, err) + + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) + // TODO: ON COSMOS SDK V0.47 - WILL ERROR + require.NoError(t, err) + + // verify the slashing params + verifyParams(t, ctx, wormchain) } diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go index a94ca322df..13434c5c70 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go @@ -83,10 +83,11 @@ func (k msgServer) ExecuteGovernanceVAA(goCtx context.Context, msg *types.MsgExe ) // Set the new params - err := k.slashingKeeper.SetParams(ctx, params) - if err != nil { - return nil, err - } + // + // TODO: Once upgraded to CosmosSDK v0.47, this method will return an error + // if the params do not pass validation checks. Because of that, we need to + // return the error from this function. + k.slashingKeeper.SetParams(ctx, params) default: return nil, types.ErrUnknownGovernanceAction From 872093853297574cb969e82fe2aaa4a09ec49b1f Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Mon, 16 Dec 2024 13:48:12 -0600 Subject: [PATCH 07/15] Fix Slashing Params VAA Test --- wormchain/testutil/keeper/wormhole.go | 126 ++---------------- .../x/wormhole/keeper/msg_server_test.go | 2 +- 2 files changed, 10 insertions(+), 118 deletions(-) diff --git a/wormchain/testutil/keeper/wormhole.go b/wormchain/testutil/keeper/wormhole.go index dcc9a80164..616b427321 100644 --- a/wormchain/testutil/keeper/wormhole.go +++ b/wormchain/testutil/keeper/wormhole.go @@ -1,140 +1,32 @@ package keeper import ( - "os" "testing" "time" - "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/version" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/wormhole-foundation/wormchain/app" - "github.com/wormhole-foundation/wormchain/app/wasm_handlers" + "github.com/wormhole-foundation/wormchain/app/apptesting" "github.com/wormhole-foundation/wormchain/x/wormhole/keeper" - "github.com/wormhole-foundation/wormchain/x/wormhole/types" - paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - "github.com/stretchr/testify/require" - "github.com/tendermint/spm/cosmoscmd" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmdb "github.com/tendermint/tm-db" ) -func WormholeKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { +func WormholeKeeper(t *testing.T) (*keeper.Keeper, sdk.Context) { k, _, _, ctx := WormholeKeeperAndWasmd(t) return k, ctx } -func WormholeKeeperAndWasmd(t testing.TB) (*keeper.Keeper, wasmkeeper.Keeper, *wasmkeeper.PermissionedKeeper, sdk.Context) { - keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, - paramstypes.StoreKey, - capabilitytypes.StoreKey, - types.StoreKey, - wasmtypes.StoreKey, - ) - tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) - memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, types.MemStoreKey) - maccPerms := map[string][]string{} +func WormholeKeeperAndWasmd(t *testing.T) (*keeper.Keeper, wasmkeeper.Keeper, *wasmkeeper.PermissionedKeeper, sdk.Context) { + app := apptesting.Setup(t, false, 0) - db := tmdb.NewMemDB() - stateStore := store.NewCommitMultiStore(db) - stateStore.MountStoreWithDB(keys[authtypes.StoreKey], sdk.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(keys[paramstypes.StoreKey], sdk.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(keys[capabilitytypes.StoreKey], sdk.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(keys[types.StoreKey], sdk.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(keys[wasmtypes.StoreKey], sdk.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(memKeys[types.MemStoreKey], sdk.StoreTypeMemory, nil) - stateStore.MountStoreWithDB(tkeys[paramstypes.TStoreKey], sdk.StoreTypeTransient, nil) - require.NoError(t, stateStore.LoadLatestVersion()) - - encodingConfig := cosmoscmd.MakeEncodingConfig(app.ModuleBasics) - appCodec := encodingConfig.Marshaler - amino := encodingConfig.Amino - - paramsKeeper := paramskeeper.NewKeeper(appCodec, amino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) - paramsKeeper.Subspace(types.ModuleName) - paramsKeeper.Subspace(wasm.ModuleName) - - paramsKeeper.Subspace(authtypes.ModuleName) - subspace_auth, _ := paramsKeeper.GetSubspace(authtypes.ModuleName) - accountKeeper := authkeeper.NewAccountKeeper( - appCodec, keys[authtypes.StoreKey], subspace_auth, authtypes.ProtoBaseAccount, maccPerms, - ) - // this line is used by starport scaffolding # stargate/app/paramSubspace - - subspaceWasmd, _ := paramsKeeper.GetSubspace(wasmtypes.ModuleName) - - bApp := baseapp.NewBaseApp("wormchain", log.NewNopLogger(), db, encodingConfig.TxConfig.TxDecoder()) - bApp.SetVersion(version.Version) - bApp.SetInterfaceRegistry(encodingConfig.InterfaceRegistry) - - appapp := &app.App{ - BaseApp: bApp, - } - - k := keeper.NewKeeper( - appCodec, - keys[types.StoreKey], - memKeys[types.MemStoreKey], - accountKeeper, - nil, - ) - - supportedFeatures := "iterator,staking,stargate,wormhole" - appapp.WormholeKeeper = *k - - appapp.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) - scopedWasmKeeper := appapp.CapabilityKeeper.ScopeToModule(wasm.ModuleName) - - wasmDir := os.TempDir() - wasmKeeper := wasm.NewKeeper( - appCodec, - keys[wasmtypes.StoreKey], - subspaceWasmd, - accountKeeper, - &wasm_handlers.BankKeeperHandler{}, - &wasm_handlers.StakingKeeperHandler{}, - &wasm_handlers.DistributionKeeperHandler{}, - &wasm_handlers.ChannelKeeperHandler{}, - &wasm_handlers.PortKeeperHandler{}, - scopedWasmKeeper, - &wasm_handlers.ICS20TransferPortSourceHandler{}, - appapp.WormholeKeeper, - appapp.MsgServiceRouter(), - appapp.GRPCQueryRouter(), - wasmDir, - wasm.DefaultWasmConfig(), - supportedFeatures, - wasmkeeper.WithQueryPlugins(keeper.NewCustomQueryHandler(appapp.WormholeKeeper)), - ) - ctx := sdk.NewContext(stateStore, tmproto.Header{ - Time: time.Now(), + ctx := app.BaseApp.NewContext(false, tmproto.Header{ + ChainID: apptesting.SimAppChainID, // The height should be at least 1, because the allowlist antehandler // passes everything at height 0 for gen tx's. Height: 1, - }, false, log.NewNopLogger()) - appapp.MountKVStores(keys) - appapp.MountTransientStores(tkeys) - appapp.MountMemoryStores(memKeys) - - wasmGenState := wasmtypes.GenesisState{} - wasmGenState.Params.CodeUploadAccess = wasmtypes.DefaultUploadAccess - wasmGenState.Params.InstantiateDefaultPermission = wasmtypes.AccessTypeEverybody - wasmKeeper.SetParams(ctx, wasmGenState.Params) - permissionedWasmKeeper := wasmkeeper.NewDefaultPermissionKeeper(wasmKeeper) - appapp.WormholeKeeper.SetWasmdKeeper(permissionedWasmKeeper) - k.SetWasmdKeeper(permissionedWasmKeeper) + Time: time.Now(), + }) - return k, wasmKeeper, permissionedWasmKeeper, ctx + return &app.WormholeKeeper, *app.GetWasmKeeper(), app.ContractKeeper, ctx } diff --git a/wormchain/x/wormhole/keeper/msg_server_test.go b/wormchain/x/wormhole/keeper/msg_server_test.go index 09fe3287d4..723ef7874b 100644 --- a/wormchain/x/wormhole/keeper/msg_server_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_test.go @@ -10,7 +10,7 @@ import ( "github.com/wormhole-foundation/wormchain/x/wormhole/types" ) -func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { +func setupMsgServer(t *testing.T) (types.MsgServer, context.Context) { k, ctx := keepertest.WormholeKeeper(t) return keeper.NewMsgServerImpl(*k), sdk.WrapSDKContext(ctx) } From 1fa4579c6adfcca07ed0b12d8e119e71eda1652b Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Tue, 17 Dec 2024 12:48:04 -0600 Subject: [PATCH 08/15] Fix ICT Workflow --- .github/workflows/wormchain-icts.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/wormchain-icts.yml b/.github/workflows/wormchain-icts.yml index b31d58367c..44f0f7e57d 100644 --- a/.github/workflows/wormchain-icts.yml +++ b/.github/workflows/wormchain-icts.yml @@ -75,6 +75,17 @@ jobs: - name: checkout chain uses: actions/checkout@v4 + - name: Download Tarball Artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.IMAGE_NAME }} + path: /tmp + + - name: Load Docker Image + run: | + docker image load -i ${{ env.TAR_PATH }} + docker image ls -a + - name: Run Test id: run_test continue-on-error: true From 2afe5697d3ada30a9e5a3baefbae9f1d0eea8141 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Thu, 9 Jan 2025 13:31:48 -0600 Subject: [PATCH 09/15] Add range check for sdk.Dec --- wormchain/Dockerfile.ict | 2 +- wormchain/x/wormhole/client/cli/genesis.go | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/wormchain/Dockerfile.ict b/wormchain/Dockerfile.ict index f186b286cc..65c8b86b5f 100644 --- a/wormchain/Dockerfile.ict +++ b/wormchain/Dockerfile.ict @@ -28,7 +28,7 @@ WORKDIR /home/heighliner COPY --from=builder /app/build/wormchaind /usr/bin # copy over c bindings (libwasmvm.x86_64.so, etc) -COPY --from=builder /go/pkg/mod/github.com/!cosm!wasm/wasmvm@v1.1.1/internal/api/* /usr/lib +COPY --from=builder /go/pkg/mod/github.com/!cosm!wasm/wasmvm@v1.1.1/internal/api/* /usr/lib/ EXPOSE 26657 EXPOSE 26656 diff --git a/wormchain/x/wormhole/client/cli/genesis.go b/wormchain/x/wormhole/client/cli/genesis.go index 5d55a37bc5..6fd842c3d9 100644 --- a/wormchain/x/wormhole/client/cli/genesis.go +++ b/wormchain/x/wormhole/client/cli/genesis.go @@ -449,6 +449,9 @@ func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { if err != nil { return err } + if minSignedPerWindowDec.LT(sdk.ZeroDec()) || minSignedPerWindowDec.GT(sdk.OneDec()) { + return fmt.Errorf("min signed per window must be greater than or equal to 0.000000000000000000 and less than or equal to 1.000000000000000000") + } downtimeJailDuration, err := cmd.Flags().GetUint64(FLAG_DOWNTIME_JAIL_DURATION) if err != nil { @@ -463,6 +466,9 @@ func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { if err != nil { return err } + if slashFractionDoubleSignDec.LT(sdk.ZeroDec()) || slashFractionDoubleSignDec.GT(sdk.OneDec()) { + return fmt.Errorf("slash fraction double sign must be greater than or equal to 0.000000000000000000 and less than or equal to 1.000000000000000000") + } slashFractionDowntime, err := cmd.Flags().GetString(FLAG_SLASH_FRACTION_DOWNTIME) if err != nil { @@ -472,6 +478,9 @@ func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { if err != nil { return err } + if slashFractionDowntimeDec.LT(sdk.ZeroDec()) || slashFractionDowntimeDec.GT(sdk.OneDec()) { + return fmt.Errorf("slash fraction downtime must be greater than or equal to 0.000000000000000000 and less than or equal to 1.000000000000000000") + } slashingUpdate := make([]byte, 40) binary.BigEndian.PutUint64(slashingUpdate[:8], signedBlocksWindow) From 635379cbe671929764830abbc22ccca8a840a74c Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Fri, 10 Jan 2025 12:51:09 -0600 Subject: [PATCH 10/15] Add BodySlashingParamsUpdate Notes --- sdk/vaa/payloads.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sdk/vaa/payloads.go b/sdk/vaa/payloads.go index b62b1ba4d1..dc7d887b75 100644 --- a/sdk/vaa/payloads.go +++ b/sdk/vaa/payloads.go @@ -128,6 +128,24 @@ type ( NewIndex uint32 } + // BodySlashingParamsUpdate is a governance message to update the slashing parameters on Wormchain. + // + // It is important to note that the slashing keeper only accepts `int64` values as input, so we need to convert + // the `uint64` values to `int64` before passing them to the keeper. This conversion can introduce overflow + // issues if the `uint64` values are too large. To combat this, the Wormchain CLI and the slashing keeper run + // validation checks on the new parameter values. + // + // Below documents the entire process of updating the slashing parameters: + // 1. The CLI command receives the new slashing parameters from the user as `uint64` values for `SignedBlocksWindow` and `DowntimeJailDuration` and as `string` values + // for `MinSignedPerWindow`, `SlashFractionDoubleSign`, and `SlashFractionDowntime`. The command accepts `string` values for ease of use when providing decimal values. + // 2. The CLI command converts the `string` values into `sdk.Dec` values and then into `uint64` values. + // 3. The CLI command validates that the `uint64` values are within the acceptable range for the slashing parameters. + // 4. The CLI command serializes the new slashing parameters into a governance VAA. + // 5. The governance VAA is signed & broadcasted to the Wormchain. + // 6. Wormchain deserializes the governance VAA and extracts every new slashing parameter as a uint64 value. + // 7. Wormchain converts the uint64 values to int64 values and passes them to the slashing keeper. + // 8. The slashing keeper runs validation checks on the new slashing parameters and throws an error if they are invalid. + // 9. If the new slashing parameters pass the validation checks, the slashing keeper updates its parameters. BodySlashingParamsUpdate struct { SignedBlocksWindow uint64 MinSignedPerWindow uint64 From 51aee11788e5cb2db1cc215ad878db09e5e7839a Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Wed, 15 Jan 2025 12:03:36 -0600 Subject: [PATCH 11/15] Cleanup --- .../slashing_params_update_vaa_test.go | 14 ++++++++++++++ wormchain/x/wormhole/client/cli/genesis.go | 4 ++-- .../x/wormhole/keeper/msg_server_allowlist_test.go | 3 +-- .../msg_server_execute_governance_vaa_test.go | 2 -- .../x/wormhole/keeper/msg_server_wasmd_test.go | 2 -- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/wormchain/interchaintest/slashing_params_update_vaa_test.go b/wormchain/interchaintest/slashing_params_update_vaa_test.go index 5ba532dbbb..476c153dbb 100644 --- a/wormchain/interchaintest/slashing_params_update_vaa_test.go +++ b/wormchain/interchaintest/slashing_params_update_vaa_test.go @@ -227,4 +227,18 @@ func TestSlashingParamsUpdateVaa(t *testing.T) { // verify the slashing params verifyParams(t, ctx, wormchain) + + // ------------------------------ + + // create a governance VAA - negative string values + payloadBytes, err = createSlashingParamsUpdate(200, "-0.1", 300, "-0.2", "-2.0") + require.NoError(t, err) + + // create and send + err = createAndExecuteVaa(ctx, guardians, wormchain, payloadBytes) + // TODO: ON COSMOS SDK V0.47 - WILL ERROR + require.NoError(t, err) + + // verify the slashing params + verifyParams(t, ctx, wormchain) } diff --git a/wormchain/x/wormhole/client/cli/genesis.go b/wormchain/x/wormhole/client/cli/genesis.go index 6fd842c3d9..a2af8f540d 100644 --- a/wormchain/x/wormhole/client/cli/genesis.go +++ b/wormchain/x/wormhole/client/cli/genesis.go @@ -384,7 +384,7 @@ func CmdGenerateGuardianSetUpdatea() *cobra.Command { } action := vaa.ActionGuardianSetUpdate - chain := 3104 + chain := vaa.ChainIDWormchain module := [32]byte{} copy(module[:], vaa.CoreModule) msg := types.NewGovernanceMessage(module, byte(action), uint16(chain), set_update) @@ -490,7 +490,7 @@ func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { binary.BigEndian.PutUint64(slashingUpdate[32:40], slashFractionDowntimeDec.BigInt().Uint64()) action := vaa.ActionSlashingParamsUpdate - chain := 3104 + chain := vaa.ChainIDWormchain module := [32]byte{} copy(module[:], vaa.CoreModule) msg := types.NewGovernanceMessage(module, byte(action), uint16(chain), slashingUpdate) diff --git a/wormchain/x/wormhole/keeper/msg_server_allowlist_test.go b/wormchain/x/wormhole/keeper/msg_server_allowlist_test.go index 9087fd78f3..c5ea497411 100644 --- a/wormchain/x/wormhole/keeper/msg_server_allowlist_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_allowlist_test.go @@ -178,8 +178,7 @@ func TestAllowlistEntry(t *testing.T) { func TestAllowlistEntryAnteHandler(t *testing.T) { k, ctx := keepertest.WormholeKeeper(t) - guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - _ = privateKeys + guardians, _ := createNGuardianValidator(k, ctx, 10) k.SetConfig(ctx, types.Config{ GovernanceEmitter: vaa.GovernanceEmitter[:], GovernanceChain: uint32(vaa.GovernanceChain), diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go index 9e876db5ab..93c3b0828a 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go @@ -35,7 +35,6 @@ func createExecuteGovernanceVaaPayload(k *keeper.Keeper, ctx sdk.Context, num_gu func TestExecuteGovernanceVAA(t *testing.T) { k, ctx := keepertest.WormholeKeeper(t) guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - _ = privateKeys k.SetConfig(ctx, types.Config{ GovernanceEmitter: vaa.GovernanceEmitter[:], GovernanceChain: uint32(vaa.GovernanceChain), @@ -136,7 +135,6 @@ func createSlashingParamsUpdatePayload() []byte { func TestExecuteSlashingParamsUpdate(t *testing.T) { k, ctx := keepertest.WormholeKeeper(t) guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - _ = privateKeys k.SetConfig(ctx, types.Config{ GovernanceEmitter: vaa.GovernanceEmitter[:], GovernanceChain: uint32(vaa.GovernanceChain), diff --git a/wormchain/x/wormhole/keeper/msg_server_wasmd_test.go b/wormchain/x/wormhole/keeper/msg_server_wasmd_test.go index d78c0cab52..7cacb2ec0a 100644 --- a/wormchain/x/wormhole/keeper/msg_server_wasmd_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_wasmd_test.go @@ -134,7 +134,6 @@ func setupAccountantAndGuardianSet(t *testing.T, ctx sdk.Context, k *keeper.Keep func TestWasmdStoreCode(t *testing.T) { k, ctx := keepertest.WormholeKeeper(t) guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - _ = privateKeys k.SetConfig(ctx, types.Config{ GovernanceEmitter: vaa.GovernanceEmitter[:], GovernanceChain: uint32(vaa.GovernanceChain), @@ -203,7 +202,6 @@ func TestWasmdStoreCode(t *testing.T) { func TestWasmdInstantiateContract(t *testing.T) { k, ctx := keepertest.WormholeKeeper(t) guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - _ = privateKeys k.SetConfig(ctx, types.Config{ GovernanceEmitter: vaa.GovernanceEmitter[:], GovernanceChain: uint32(vaa.GovernanceChain), From 30efe59cdf0077c8708c22a04ee6a8c90a8ea1ba Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Thu, 23 Jan 2025 11:31:13 -0600 Subject: [PATCH 12/15] fix upload artifact Also removes flaky CI tests. --- .github/workflows/wormchain-icts.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wormchain-icts.yml b/.github/workflows/wormchain-icts.yml index bfba0f8af1..d9cd071b12 100644 --- a/.github/workflows/wormchain-icts.yml +++ b/.github/workflows/wormchain-icts.yml @@ -46,7 +46,7 @@ jobs: outputs: type=docker,dest=${{ env.TAR_PATH }} - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.IMAGE_NAME }} path: ${{ env.TAR_PATH }} @@ -62,7 +62,8 @@ jobs: - "ictest-slashing-params-update-vaa" - "ictest-upgrade" - "ictest-wormchain" - - "ictest-ibc-receiver" + # Disabled due to flakiness in CI. + # - "ictest-ibc-receiver" - "ictest-cw-wormhole" fail-fast: false From 24ab29d848ce659bb9269a140f1788ac8da4006d Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Thu, 23 Jan 2025 11:38:12 -0600 Subject: [PATCH 13/15] fix download artifact --- .github/workflows/wormchain-icts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wormchain-icts.yml b/.github/workflows/wormchain-icts.yml index d9cd071b12..77eb9083ac 100644 --- a/.github/workflows/wormchain-icts.yml +++ b/.github/workflows/wormchain-icts.yml @@ -78,7 +78,7 @@ jobs: uses: actions/checkout@v4 - name: Download Tarball Artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.IMAGE_NAME }} path: /tmp From b8eafd1453384c915cf07dd8cadcd42cb571be32 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Thu, 23 Jan 2025 11:52:14 -0600 Subject: [PATCH 14/15] Fix GenerateVaa in ICT --- wormchain/interchaintest/helpers/vaa.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wormchain/interchaintest/helpers/vaa.go b/wormchain/interchaintest/helpers/vaa.go index 26cf28411f..c327651eba 100644 --- a/wormchain/interchaintest/helpers/vaa.go +++ b/wormchain/interchaintest/helpers/vaa.go @@ -58,7 +58,7 @@ func GenerateEmptyVAA( payloadBz, err := vaa.EmptyPayloadVaa(moduleStr, action, chainID) require.NoError(t, err) - v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) + v := GenerateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz) v = signVaa(v, guardians) vBz, err := v.Marshal() From 9e88ce5efd0ebd196f4839a71a7a471f8e43c439 Mon Sep 17 00:00:00 2001 From: Joel Smith Date: Wed, 5 Feb 2025 12:27:13 -0600 Subject: [PATCH 15/15] Switch to Gateway Governance Module --- sdk/vaa/payloads.go | 106 +++++++++--------- sdk/vaa/payloads_test.go | 78 +++++++++---- .../slashing_params_update_vaa_test.go | 25 ++--- wormchain/x/wormhole/client/cli/genesis.go | 26 ++--- ...g_server_execute_gateway_governance_vaa.go | 30 +++++ ...ver_execute_gateway_governance_vaa_test.go | 52 +++++++++ .../msg_server_execute_governance_vaa.go | 29 ----- .../msg_server_execute_governance_vaa_test.go | 54 --------- 8 files changed, 216 insertions(+), 184 deletions(-) create mode 100644 wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa_test.go diff --git a/sdk/vaa/payloads.go b/sdk/vaa/payloads.go index dc7d887b75..b28ff4f551 100644 --- a/sdk/vaa/payloads.go +++ b/sdk/vaa/payloads.go @@ -69,12 +69,11 @@ type GovernanceAction uint8 var ( // Wormhole core governance actions // See e.g. GovernanceStructs.sol for semantic meaning of these - ActionContractUpgrade GovernanceAction = 1 - ActionGuardianSetUpdate GovernanceAction = 2 - ActionCoreSetMessageFee GovernanceAction = 3 - ActionCoreTransferFees GovernanceAction = 4 - ActionCoreRecoverChainId GovernanceAction = 5 - ActionSlashingParamsUpdate GovernanceAction = 6 + ActionContractUpgrade GovernanceAction = 1 + ActionGuardianSetUpdate GovernanceAction = 2 + ActionCoreSetMessageFee GovernanceAction = 3 + ActionCoreTransferFees GovernanceAction = 4 + ActionCoreRecoverChainId GovernanceAction = 5 // Wormchain cosmwasm/middleware governance actions ActionStoreCode GovernanceAction = 1 @@ -87,6 +86,7 @@ var ( ActionScheduleUpgrade GovernanceAction = 1 ActionCancelUpgrade GovernanceAction = 2 ActionSetIbcComposabilityMwContract GovernanceAction = 3 + ActionSlashingParamsUpdate GovernanceAction = 4 // Accountant governance actions ActionModifyBalance GovernanceAction = 1 @@ -128,32 +128,6 @@ type ( NewIndex uint32 } - // BodySlashingParamsUpdate is a governance message to update the slashing parameters on Wormchain. - // - // It is important to note that the slashing keeper only accepts `int64` values as input, so we need to convert - // the `uint64` values to `int64` before passing them to the keeper. This conversion can introduce overflow - // issues if the `uint64` values are too large. To combat this, the Wormchain CLI and the slashing keeper run - // validation checks on the new parameter values. - // - // Below documents the entire process of updating the slashing parameters: - // 1. The CLI command receives the new slashing parameters from the user as `uint64` values for `SignedBlocksWindow` and `DowntimeJailDuration` and as `string` values - // for `MinSignedPerWindow`, `SlashFractionDoubleSign`, and `SlashFractionDowntime`. The command accepts `string` values for ease of use when providing decimal values. - // 2. The CLI command converts the `string` values into `sdk.Dec` values and then into `uint64` values. - // 3. The CLI command validates that the `uint64` values are within the acceptable range for the slashing parameters. - // 4. The CLI command serializes the new slashing parameters into a governance VAA. - // 5. The governance VAA is signed & broadcasted to the Wormchain. - // 6. Wormchain deserializes the governance VAA and extracts every new slashing parameter as a uint64 value. - // 7. Wormchain converts the uint64 values to int64 values and passes them to the slashing keeper. - // 8. The slashing keeper runs validation checks on the new slashing parameters and throws an error if they are invalid. - // 9. If the new slashing parameters pass the validation checks, the slashing keeper updates its parameters. - BodySlashingParamsUpdate struct { - SignedBlocksWindow uint64 - MinSignedPerWindow uint64 - DowntimeJailDuration uint64 - SlashFractionDoubleSign uint64 - SlashFractionDowntime uint64 - } - // BodyTokenBridgeRegisterChain is a governance message to register a chain on the token bridge BodyTokenBridgeRegisterChain struct { Module string @@ -220,6 +194,32 @@ type ( ContractAddr [32]byte } + // BodyGatewaySlashingParamsUpdate is a governance message to update the slashing parameters on Wormchain. + // + // It is important to note that the slashing keeper only accepts `int64` values as input, so we need to convert + // the `uint64` values to `int64` before passing them to the keeper. This conversion can introduce overflow + // issues if the `uint64` values are too large. To combat this, the Wormchain CLI and the slashing keeper run + // validation checks on the new parameter values. + // + // Below documents the entire process of updating the slashing parameters: + // 1. The CLI command receives the new slashing parameters from the user as `uint64` values for `SignedBlocksWindow` and `DowntimeJailDuration` and as `string` values + // for `MinSignedPerWindow`, `SlashFractionDoubleSign`, and `SlashFractionDowntime`. The command accepts `string` values for ease of use when providing decimal values. + // 2. The CLI command converts the `string` values into `sdk.Dec` values and then into `uint64` values. + // 3. The CLI command validates that the `uint64` values are within the acceptable range for the slashing parameters. + // 4. The CLI command serializes the new slashing parameters into a governance VAA. + // 5. The governance VAA is signed & broadcasted to the Wormchain. + // 6. Wormchain deserializes the governance VAA and extracts every new slashing parameter as a uint64 value. + // 7. Wormchain converts the uint64 values to int64 values and passes them to the slashing keeper. + // 8. The slashing keeper runs validation checks on the new slashing parameters and throws an error if they are invalid. + // 9. If the new slashing parameters pass the validation checks, the slashing keeper updates its parameters. + BodyGatewaySlashingParamsUpdate struct { + SignedBlocksWindow uint64 + MinSignedPerWindow uint64 + DowntimeJailDuration uint64 + SlashFractionDoubleSign uint64 + SlashFractionDowntime uint64 + } + // BodyCircleIntegrationUpdateWormholeFinality is a governance message to update the wormhole finality for Circle Integration. BodyCircleIntegrationUpdateWormholeFinality struct { TargetChainID ChainID @@ -310,25 +310,6 @@ func (b BodyGuardianSetUpdate) Serialize() ([]byte, error) { return buf.Bytes(), nil } -func (b BodySlashingParamsUpdate) Serialize() ([]byte, error) { - buf := new(bytes.Buffer) - - // Module - buf.Write(CoreModule) - // // Action - MustWrite(buf, binary.BigEndian, ActionSlashingParamsUpdate) - // // ChainID - 0 for universal - MustWrite(buf, binary.BigEndian, uint16(0)) - - MustWrite(buf, binary.BigEndian, b.SignedBlocksWindow) - MustWrite(buf, binary.BigEndian, b.MinSignedPerWindow) - MustWrite(buf, binary.BigEndian, b.DowntimeJailDuration) - MustWrite(buf, binary.BigEndian, b.SlashFractionDoubleSign) - MustWrite(buf, binary.BigEndian, b.SlashFractionDowntime) - - return buf.Bytes(), nil -} - func (r BodyTokenBridgeRegisterChain) Serialize() ([]byte, error) { payload := &bytes.Buffer{} MustWrite(payload, binary.BigEndian, r.ChainID) @@ -439,6 +420,29 @@ func (r *BodyGatewayIbcComposabilityMwContract) Deserialize(bz []byte) error { return nil } +func (b BodyGatewaySlashingParamsUpdate) Serialize() ([]byte, error) { + payload := new(bytes.Buffer) + MustWrite(payload, binary.BigEndian, b.SignedBlocksWindow) + MustWrite(payload, binary.BigEndian, b.MinSignedPerWindow) + MustWrite(payload, binary.BigEndian, b.DowntimeJailDuration) + MustWrite(payload, binary.BigEndian, b.SlashFractionDoubleSign) + MustWrite(payload, binary.BigEndian, b.SlashFractionDowntime) + return serializeBridgeGovernanceVaa(GatewayModuleStr, ActionSlashingParamsUpdate, ChainIDWormchain, payload.Bytes()) +} + +func (r *BodyGatewaySlashingParamsUpdate) Deserialize(bz []byte) error { + if len(bz) != 40 { + return fmt.Errorf("incorrect payload length, should be 40, is %d", len(bz)) + } + + r.SignedBlocksWindow = binary.BigEndian.Uint64(bz[0:8]) + r.MinSignedPerWindow = binary.BigEndian.Uint64(bz[8:16]) + r.DowntimeJailDuration = binary.BigEndian.Uint64(bz[16:24]) + r.SlashFractionDoubleSign = binary.BigEndian.Uint64(bz[24:32]) + r.SlashFractionDowntime = binary.BigEndian.Uint64(bz[32:40]) + return nil +} + func (r BodyGatewayScheduleUpgrade) Serialize() ([]byte, error) { payload := &bytes.Buffer{} payload.Write([]byte(r.Name)) diff --git a/sdk/vaa/payloads_test.go b/sdk/vaa/payloads_test.go index 23d8284cd0..9333233017 100644 --- a/sdk/vaa/payloads_test.go +++ b/sdk/vaa/payloads_test.go @@ -74,27 +74,6 @@ func TestBodyGuardianSetUpdateSerialize(t *testing.T) { assert.Equal(t, expected, hex.EncodeToString(serializedBodyGuardianSetUpdate)) } -func TestBodySlashingParamsUpdateSerialize(t *testing.T) { - signedBlocksWindow := uint64(100) - minSignedPerWindow := uint64(500000000000000000) - downtimeJailDuration := uint64(600 * time.Second) - slashFractionDoubleSign := uint64(50000000000000000) - slashFractionDowntime := uint64(10000000000000000) - - bodySlashingParamsUpdate := BodySlashingParamsUpdate{ - SignedBlocksWindow: signedBlocksWindow, - MinSignedPerWindow: minSignedPerWindow, - DowntimeJailDuration: downtimeJailDuration, - SlashFractionDoubleSign: slashFractionDoubleSign, - SlashFractionDowntime: slashFractionDowntime, - } - serializedBody, err := bodySlashingParamsUpdate.Serialize() - require.NoError(t, err) - - expected := "00000000000000000000000000000000000000000000000000000000436f7265060000000000000000006406f05b59d3b200000000008bb2c9700000b1a2bc2ec50000002386f26fc10000" - assert.Equal(t, expected, hex.EncodeToString(serializedBody)) -} - func TestBodyTokenBridgeRegisterChainSerialize(t *testing.T) { module := "test" tests := []struct { @@ -385,6 +364,63 @@ func TestBodyGatewayIbcComposabilityMwContractDeserializeFailureTooLong(t *testi require.ErrorContains(t, err, "incorrect payload length, should be 32, is 33") } +func TestBodySlashingParamsUpdateSerialize(t *testing.T) { + signedBlocksWindow := uint64(100) + minSignedPerWindow := uint64(500000000000000000) + downtimeJailDuration := uint64(600 * time.Second) + slashFractionDoubleSign := uint64(50000000000000000) + slashFractionDowntime := uint64(10000000000000000) + + bodySlashingParamsUpdate := BodyGatewaySlashingParamsUpdate{ + SignedBlocksWindow: signedBlocksWindow, + MinSignedPerWindow: minSignedPerWindow, + DowntimeJailDuration: downtimeJailDuration, + SlashFractionDoubleSign: slashFractionDoubleSign, + SlashFractionDowntime: slashFractionDowntime, + } + serializedBody, err := bodySlashingParamsUpdate.Serialize() + require.NoError(t, err) + + expected := "00000000000000000000000000000000000000476174657761794d6f64756c65040c20000000000000006406f05b59d3b200000000008bb2c9700000b1a2bc2ec50000002386f26fc10000" + assert.Equal(t, expected, hex.EncodeToString(serializedBody)) +} + +const BodySlashingParamsUpdateBuf = "000000000000006406f05b59d3b200000000008bb2c9700000b1a2bc2ec50000002386f26fc10000" + +func TestBodySlashingParamsUpdateDeserialize(t *testing.T) { + expected := BodyGatewaySlashingParamsUpdate{ + SignedBlocksWindow: 100, + MinSignedPerWindow: 500000000000000000, + DowntimeJailDuration: uint64(600 * time.Second), + SlashFractionDoubleSign: 50000000000000000, + SlashFractionDowntime: 10000000000000000, + } + var payloadBody BodyGatewaySlashingParamsUpdate + bz, err := hex.DecodeString(BodySlashingParamsUpdateBuf) + require.NoError(t, err) + err = payloadBody.Deserialize(bz) + require.NoError(t, err) + assert.Equal(t, expected, payloadBody) +} + +func TestBodySlashingParamsUpdateDeserializeFailureTooShort(t *testing.T) { + buf, err := hex.DecodeString(BodySlashingParamsUpdateBuf[0 : len(BodySlashingParamsUpdateBuf)-2]) + require.NoError(t, err) + + var actual BodyGatewaySlashingParamsUpdate + err = actual.Deserialize(buf) + require.ErrorContains(t, err, "incorrect payload length, should be 40, is 39") +} + +func TestBodySlashingParamsUpdateDeserializeFailureTooLong(t *testing.T) { + buf, err := hex.DecodeString(BodySlashingParamsUpdateBuf + "00") + require.NoError(t, err) + + var actual BodyGatewaySlashingParamsUpdate + err = actual.Deserialize(buf) + require.ErrorContains(t, err, "incorrect payload length, should be 40, is 41") +} + func TestBodyCoreRecoverChainIdSerialize(t *testing.T) { expected := "00000000000000000000000000000000000000000000000000000000436f72650500000000000000000000000000000000000000000000000000000000000000010fa0" BodyRecoverChainId := BodyRecoverChainId{ diff --git a/wormchain/interchaintest/slashing_params_update_vaa_test.go b/wormchain/interchaintest/slashing_params_update_vaa_test.go index 476c153dbb..c18f642f57 100644 --- a/wormchain/interchaintest/slashing_params_update_vaa_test.go +++ b/wormchain/interchaintest/slashing_params_update_vaa_test.go @@ -2,7 +2,6 @@ package ictest import ( "context" - "encoding/binary" "encoding/hex" "encoding/json" "strconv" @@ -15,7 +14,6 @@ import ( "github.com/stretchr/testify/require" "github.com/wormhole-foundation/wormchain/interchaintest/guardians" "github.com/wormhole-foundation/wormchain/interchaintest/helpers" - types "github.com/wormhole-foundation/wormchain/x/wormhole/types" "github.com/wormhole-foundation/wormhole/sdk/vaa" ) @@ -37,9 +35,6 @@ func createSlashingParamsUpdate( slashFractionDoubleSign string, slashFractionDowntime string, ) ([]byte, error) { - var coreModule [32]byte - copy(coreModule[:], vaa.CoreModule[:]) - minSignedWindow, err := sdk.NewDecFromStr(minSignedPerWindow) if err != nil { return nil, err @@ -57,17 +52,15 @@ func createSlashingParamsUpdate( return nil, err } - payload := make([]byte, 40) - binary.BigEndian.PutUint64(payload[0:8], signedBlocksWindow) - binary.BigEndian.PutUint64(payload[8:16], minSignedWindow.BigInt().Uint64()) - binary.BigEndian.PutUint64(payload[16:24], downtimeJailDurationSeconds) - binary.BigEndian.PutUint64(payload[24:32], slashFractionDoubleSignDec.BigInt().Uint64()) - binary.BigEndian.PutUint64(payload[32:40], slashFractionDowntimeDec.BigInt().Uint64()) - - gov_msg := types.NewGovernanceMessage(coreModule, byte(vaa.ActionSlashingParamsUpdate), uint16(vaa.ChainIDWormchain), - payload) + payloadBody := vaa.BodyGatewaySlashingParamsUpdate{ + SignedBlocksWindow: signedBlocksWindow, + MinSignedPerWindow: minSignedWindow.BigInt().Uint64(), + DowntimeJailDuration: downtimeJailDurationSeconds, + SlashFractionDoubleSign: slashFractionDoubleSignDec.BigInt().Uint64(), + SlashFractionDowntime: slashFractionDowntimeDec.BigInt().Uint64(), + } - return gov_msg.MarshalBinary(), nil + return payloadBody.Serialize() } // querySlashingParams queries the slashing params from the chain @@ -121,7 +114,7 @@ func createAndExecuteVaa(ctx context.Context, guardians *guardians.ValSet, wormc } vHex := hex.EncodeToString(vBz) - _, err = wormchain.FullNodes[0].ExecTx(ctx, "faucet", "wormhole", "execute-governance-vaa", vHex) + _, err = wormchain.FullNodes[0].ExecTx(ctx, "faucet", "wormhole", "execute-gateway-governance-vaa", vHex) if err != nil { return err } diff --git a/wormchain/x/wormhole/client/cli/genesis.go b/wormchain/x/wormhole/client/cli/genesis.go index a2af8f540d..b74e949a87 100644 --- a/wormchain/x/wormhole/client/cli/genesis.go +++ b/wormchain/x/wormhole/client/cli/genesis.go @@ -482,19 +482,19 @@ func CmdGenerateSlashingParamsUpdateVaa() *cobra.Command { return fmt.Errorf("slash fraction downtime must be greater than or equal to 0.000000000000000000 and less than or equal to 1.000000000000000000") } - slashingUpdate := make([]byte, 40) - binary.BigEndian.PutUint64(slashingUpdate[:8], signedBlocksWindow) - binary.BigEndian.PutUint64(slashingUpdate[8:16], minSignedPerWindowDec.BigInt().Uint64()) - binary.BigEndian.PutUint64(slashingUpdate[16:24], downtimeJailDuration*uint64(time.Second)) - binary.BigEndian.PutUint64(slashingUpdate[24:32], slashFractionDoubleSignDec.BigInt().Uint64()) - binary.BigEndian.PutUint64(slashingUpdate[32:40], slashFractionDowntimeDec.BigInt().Uint64()) - - action := vaa.ActionSlashingParamsUpdate - chain := vaa.ChainIDWormchain - module := [32]byte{} - copy(module[:], vaa.CoreModule) - msg := types.NewGovernanceMessage(module, byte(action), uint16(chain), slashingUpdate) - v.Payload = msg.MarshalBinary() + slashingBody := vaa.BodyGatewaySlashingParamsUpdate{ + SignedBlocksWindow: signedBlocksWindow, + MinSignedPerWindow: minSignedPerWindowDec.BigInt().Uint64(), + DowntimeJailDuration: downtimeJailDuration * uint64(time.Second), + SlashFractionDoubleSign: slashFractionDoubleSignDec.BigInt().Uint64(), + SlashFractionDowntime: slashFractionDowntimeDec.BigInt().Uint64(), + } + payload, err := slashingBody.Serialize() + if err != nil { + return + } + + v.Payload = payload v.EmitterChain = 1 for i, key := range privateKeys { diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa.go index 415a8b387e..611d068734 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa.go @@ -2,9 +2,11 @@ package keeper import ( "context" + "time" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/wormhole-foundation/wormchain/x/wormhole/types" @@ -48,6 +50,8 @@ func (k msgServer) ExecuteGatewayGovernanceVaa( return k.cancelUpgrade(ctx) case vaa.ActionSetIbcComposabilityMwContract: return k.setIbcComposabilityMwContract(ctx, payload) + case vaa.ActionSlashingParamsUpdate: + return k.setSlashingParams(ctx, payload) default: return nil, types.ErrUnknownGovernanceAction } @@ -100,3 +104,29 @@ func (k msgServer) setIbcComposabilityMwContract( return &types.EmptyResponse{}, nil } + +func (k msgServer) setSlashingParams( + ctx sdk.Context, + payload []byte, +) (*types.EmptyResponse, error) { + var payloadBody vaa.BodyGatewaySlashingParamsUpdate + payloadBody.Deserialize(payload) + + // Update slashing params + params := slashingtypes.NewParams( + int64(payloadBody.SignedBlocksWindow), + sdk.NewDecWithPrec(int64(payloadBody.MinSignedPerWindow), 18), + time.Duration(int64(payloadBody.DowntimeJailDuration)), + sdk.NewDecWithPrec(int64(payloadBody.SlashFractionDoubleSign), 18), + sdk.NewDecWithPrec(int64(payloadBody.SlashFractionDowntime), 18), + ) + + // Set the new params + // + // TODO: Once upgraded to CosmosSDK v0.47, this method will return an error + // if the params do not pass validation checks. Because of that, we need to + // return the error from this function. + k.slashingKeeper.SetParams(ctx, params) + + return &types.EmptyResponse{}, nil +} diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa_test.go b/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa_test.go new file mode 100644 index 0000000000..6450e4a52a --- /dev/null +++ b/wormchain/x/wormhole/keeper/msg_server_execute_gateway_governance_vaa_test.go @@ -0,0 +1,52 @@ +package keeper_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + keepertest "github.com/wormhole-foundation/wormchain/testutil/keeper" + "github.com/wormhole-foundation/wormchain/x/wormhole/keeper" + "github.com/wormhole-foundation/wormchain/x/wormhole/types" + "github.com/wormhole-foundation/wormhole/sdk/vaa" +) + +func TestExecuteSlashingParamsUpdate(t *testing.T) { + k, ctx := keepertest.WormholeKeeper(t) + guardians, privateKeys := createNGuardianValidator(k, ctx, 10) + k.SetConfig(ctx, types.Config{ + GovernanceEmitter: vaa.GovernanceEmitter[:], + GovernanceChain: uint32(vaa.GovernanceChain), + ChainId: uint32(vaa.ChainIDWormchain), + GuardianSetExpiration: 86400, + }) + signer_bz := [20]byte{} + signer := sdk.AccAddress(signer_bz[:]) + + set := createNewGuardianSet(k, ctx, guardians) + k.SetConsensusGuardianSetIndex(ctx, types.ConsensusGuardianSetIndex{Index: set.Index}) + + context := sdk.WrapSDKContext(ctx) + msgServer := keeper.NewMsgServerImpl(*k) + + // create governance to update slashing params + payloadBody := vaa.BodyGatewaySlashingParamsUpdate{ + SignedBlocksWindow: uint64(100), + MinSignedPerWindow: sdk.NewDecWithPrec(5, 1).BigInt().Uint64(), + DowntimeJailDuration: uint64(600 * time.Second), + SlashFractionDoubleSign: sdk.NewDecWithPrec(5, 2).BigInt().Uint64(), + SlashFractionDowntime: sdk.NewDecWithPrec(1, 2).BigInt().Uint64(), + } + payloadBz, err := payloadBody.Serialize() + assert.NoError(t, err) + + v := generateVaa(set.Index, privateKeys, vaa.ChainID(vaa.GovernanceChain), payloadBz) + vBz, _ := v.Marshal() + res, err := msgServer.ExecuteGatewayGovernanceVaa(context, &types.MsgExecuteGatewayGovernanceVaa{ + Signer: signer.String(), + Vaa: vBz, + }) + assert.NoError(t, err) + assert.Equal(t, &types.EmptyResponse{}, res) +} diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go index 13434c5c70..d4d7e05a39 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa.go @@ -3,10 +3,8 @@ package keeper import ( "context" "encoding/binary" - "time" sdk "github.com/cosmos/cosmos-sdk/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/wormhole-foundation/wormchain/x/wormhole/types" "github.com/wormhole-foundation/wormhole/sdk/vaa" ) @@ -61,33 +59,6 @@ func (k msgServer) ExecuteGovernanceVAA(goCtx context.Context, msg *types.MsgExe if err != nil { return nil, err } - case vaa.ActionSlashingParamsUpdate: - if len(payload) != 40 { - return nil, types.ErrInvalidGovernancePayloadLength - } - - // Extract params from payload - signedBlocksWindow := int64(binary.BigEndian.Uint64(payload[:8])) - minSignedPerWindow := int64(binary.BigEndian.Uint64(payload[8:16])) - downtimeJailDuration := int64(binary.BigEndian.Uint64(payload[16:24])) - slashFractionDoubleSign := int64(binary.BigEndian.Uint64(payload[24:32])) - slashFractionDowntime := int64(binary.BigEndian.Uint64(payload[32:40])) - - // Update slashing params - params := slashingtypes.NewParams( - signedBlocksWindow, - sdk.NewDecWithPrec(minSignedPerWindow, 18), - time.Duration(downtimeJailDuration), - sdk.NewDecWithPrec(slashFractionDoubleSign, 18), - sdk.NewDecWithPrec(slashFractionDowntime, 18), - ) - - // Set the new params - // - // TODO: Once upgraded to CosmosSDK v0.47, this method will return an error - // if the params do not pass validation checks. Because of that, we need to - // return the error from this function. - k.slashingKeeper.SetParams(ctx, params) default: return nil, types.ErrUnknownGovernanceAction diff --git a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go index 93c3b0828a..5e35b2a859 100644 --- a/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go +++ b/wormchain/x/wormhole/keeper/msg_server_execute_governance_vaa_test.go @@ -4,7 +4,6 @@ import ( "crypto/ecdsa" "encoding/binary" "testing" - "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" @@ -107,56 +106,3 @@ func TestExecuteGovernanceVAA(t *testing.T) { new_index2 := k.GetLatestGuardianSetIndex(ctx) assert.Equal(t, new_set.Index+1, new_index2) } - -func createSlashingParamsUpdatePayload() []byte { - // 5 int64 values - slashingParams := make([]byte, 40) - - signedBlocksWindow := uint64(100) - minSignedPerWindow := sdk.NewDecWithPrec(5, 1).BigInt().Uint64() - downtimeJailDuration := uint64(600 * time.Second) - slashFractionDoubleSign := sdk.NewDecWithPrec(5, 2).BigInt().Uint64() - slashFractionDowntime := sdk.NewDecWithPrec(1, 2).BigInt().Uint64() - - binary.BigEndian.PutUint64(slashingParams, signedBlocksWindow) - binary.BigEndian.PutUint64(slashingParams[8:], minSignedPerWindow) - binary.BigEndian.PutUint64(slashingParams[16:], downtimeJailDuration) - binary.BigEndian.PutUint64(slashingParams[24:], slashFractionDoubleSign) - binary.BigEndian.PutUint64(slashingParams[32:], slashFractionDowntime) - - // governance message with sha3 of wasmBytes as the payload - module := [32]byte{} - copy(module[:], vaa.CoreModule) - gov_msg := types.NewGovernanceMessage(module, byte(vaa.ActionSlashingParamsUpdate), uint16(vaa.ChainIDWormchain), slashingParams) - - return gov_msg.MarshalBinary() -} - -func TestExecuteSlashingParamsUpdate(t *testing.T) { - k, ctx := keepertest.WormholeKeeper(t) - guardians, privateKeys := createNGuardianValidator(k, ctx, 10) - k.SetConfig(ctx, types.Config{ - GovernanceEmitter: vaa.GovernanceEmitter[:], - GovernanceChain: uint32(vaa.GovernanceChain), - ChainId: uint32(vaa.ChainIDWormchain), - GuardianSetExpiration: 86400, - }) - signer_bz := [20]byte{} - signer := sdk.AccAddress(signer_bz[:]) - - set := createNewGuardianSet(k, ctx, guardians) - k.SetConsensusGuardianSetIndex(ctx, types.ConsensusGuardianSetIndex{Index: set.Index}) - - context := sdk.WrapSDKContext(ctx) - msgServer := keeper.NewMsgServerImpl(*k) - - // create governance to update slashing params - payload := createSlashingParamsUpdatePayload() - v := generateVaa(set.Index, privateKeys, vaa.ChainID(vaa.GovernanceChain), payload) - vBz, _ := v.Marshal() - _, err := msgServer.ExecuteGovernanceVAA(context, &types.MsgExecuteGovernanceVAA{ - Signer: signer.String(), - Vaa: vBz, - }) - assert.NoError(t, err) -}