add chain create-evm-actor and invoke-emv-actor commands
This commit is contained in:
parent
2317111c85
commit
fc273bb79e
223
cli/chain.go
223
cli/chain.go
@ -25,6 +25,7 @@ import (
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
evm "github.com/filecoin-project/go-state-types/builtin/v10/evm"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
@ -63,6 +64,8 @@ var ChainCmd = &cli.Command{
|
||||
ChainEncodeCmd,
|
||||
ChainDisputeSetCmd,
|
||||
ChainPruneCmd,
|
||||
ChainExecEVMCmd,
|
||||
ChainInvokeEVMCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1509,3 +1512,223 @@ var ChainPruneCmd = &cli.Command{
|
||||
return api.ChainPrune(ctx, opts)
|
||||
},
|
||||
}
|
||||
|
||||
var ChainExecEVMCmd = &cli.Command{
|
||||
Name: "create-evm-actor",
|
||||
Usage: "Create an new EVM actor via the init actor and return its address",
|
||||
ArgsUsage: "contract [params]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to use for sending the exec message",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
afmt := NewAppFmt(cctx.App)
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if argc := cctx.Args().Len(); argc < 1 || argc > 2 {
|
||||
return xerrors.Errorf("must pass the contract and (optionally) constructor input data")
|
||||
}
|
||||
|
||||
contract, err := os.ReadFile(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to read contract: %w", err)
|
||||
}
|
||||
|
||||
var inputData []byte
|
||||
if cctx.Args().Len() == 2 {
|
||||
inputData, err = base64.StdEncoding.DecodeString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding base64 value: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
|
||||
Bytecode: contract,
|
||||
InputData: inputData,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to serialize constructor params: %w", err)
|
||||
}
|
||||
|
||||
evmActorCid, ok := actors.GetActorCodeID(actors.Version8, "evm")
|
||||
if !ok {
|
||||
return xerrors.Errorf("failed to lookup evm actor code CID")
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&init8.ExecParams{
|
||||
CodeCID: evmActorCid,
|
||||
ConstructorParams: constructorParams,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to serialize init actor exec params: %w", err)
|
||||
}
|
||||
|
||||
var fromAddr address.Address
|
||||
if from := cctx.String("from"); from == "" {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = defaddr
|
||||
} else {
|
||||
addr, err := address.NewFromString(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = addr
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: builtin.InitActorAddr,
|
||||
From: fromAddr,
|
||||
Value: big.Zero(),
|
||||
Method: 2,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
afmt.Println("sending message...")
|
||||
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to push message: %w", err)
|
||||
}
|
||||
|
||||
afmt.Println("waiting for message to execute...")
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error waiting for message: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("actor execution failed")
|
||||
}
|
||||
|
||||
var result init8.ExecReturn
|
||||
r := bytes.NewReader(wait.Receipt.Return)
|
||||
if err := result.UnmarshalCBOR(r); err != nil {
|
||||
return xerrors.Errorf("error unmarshaling return value: %w", err)
|
||||
}
|
||||
|
||||
afmt.Printf("ID Address: %s\n", result.IDAddress)
|
||||
afmt.Printf("Robust Address: %s\n", result.RobustAddress)
|
||||
|
||||
if len(wait.Receipt.Return) > 0 {
|
||||
result := base64.StdEncoding.EncodeToString(wait.Receipt.Return)
|
||||
afmt.Printf("Return: %s\n", result)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var ChainInvokeEVMCmd = &cli.Command{
|
||||
Name: "invoke-evm-actor",
|
||||
Usage: "Invoke a contract entry point in an EVM actor",
|
||||
ArgsUsage: "address contract-entry-point [input-data]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to use for sending the exec message",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
afmt := NewAppFmt(cctx.App)
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if argc := cctx.Args().Len(); argc < 2 || argc > 3 {
|
||||
return xerrors.Errorf("must pass the address, entry point and (optionally) input data")
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to decode address: %w", err)
|
||||
}
|
||||
|
||||
entryPoint, err := hex.DecodeString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to decode hex entry point: %w", err)
|
||||
}
|
||||
|
||||
var inputData []byte
|
||||
if cctx.Args().Len() == 3 {
|
||||
inputData, err = hex.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding hex input data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&evm.InvokeParams{
|
||||
InputData: append(entryPoint, inputData...),
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to serialize evm actor invoke params: %w", err)
|
||||
}
|
||||
|
||||
var fromAddr address.Address
|
||||
if from := cctx.String("from"); from == "" {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = defaddr
|
||||
} else {
|
||||
addr, err := address.NewFromString(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = addr
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: addr,
|
||||
From: fromAddr,
|
||||
Value: big.Zero(),
|
||||
Method: abi.MethodNum(2),
|
||||
Params: params,
|
||||
}
|
||||
|
||||
afmt.Println("sending message...")
|
||||
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to push message: %w", err)
|
||||
}
|
||||
|
||||
afmt.Println("waiting for message to execute...")
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error waiting for message: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("actor execution failed")
|
||||
}
|
||||
|
||||
if len(wait.Receipt.Return) > 0 {
|
||||
result := hex.EncodeToString(wait.Receipt.Return)
|
||||
afmt.Println(result)
|
||||
} else {
|
||||
afmt.Println("OK")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user