110 lines
3.4 KiB
Go
110 lines
3.4 KiB
Go
package wormhole
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
|
"github.com/wormhole-foundation/wormchain/x/wormhole/keeper"
|
|
"github.com/wormhole-foundation/wormchain/x/wormhole/types"
|
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
|
)
|
|
|
|
// NewWormholeGovernanceProposalHandler creates a governance handler to manage new proposal types.
|
|
// It enables GuardianSetProposal to update the guardian set and GenericWormholeMessageProposal to emit a generic wormhole
|
|
// message from the governance emitter.
|
|
func NewWormholeGovernanceProposalHandler(k keeper.Keeper) govtypes.Handler {
|
|
return func(ctx sdk.Context, content govtypes.Content) error {
|
|
switch c := content.(type) {
|
|
case *types.GuardianSetUpdateProposal:
|
|
return handleGuardianSetUpdateProposal(ctx, k, c)
|
|
|
|
case *types.GovernanceWormholeMessageProposal:
|
|
return handleGovernanceWormholeMessageProposal(ctx, k, c)
|
|
|
|
default:
|
|
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized wormhole proposal content type: %T", c)
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleGuardianSetUpdateProposal(ctx sdk.Context, k keeper.Keeper, proposal *types.GuardianSetUpdateProposal) error {
|
|
err := k.UpdateGuardianSet(ctx, types.GuardianSet{
|
|
Index: proposal.NewGuardianSet.Index,
|
|
Keys: proposal.NewGuardianSet.Keys,
|
|
ExpirationTime: 0,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update guardian set: %w", err)
|
|
}
|
|
|
|
config, ok := k.GetConfig(ctx)
|
|
if !ok {
|
|
return types.ErrNoConfig
|
|
}
|
|
|
|
// Post a wormhole guardian set update governance message
|
|
message := &bytes.Buffer{}
|
|
|
|
// Header
|
|
message.Write(vaa.CoreModule)
|
|
MustWrite(message, binary.BigEndian, uint8(2))
|
|
MustWrite(message, binary.BigEndian, uint16(0))
|
|
|
|
// Body
|
|
MustWrite(message, binary.BigEndian, proposal.NewGuardianSet.Index)
|
|
MustWrite(message, binary.BigEndian, uint8(len(proposal.NewGuardianSet.Keys)))
|
|
for _, key := range proposal.NewGuardianSet.Keys {
|
|
message.Write(key)
|
|
}
|
|
|
|
emitterAddress, err := types.EmitterAddressFromBytes32(config.GovernanceEmitter)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to post message: %w", err)
|
|
}
|
|
|
|
err = k.PostMessage(ctx, emitterAddress, 0, message.Bytes())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to post message: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleGovernanceWormholeMessageProposal(ctx sdk.Context, k keeper.Keeper, proposal *types.GovernanceWormholeMessageProposal) error {
|
|
config, ok := k.GetConfig(ctx)
|
|
if !ok {
|
|
return types.ErrNoConfig
|
|
}
|
|
|
|
// Post a wormhole governance message
|
|
message := &bytes.Buffer{}
|
|
message.Write(proposal.Module)
|
|
MustWrite(message, binary.BigEndian, uint8(proposal.Action))
|
|
MustWrite(message, binary.BigEndian, uint16(proposal.TargetChain))
|
|
message.Write(proposal.Payload)
|
|
|
|
emitterAddress, err := types.EmitterAddressFromBytes32(config.GovernanceEmitter)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to post message: %w", err)
|
|
}
|
|
|
|
err = k.PostMessage(ctx, emitterAddress, 0, message.Bytes())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to post message: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MustWrite calls binary.Write and panics on errors
|
|
func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
|
|
if err := binary.Write(w, order, data); err != nil {
|
|
panic(fmt.Errorf("failed to write binary data: %v", data).Error())
|
|
}
|
|
}
|