Skip to content

Commit

Permalink
[ioctl][ws][#4] prover sub commands to support interaction with ws co…
Browse files Browse the repository at this point in the history
…ntracts (#4282)

* feat(ioctl/ws): sync latest w3bstream contract abis and generate go code

* feat(ioctl/config): add ws contract address configurations

* feat(ioctl/ws): ioctl support ws project contracts interactions

* feat(ioctl/ws): ioctl support ws prover contracts interactions
  • Loading branch information
saitofun committed May 30, 2024
1 parent 66bf477 commit 3ebc017
Show file tree
Hide file tree
Showing 6 changed files with 480 additions and 0 deletions.
89 changes: 89 additions & 0 deletions ioctl/cmd/ws/wsprover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package ws

import (
"bytes"
_ "embed" // used to embed contract abi

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/flag"
)

var wsProverCmd = &cobra.Command{
Use: "prover",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "w3bstream prover management",
config.Chinese: "w3bstream prover 节点管理",
}, config.UILanguage),
}

var (
proverID = flag.NewUint64VarP("id", "", 0, config.TranslateInLang(_flagProverIDUsages, config.UILanguage))
proverNodeType = flag.NewUint64VarP("node-type", "", 0, config.TranslateInLang(_flagProverNodeTypeUsages, config.UILanguage))
proverOperator = flag.NewStringVarP("operator", "", "", config.TranslateInLang(_flagProverOperatorUsages, config.UILanguage))
)

var (
_flagProverIDUsages = map[config.Language]string{
config.English: "prover id",
config.Chinese: "prover(计算节点) ID",
}
_flagProverNodeTypeUsages = map[config.Language]string{
config.English: "prover node type",
config.Chinese: "prover(计算节点) 节点类型",
}
_flagProverOperatorUsages = map[config.Language]string{
config.English: "prover node operator",
config.Chinese: "prover(计算节点)操作者",
}
)

var (
//go:embed contracts/abis/W3bstreamProver.json
proverStoreJSON []byte
proverStoreAddress string
proverStoreABI abi.ABI

//go:embed contracts/abis/FleetManagement.json
fleetManagementJSON []byte
fleetManagementAddress string
fleetManagementABI abi.ABI
)

const (
funcProverRegister = "register"
funcUpdateProver = "updateNodeType"
funcQueryProverNodeType = "nodeType"
funcQueryProverIsPaused = "isPaused"
funcQueryProverOperator = "operator"
funcQueryProverOwner = "prover"
funcPauseProver = "pause"
funcResumeProver = "resume"
funcChangeProverOwner = "changeOperator"
)

const (
eventOnProverRegistered = "Transfer"
eventOnProverUpdated = "NodeTypeUpdated"
eventOnProverPaused = "ProverPaused"
eventOnProverResumed = "ProverResumed"
eventOnProverOwnerChanged = "OperatorSet"
)

func init() {
var err error
proverStoreABI, err = abi.JSON(bytes.NewReader(proverStoreJSON))
if err != nil {
panic(err)
}
proverStoreAddress = config.ReadConfig.WsProverStoreContract
fleetManagementABI, err = abi.JSON(bytes.NewReader(fleetManagementJSON))
if err != nil {
panic(err)
}
fleetManagementAddress = config.ReadConfig.WsFleetManagementContract

WsCmd.AddCommand(wsProverCmd)
}
105 changes: 105 additions & 0 deletions ioctl/cmd/ws/wsproverquery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package ws

import (
"math/big"

"github.com/ethereum/go-ethereum/common"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
"github.com/iotexproject/iotex-core/ioctl/util"
)

var wsProverQueryCmd = &cobra.Command{
Use: "query",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "query prover",
config.Chinese: "查询prover节点信息",
}, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
out, err := queryProver(big.NewInt(int64(proverID.Value().(uint64))))
if err != nil {
return output.PrintError(err)
}
output.PrintResult(output.JSONString(out))
return nil
},
}

func init() {
proverID.RegisterCommand(wsProverQueryCmd)
proverID.MarkFlagRequired(wsProverQueryCmd)

wsProverCmd.AddCommand(wsProverQueryCmd)
}

func queryProver(proverID *big.Int) (any, error) {
caller, err := NewContractCaller(proverStoreABI, proverStoreAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to new contract caller")
}
result := NewContractResult(&proverStoreABI, funcQueryProverNodeType, new(big.Int))
if err = caller.Read(funcQueryProverNodeType, []any{proverID}, result); err != nil {
return nil, errors.Wrapf(err, "failed to read contract: %s", funcQueryProverNodeType)
}

nodeType, err := result.Result()
if err != nil {
return nil, err
}

result = NewContractResult(&proverStoreABI, funcQueryProverIsPaused, new(bool))
if err = caller.Read(funcQueryProverIsPaused, []any{proverID}, result); err != nil {
return nil, errors.Wrapf(err, "failed to read contract: %s", funcQueryProverIsPaused)
}
isPaused, err := result.Result()
if err != nil {
return nil, err
}

result = NewContractResult(&proverStoreABI, funcQueryProverOperator, &common.Address{})
if err = caller.Read(funcQueryProverOperator, []any{proverID}, result); err != nil {
return nil, errors.Wrapf(err, "failed to read contract: %s", funcQueryProverOperator)
}
operator, err := result.Result()
if err != nil {
return nil, err
}

result = NewContractResult(&proverStoreABI, funcQueryProverOwner, &common.Address{})
if err = caller.Read(funcQueryProverOwner, []any{proverID}, result); err != nil {
return nil, errors.Wrapf(err, "failed to read contract: %s", funcQueryProverOwner)
}
owner, err := result.Result()
if err != nil {
return nil, err
}

operatorAddr, err := util.Address((*operator.(*common.Address)).String())
if err != nil {
return nil, errors.Wrapf(err, "failed to convert operator address")
}

ownerAddr, err := util.Address((*owner.(*common.Address)).String())
if err != nil {
return nil, errors.Wrapf(err, "failed to convert prover address")
}

return &struct {
ProverID uint64 `json:"proverID"`
Prover string `json:"owner"`
NodeType uint64 `json:"nodeType"`
IsPaused bool `json:"isPaused"`
Operator string `json:"operator"`
}{
ProverID: proverID.Uint64(),
Prover: ownerAddr,
NodeType: nodeType.(*big.Int).Uint64(),
IsPaused: *isPaused.(*bool),
Operator: operatorAddr,
}, nil

}
54 changes: 54 additions & 0 deletions ioctl/cmd/ws/wsproverregister.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ws

import (
"math/big"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl/cmd/ws/contracts"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

var wsProverRegisterCmd = &cobra.Command{
Use: "register",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "register prover",
config.Chinese: "注册prover节点",
}, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
out, err := registerProver()
if err != nil {
return output.PrintError(err)
}
output.PrintResult(output.JSONString(out))
return nil
},
}

func init() {
transferAmount.RegisterCommand(wsProverRegisterCmd)

wsProverCmd.AddCommand(wsProverRegisterCmd)
}

func registerProver() (any, error) {
caller, err := NewContractCaller(fleetManagementABI, fleetManagementAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to create contract caller")
}
caller.SetAmount(big.NewInt(int64(transferAmount.Value().(uint64))))

value := new(contracts.W3bstreamProverTransfer)
result := NewContractResult(&proverStoreABI, eventOnProverRegistered, value)
if _, err = caller.CallAndRetrieveResult(funcProverRegister, nil, result); err != nil {
return nil, errors.Wrap(err, "failed to call contract")
}

if _, err = result.Result(); err != nil {
return nil, err
}

return queryProver(value.TokenId)
}
96 changes: 96 additions & 0 deletions ioctl/cmd/ws/wsproverstate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ws

import (
"fmt"
"math/big"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

var wsProverPauseCmd = &cobra.Command{
Use: "pause",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "pause prover",
config.Chinese: "停止prover",
}, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
id := big.NewInt(int64(proverID.Value().(uint64)))
out, err := pauseProver(id)
if err != nil {
return output.PrintError(err)
}
output.PrintResult(fmt.Sprintf("prover %d paused", id))
output.PrintResult(output.JSONString(out))
return nil
},
}

var wsProverResumeCmd = &cobra.Command{
Use: "resume",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "resume prover",
config.Chinese: "启动prover",
}, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
id := big.NewInt(int64(proverID.Value().(uint64)))
out, err := resumeProver(id)
if err != nil {
return output.PrintError(err)
}
output.PrintResult(fmt.Sprintf("prover %d resumed", id))
output.PrintResult(output.JSONString(out))
return nil
},
}

func init() {
proverID.RegisterCommand(wsProverPauseCmd)
proverID.MarkFlagRequired(wsProverPauseCmd)

proverID.RegisterCommand(wsProverResumeCmd)
proverID.MarkFlagRequired(wsProverResumeCmd)

wsProverCmd.AddCommand(wsProverPauseCmd)
wsProverCmd.AddCommand(wsProverResumeCmd)
}

func pauseProver(proverID *big.Int) (any, error) {
caller, err := NewContractCaller(proverStoreABI, proverStoreAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to new contract caller")
}

result := NewContractResult(&proverStoreABI, eventOnProverPaused, nil)
_, err = caller.CallAndRetrieveResult(funcPauseProver, []any{proverID}, result)
if err != nil {
return nil, errors.Wrap(err, "failed to call contract")
}
_, err = result.Result()
if err != nil {
return nil, err
}
return queryProver(proverID)
}

func resumeProver(proverID *big.Int) (any, error) {
caller, err := NewContractCaller(proverStoreABI, proverStoreAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to new contract caller")
}

result := NewContractResult(&proverStoreABI, eventOnProverResumed, nil)
_, err = caller.CallAndRetrieveResult(funcResumeProver, []any{proverID}, result)
if err != nil {
return nil, errors.Wrap(err, "failed to call contract")
}
_, err = result.Result()
if err != nil {
return nil, err
}

return queryProver(proverID)
}
Loading

0 comments on commit 3ebc017

Please sign in to comment.