Skip to content

Commit

Permalink
fix bug
Browse files Browse the repository at this point in the history
  • Loading branch information
KeaneHh committed Jan 16, 2025
1 parent 8d61e88 commit bd624ba
Show file tree
Hide file tree
Showing 33 changed files with 1,342 additions and 392 deletions.
332 changes: 225 additions & 107 deletions clientcontroller/babylon.go

Large diffs are not rendered by default.

26 changes: 7 additions & 19 deletions clientcontroller/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"github.com/btcsuite/btcd/chaincfg"
"go.uber.org/zap"

finalitytypes "github.com/babylonlabs-io/babylon/x/finality/types"

fpcfg "github.com/Manta-Network/manta-fp/finality-provider/config"
"github.com/Manta-Network/manta-fp/types"
)
Expand Down Expand Up @@ -42,7 +40,7 @@ type ClientController interface {
SubmitFinalitySig(fpPk *btcec.PublicKey, block *types.BlockInfo, pubRand *btcec.FieldVal, proof []byte, sig *btcec.ModNScalar) (*types.TxResponse, error)

// SubmitBatchFinalitySigs submits a batch of finality signatures to the consumer chain
SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, pubRandList []*btcec.FieldVal, proofList [][]byte, sigs []*btcec.ModNScalar) (*types.TxResponse, error)
SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks *types.BlockInfo, pubRandList *btcec.FieldVal, proofList []byte, sigs *btcec.ModNScalar) (*types.TxResponse, error)

// UnjailFinalityProvider sends an unjail transaction to the consumer chain
UnjailFinalityProvider(fpPk *btcec.PublicKey) (*types.TxResponse, error)
Expand All @@ -52,22 +50,19 @@ type ClientController interface {
*/

// QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height
QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error)
QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (bool, error)

// QueryFinalityProviderSlashedOrJailed queries if the finality provider is slashed or jailed
QueryFinalityProviderSlashedOrJailed(fpPk *btcec.PublicKey) (slashed bool, jailed bool, err error)

// QueryFinalityProviderHighestVotedHeight queries the highest voted height of the given finality provider
QueryFinalityProviderHighestVotedHeight(fpPk *btcec.PublicKey) (uint64, error)

// QueryLatestFinalizedBlocks returns the latest finalized blocks
QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error)
QueryLatestFinalizedBlocks() (uint64, error)

// QueryLastCommittedPublicRand returns the last committed public randomness
QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*finalitytypes.PubRandCommitResponse, error)
QueryLastCommittedPublicRand(fpPk *btcec.PublicKey) (*types.PubRandCommit, error)

// QueryBlock queries the block at the given height
QueryBlock(height uint64) (*types.BlockInfo, error)
QueryBlock(height uint64) (bool, error)

// QueryBlocks returns a list of blocks from startHeight to endHeight
QueryBlocks(startHeight, endHeight uint64, limit uint32) ([]*types.BlockInfo, error)
Expand All @@ -79,25 +74,18 @@ type ClientController interface {
// error will be returned if the consumer chain has not been activated
QueryActivatedHeight() (uint64, error)

// QueryFinalityActivationBlockHeight returns the block height of the consumer chain
// starts to accept finality voting and pub rand commit as start height
// error will be returned if the consumer chain failed to get this value
// if the consumer chain wants to accept finality voting at any block height
// the value zero should be returned.
QueryFinalityActivationBlockHeight() (uint64, error)

Close() error
}

func NewClientController(chainType string, bbnConfig *fpcfg.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) {
func NewClientController(chainType string, bbnConfig *fpcfg.BBNConfig, opConfig *fpcfg.OpEventConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) {
var (
cc ClientController
err error
)

switch chainType {
case babylonConsumerChainType:
cc, err = NewBabylonController(bbnConfig, netParams, logger)
cc, err = NewBabylonController(bbnConfig, opConfig, netParams, logger)
if err != nil {
return nil, fmt.Errorf("failed to create Babylon rpc client: %w", err)
}
Expand Down
63 changes: 63 additions & 0 deletions clientcontroller/msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package clientcontroller

type CommitPublicRandomnessMsg struct {
CommitPublicRandomness CommitPublicRandomnessMsgParams `json:"commit_public_randomness"`
}

type CommitPublicRandomnessMsgParams struct {
FpPubkeyHex string `json:"fp_pubkey_hex"`
StartHeight uint64 `json:"start_height"`
NumPubRand uint64 `json:"num_pub_rand"`
Commitment []byte `json:"commitment"`
Signature []byte `json:"signature"`
}

// TODO: need to update based on contract implementation
type CommitPublicRandomnessResponse struct {
Result bool `json:"result"`
}

type SubmitFinalitySignatureMsg struct {
SubmitFinalitySignature SubmitFinalitySignatureMsgParams `json:"submit_finality_signature"`
}

type SubmitFinalitySignatureMsgParams struct {
FpPubkeyHex string `json:"fp_pubkey_hex"`
Height uint64 `json:"height"`
PubRand []byte `json:"pub_rand"`
Proof Proof `json:"proof"`
BlockHash []byte `json:"block_hash"`
Signature []byte `json:"signature"`
}

// TODO: need to update based on contract implementation
type SubmitFinalitySignatureResponse struct {
Result bool `json:"result"`
}

type QueryMsg struct {
Config *Config `json:"config,omitempty"`
FirstPubRandCommit *PubRandCommit `json:"first_pub_rand_commit,omitempty"`
LastPubRandCommit *PubRandCommit `json:"last_pub_rand_commit,omitempty"`
}

type Config struct{}

type PubRandCommit struct {
BtcPkHex string `json:"btc_pk_hex"`
}

type ConfigResponse struct {
ConsumerId string `json:"consumer_id"`
ActivatedHeight uint64 `json:"activated_height"`
}

// FIXME: Remove this ancillary struct.
// Only required because the e2e tests are using a zero index, which is removed by the `json:"omitempty"` annotation in
// the original cmtcrypto Proof
type Proof struct {
Total uint64 `json:"total"`
Index uint64 `json:"index"`
LeafHash []byte `json:"leaf_hash"`
Aunts [][]byte `json:"aunts"`
}
98 changes: 98 additions & 0 deletions cosmwasmclient/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package client

import (
"context"
"sync"
"time"

wasmdparams "github.com/CosmWasm/wasmd/app/params"
"github.com/Manta-Network/manta-fp/cosmwasmclient/config"
"github.com/Manta-Network/manta-fp/cosmwasmclient/query"
rpchttp "github.com/cometbft/cometbft/rpc/client/http"
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
"go.uber.org/zap"
)

type Client struct {
mu sync.Mutex
*query.QueryClient

provider *cosmos.CosmosProvider
timeout time.Duration
logger *zap.Logger
cfg *config.CosmwasmConfig
}

func New(cfg *config.CosmwasmConfig, chainName string, encodingCfg wasmdparams.EncodingConfig, logger *zap.Logger) (*Client, error) {
var (
zapLogger *zap.Logger
err error
)

// ensure cfg is valid
if err := cfg.Validate(); err != nil {
return nil, err
}

// use the existing logger or create a new one if not given
zapLogger = logger
if zapLogger == nil {
zapLogger, err = newRootLogger("console", true)
if err != nil {
return nil, err
}
}

provider, err := cfg.ToCosmosProviderConfig().NewProvider(
zapLogger,
"", // TODO: set home path
true,
chainName,
)
if err != nil {
return nil, err
}

cp := provider.(*cosmos.CosmosProvider)
cp.PCfg.KeyDirectory = cfg.KeyDirectory
cp.Cdc = cosmos.Codec{
InterfaceRegistry: encodingCfg.InterfaceRegistry,
Marshaler: encodingCfg.Codec,
TxConfig: encodingCfg.TxConfig,
Amino: encodingCfg.Amino,
}

// initialise Cosmos provider
// NOTE: this will create a RPC client. The RPC client will be used for
// submitting txs and making ad hoc queries. It won't create WebSocket
// connection with wasmd node
err = cp.Init(context.Background())
if err != nil {
return nil, err
}

// create a queryClient so that the Client inherits all query functions
// TODO: merge this RPC client with the one in `cp` after Cosmos side
// finishes the migration to new RPC client
// see https://github.com/strangelove-ventures/cometbft-client
c, err := rpchttp.NewWithTimeout(cp.PCfg.RPCAddr, "/websocket", uint(cfg.Timeout.Seconds()))
if err != nil {
return nil, err
}
queryClient, err := query.NewWithClient(c, cfg.Timeout)
if err != nil {
return nil, err
}

return &Client{
QueryClient: queryClient,
provider: cp,
timeout: cfg.Timeout,
logger: zapLogger,
cfg: cfg,
}, nil
}

func (c *Client) GetConfig() *config.CosmwasmConfig {
return c.cfg
}
80 changes: 80 additions & 0 deletions cosmwasmclient/client/contract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package client

import (
"bytes"
"compress/gzip"
"context"
"fmt"
"os"
"strings"

wasmdtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdkquery "github.com/cosmos/cosmos-sdk/types/query"
)

func (cwClient *Client) StoreWasmCode(wasmFile string) error {
wasmCode, err := os.ReadFile(wasmFile)
if err != nil {
return err
}
if strings.HasSuffix(wasmFile, "wasm") { // compress for gas limit
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
_, err = gz.Write(wasmCode)
if err != nil {
return err
}
err = gz.Close()
if err != nil {
return err
}
wasmCode = buf.Bytes()
}

storeMsg := &wasmdtypes.MsgStoreCode{
Sender: cwClient.MustGetAddr(),
WASMByteCode: wasmCode,
}
_, err = cwClient.ReliablySendMsg(context.Background(), storeMsg, nil, nil)
if err != nil {
return err
}

return nil
}

func (cwClient *Client) InstantiateContract(codeID uint64, initMsg []byte) error {
instantiateMsg := &wasmdtypes.MsgInstantiateContract{
Sender: cwClient.MustGetAddr(),
Admin: cwClient.MustGetAddr(),
CodeID: codeID,
Label: "cw",
Msg: initMsg,
Funds: nil,
}

_, err := cwClient.ReliablySendMsg(context.Background(), instantiateMsg, nil, nil)
if err != nil {
return err
}

return nil
}

// returns the latest wasm code id.
func (cwClient *Client) GetLatestCodeId() (uint64, error) {
pagination := &sdkquery.PageRequest{
Limit: 1,
Reverse: true,
}
resp, err := cwClient.ListCodes(pagination)
if err != nil {
return 0, err
}

if len(resp.CodeInfos) == 0 {
return 0, fmt.Errorf("no codes found")
}

return resp.CodeInfos[0].CodeID, nil
}
49 changes: 49 additions & 0 deletions cosmwasmclient/client/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package client

import (
"fmt"
"path"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/juju/fslock"
)

func (c *Client) GetAddr() (string, error) {
return c.provider.Address()
}

func (c *Client) MustGetAddr() string {
addr, err := c.provider.Address()
if err != nil {
panic(fmt.Errorf("failed to get signer: %v", err))
}
return addr
}

func (c *Client) GetKeyring() keyring.Keyring {
return c.provider.Keybase
}

// accessKeyWithLock triggers a function that access key ring while acquiring
// the file system lock, in order to remain thread-safe when multiple concurrent
// relayers are running on the same machine and accessing the same keyring
// adapted from
// https://github.com/babylonchain/babylon-relayer/blob/f962d0940832a8f84f747c5d9cbc67bc1b156386/bbnrelayer/utils.go#L212
func (c *Client) accessKeyWithLock(accessFunc func()) error {
// use lock file to guard concurrent access to the keyring
lockFilePath := path.Join(c.provider.PCfg.KeyDirectory, "keys.lock")
lock := fslock.New(lockFilePath)
if err := lock.Lock(); err != nil {
return fmt.Errorf("failed to acquire file system lock (%s): %w", lockFilePath, err)
}

// trigger function that access keyring
accessFunc()

// unlock and release access
if err := lock.Unlock(); err != nil {
return fmt.Errorf("error unlocking file system lock (%s), please manually delete", lockFilePath)
}

return nil
}
Loading

0 comments on commit bd624ba

Please sign in to comment.