Skip to content

Commit

Permalink
wormchain: add slashing params vaa (#4194)
Browse files Browse the repository at this point in the history
* Add ICT Local Image

* Ref Slashing Keeper in Wormhole Keeper

* Add Payload & Test

* Add Generate Slashing Params Update Vaa Cmd

* Add ICT Tests

* Finish ICTs

* Fix Slashing Params VAA Test

* Fix ICT Workflow

* Add range check for sdk.Dec

* Add BodySlashingParamsUpdate Notes

* Cleanup

* fix upload artifact

Also removes flaky CI tests.

* fix download artifact

* Fix GenerateVaa in ICT

* Switch to Gateway Governance Module
  • Loading branch information
joelsmith-2019 authored Feb 11, 2025
1 parent 477d475 commit aaed33c
Show file tree
Hide file tree
Showing 24 changed files with 604 additions and 150 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/wormchain-icts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -59,9 +59,11 @@ jobs:
# names of `make` commands to run tests
test:
- "ictest-cancel-upgrade"
- "ictest-slashing-params-update-vaa"
- "ictest-upgrade"
- "ictest-wormchain"
- "ictest-ibc-receiver"
# Disabled due to flakiness in CI.
# - "ictest-ibc-receiver"
- "ictest-validator-hotswap"
- "ictest-cw-wormhole"
fail-fast: false
Expand All @@ -77,7 +79,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
Expand Down
50 changes: 50 additions & 0 deletions sdk/vaa/payloads.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ var (
ActionScheduleUpgrade GovernanceAction = 1
ActionCancelUpgrade GovernanceAction = 2
ActionSetIbcComposabilityMwContract GovernanceAction = 3
ActionSlashingParamsUpdate GovernanceAction = 4

// Accountant governance actions
ActionModifyBalance GovernanceAction = 1
Expand Down Expand Up @@ -193,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
Expand Down Expand Up @@ -393,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))
Expand Down
58 changes: 58 additions & 0 deletions sdk/vaa/payloads_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"reflect"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
Expand Down Expand Up @@ -363,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{
Expand Down
2 changes: 1 addition & 1 deletion wormchain/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion wormchain/Dockerfile.ict
Original file line number Diff line number Diff line change
Expand Up @@ -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/[email protected]/internal/api/* /usr/lib
COPY --from=builder /go/pkg/mod/github.com/!cosm!wasm/[email protected]/internal/api/* /usr/lib/

EXPOSE 26657
EXPOSE 26656
Expand Down
15 changes: 13 additions & 2 deletions wormchain/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,40 @@ local-image: build/wormchaind
# Individual Tests ($$ is interpreted as $)
rm-testcache:
go clean -testcache
.PHONY: rm-testcache

ictest-cancel-upgrade: rm-testcache
cd interchaintest && go test -race -v -run ^TestCancelUpgrade$$ ./...
.PHONY: ictest-cancel-upgrade

ictest-malformed-payload: rm-testcache
cd interchaintest && go test -race -v -run ^TestMalformedPayload$$ ./...
.PHONY: ictest-malformed-payload

ictest-slashing-params-update-vaa: rm-testcache
cd interchaintest && go test -race -v -run ^TestSlashingParamsUpdateVaa$$ ./...
.PHONY: ictest-slashing-params-update-vaa

ictest-upgrade-failure: rm-testcache
cd interchaintest && go test -race -v -run ^TestUpgradeFailure$$ ./...
.PHONY: ictest-upgrade-failure

ictest-upgrade: rm-testcache
cd interchaintest && go test -race -v -run ^TestUpgrade$$ ./...
.PHONY: ictest-upgrade

ictest-wormchain: rm-testcache
cd interchaintest && go test -race -v -run ^TestWormchain$$ ./...
.PHONY: ictest-wormchain

ictest-ibc-receiver: rm-testcache
cd interchaintest && go test -race -v -run ^TestIbcReceiver ./...
.PHONY: ictest-ibc-receiver

ictest-cw-wormhole: rm-testcache
cd interchaintest && go test -race -v -run ^TestCWWormhole ./...
.PHONY: ictest-cw-wormhole

ictest-validator-hotswap: rm-testcache
cd interchaintest && go test -race -v -run ^TestValidatorHotswap$$ ./...

.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver ictest-cw-wormhole ictest-validator-hotswap
.PHONY: ictest-validator-hotswap
2 changes: 2 additions & 0 deletions wormchain/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
6 changes: 3 additions & 3 deletions wormchain/interchaintest/helpers/gateway_governance_vaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions wormchain/interchaintest/helpers/ibc_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion wormchain/interchaintest/helpers/instantiate_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion wormchain/interchaintest/helpers/migrate_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion wormchain/interchaintest/helpers/store_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions wormchain/interchaintest/helpers/token_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions wormchain/interchaintest/helpers/vaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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,
Expand Down Expand Up @@ -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()
Expand Down
Loading

0 comments on commit aaed33c

Please sign in to comment.