Skip to content

Commit e74fb02

Browse files
authored
feat: implement object deploy cmd for auto address derivation (#343)
* implement object deploy cmd for auto address derivation * add more description * add comments
1 parent 3a10bf0 commit e74fb02

File tree

2 files changed

+269
-104
lines changed

2 files changed

+269
-104
lines changed

cmd/move/deploy.go

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
package movecmd
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
8+
"github.com/spf13/cobra"
9+
"golang.org/x/crypto/sha3"
10+
11+
"cosmossdk.io/core/address"
12+
errorsmod "cosmossdk.io/errors"
13+
"github.com/cosmos/cosmos-sdk/client"
14+
"github.com/cosmos/cosmos-sdk/client/flags"
15+
"github.com/cosmos/cosmos-sdk/client/input"
16+
"github.com/cosmos/cosmos-sdk/client/tx"
17+
sdk "github.com/cosmos/cosmos-sdk/types"
18+
19+
movecli "github.com/initia-labs/initia/x/move/client/cli"
20+
movetypes "github.com/initia-labs/initia/x/move/types"
21+
22+
"github.com/initia-labs/movevm/api"
23+
vmtypes "github.com/initia-labs/movevm/types"
24+
)
25+
26+
func moveDeployCmd(ac address.Codec) *cobra.Command {
27+
cmd := &cobra.Command{
28+
Use: "deploy [flags]",
29+
Short: "deploy a whole move package",
30+
Long: "deploy a whole move package. This command occurs a tx to publish module bundle.",
31+
Args: cobra.ExactArgs(0),
32+
RunE: func(cmd *cobra.Command, args []string) error {
33+
// build package
34+
flagBuild, err := cmd.Flags().GetBool(flagBuild)
35+
if err != nil {
36+
return err
37+
}
38+
39+
if flagBuild {
40+
arg, err := getCompilerArgument(cmd)
41+
if err != nil {
42+
return err
43+
}
44+
45+
_, err = api.BuildContract(*arg)
46+
if err != nil {
47+
return err
48+
}
49+
}
50+
51+
flagVerify, err := cmd.Flags().GetBool(flagVerify)
52+
if err != nil {
53+
return err
54+
}
55+
56+
return deploy(cmd, ac, false, flagVerify)
57+
},
58+
}
59+
60+
// add flat set for upgrade policy
61+
cmd.Flags().AddFlagSet(movecli.FlagSetUpgradePolicy())
62+
63+
addMoveDeployFlags(cmd)
64+
addMoveBuildFlags(cmd)
65+
addMoveVerifyFlags(cmd, false)
66+
flags.AddTxFlagsToCmd(cmd)
67+
return cmd
68+
}
69+
70+
// OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR is the domain separator used for object code deployment
71+
var OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR string = "initia_std::object_code_deployment"
72+
73+
func deployObjectCmd(ac address.Codec) *cobra.Command {
74+
cmd := &cobra.Command{
75+
Use: "deploy-object [target-name] [flags]",
76+
Short: "build and deploy a move package via @std::object_code_deployment",
77+
Long: `
78+
Build and deploy a move package via @std::object_code_deployment.
79+
80+
This command adds the named address to the build config, so the user must set
81+
the target name to '_' in the Move.toml file.
82+
`,
83+
Args: cobra.ExactArgs(1),
84+
RunE: func(cmd *cobra.Command, args []string) error {
85+
86+
arg, err := getCompilerArgument(cmd)
87+
if err != nil {
88+
return err
89+
}
90+
91+
// compute object address
92+
clientCtx, err := client.GetClientTxContext(cmd)
93+
if err != nil {
94+
return err
95+
}
96+
_, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, clientCtx.FromAddress)
97+
if err != nil {
98+
return err
99+
}
100+
101+
// Add 2 here because the sequence number will be incremented by 1
102+
// during the deployment transaction.
103+
seq += 2
104+
105+
var buf []byte
106+
bz1, err := vmtypes.SerializeString(OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR)
107+
if err != nil {
108+
return err
109+
}
110+
bz2, err := vmtypes.SerializeUint64(seq)
111+
if err != nil {
112+
return err
113+
}
114+
115+
// compute vm address
116+
vmAddr, err := vmtypes.NewAccountAddressFromBytes(clientCtx.FromAddress.Bytes())
117+
if err != nil {
118+
return err
119+
}
120+
121+
// derive object address
122+
// address + domain separator + sequence + 0xFE
123+
buf = append(buf, vmAddr[:]...)
124+
buf = append(buf, bz1...)
125+
buf = append(buf, bz2...)
126+
buf = append(buf, 0xFE)
127+
128+
objectAddrBz := sha3.Sum256(buf)
129+
objectAccAddr := sdk.AccAddress(objectAddrBz[:])
130+
objectVmAddr := vmtypes.AccountAddress(objectAddrBz[:])
131+
objectAddressName := args[0]
132+
133+
if !clientCtx.SkipConfirm {
134+
if ok, err := input.GetConfirmation(
135+
fmt.Sprintf("Do you want to publish this package at object address 0x%x", objectAccAddr),
136+
bufio.NewReader(clientCtx.Input),
137+
os.Stderr,
138+
); err != nil {
139+
return err
140+
} else if !ok {
141+
return nil
142+
}
143+
} else {
144+
fmt.Printf("Publishing package at object address 0x%x\n", objectAccAddr)
145+
}
146+
147+
// add object address's named address
148+
arg.BuildConfig.AdditionalNamedAddresses = append(arg.BuildConfig.AdditionalNamedAddresses,
149+
struct {
150+
Field0 string
151+
Field1 vmtypes.AccountAddress
152+
}{
153+
Field0: objectAddressName,
154+
Field1: objectVmAddr,
155+
})
156+
157+
_, err = api.BuildContract(*arg)
158+
if err != nil {
159+
return err
160+
}
161+
162+
return deploy(cmd, ac, true, false)
163+
},
164+
}
165+
166+
addMoveBuildFlags(cmd)
167+
flags.AddTxFlagsToCmd(cmd)
168+
return cmd
169+
}
170+
171+
func deploy(cmd *cobra.Command, ac address.Codec, isObjectDeployment, verify bool) error {
172+
// deploy package
173+
clientCtx, err := client.GetClientTxContext(cmd)
174+
if err != nil {
175+
return err
176+
}
177+
178+
packagePath, err := cmd.Flags().GetString(flagPackagePath)
179+
if err != nil {
180+
return err
181+
}
182+
183+
moduleBundle, err := getModuleBundle(packagePath)
184+
if err != nil {
185+
return err
186+
}
187+
188+
if len(moduleBundle) == 0 {
189+
return fmt.Errorf("module bundle is empty")
190+
}
191+
192+
senderAddr := clientCtx.FromAddress
193+
senderStrAddr, err := ac.BytesToString(senderAddr.Bytes())
194+
if err != nil {
195+
return err
196+
}
197+
198+
var msg sdk.Msg
199+
if isObjectDeployment {
200+
moduleBundleStr := marshalBytesArrayToHexArray(moduleBundle)
201+
executeMsg := &movetypes.MsgExecuteJSON{
202+
Sender: senderStrAddr,
203+
ModuleAddress: vmtypes.StdAddress.String(),
204+
ModuleName: "object_code_deployment",
205+
FunctionName: "publish_v2",
206+
Args: []string{
207+
moduleBundleStr, // code bytes array
208+
},
209+
}
210+
211+
if err = executeMsg.Validate(ac); err != nil {
212+
return err
213+
}
214+
215+
msg = executeMsg
216+
} else {
217+
upgradePolicyStr, err := cmd.Flags().GetString(movecli.FlagUpgradePolicy)
218+
if err != nil {
219+
return err
220+
}
221+
222+
upgradePolicy, found := movetypes.UpgradePolicy_value[upgradePolicyStr]
223+
if !found {
224+
return fmt.Errorf("invalid upgrade-policy `%s`", upgradePolicyStr)
225+
}
226+
227+
publishMsg := &movetypes.MsgPublish{
228+
Sender: senderStrAddr,
229+
CodeBytes: moduleBundle,
230+
UpgradePolicy: movetypes.UpgradePolicy(upgradePolicy),
231+
}
232+
233+
if err = publishMsg.Validate(ac); err != nil {
234+
return err
235+
}
236+
237+
msg = publishMsg
238+
}
239+
240+
err = tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
241+
if err != nil {
242+
return err
243+
}
244+
245+
// request contract verify
246+
if verify {
247+
vc, err := getVerifyConfig(cmd)
248+
if err != nil {
249+
return err
250+
}
251+
252+
if err := verifyContract(*vc); err != nil {
253+
return errorsmod.Wrap(err, "failed to verify published package")
254+
}
255+
}
256+
257+
return nil
258+
}
259+
260+
func marshalBytesArrayToHexArray(data [][]byte) string {
261+
str := "["
262+
for _, b := range data {
263+
str += fmt.Sprintf("\"%02x\",", b)
264+
}
265+
str = str[:len(str)-1]
266+
str += "]"
267+
return str
268+
}

cmd/move/move.go

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import (
1313

1414
"github.com/cosmos/cosmos-sdk/client"
1515
"github.com/cosmos/cosmos-sdk/client/flags"
16-
"github.com/cosmos/cosmos-sdk/client/tx"
1716
"github.com/cosmos/cosmos-sdk/version"
1817

1918
movecli "github.com/initia-labs/initia/x/move/client/cli"
20-
movetypes "github.com/initia-labs/initia/x/move/types"
2119

2220
"github.com/initia-labs/movevm/api"
2321
"github.com/initia-labs/movevm/types"
@@ -102,6 +100,7 @@ func MoveCommand(ac address.Codec, useMinlib bool) *cobra.Command {
102100
moveNewCmd(useMinlib),
103101
moveCleanCmd(),
104102
moveDeployCmd(ac),
103+
deployObjectCmd(ac),
105104
moveVerifyCmd(),
106105
moveDocgenCmd(),
107106
)
@@ -402,108 +401,6 @@ func getModuleBundle(packagePath string) ([][]byte, error) {
402401
return moduleBundle, nil
403402
}
404403

405-
func moveDeployCmd(ac address.Codec) *cobra.Command {
406-
cmd := &cobra.Command{
407-
Use: "deploy [flags]",
408-
Short: "deploy a whole move package",
409-
Long: "deploy a whole move package. This command occurs a tx to publish module bundle.",
410-
Args: cobra.ExactArgs(0),
411-
RunE: func(cmd *cobra.Command, args []string) error {
412-
413-
// build package
414-
flagBuild, err := cmd.Flags().GetBool(flagBuild)
415-
if err != nil {
416-
return err
417-
}
418-
419-
if flagBuild {
420-
arg, err := getCompilerArgument(cmd)
421-
if err != nil {
422-
return err
423-
}
424-
425-
_, err = api.BuildContract(*arg)
426-
if err != nil {
427-
return err
428-
}
429-
}
430-
431-
// verify package
432-
flagVerify, err := cmd.Flags().GetBool(flagVerify)
433-
if err != nil {
434-
return err
435-
}
436-
437-
var vc *verifyConfig
438-
if flagVerify { // load verify config here to check flags validation before publishing
439-
vc, err = getVerifyConfig(cmd)
440-
if err != nil {
441-
return err
442-
}
443-
}
444-
445-
// deploy package
446-
clientCtx, err := client.GetClientTxContext(cmd)
447-
if err != nil {
448-
return err
449-
}
450-
451-
packagePath, err := cmd.Flags().GetString(flagPackagePath)
452-
if err != nil {
453-
return err
454-
}
455-
456-
module_bundle, err := getModuleBundle(packagePath)
457-
if err != nil {
458-
return err
459-
}
460-
461-
upgradePolicyStr, err := cmd.Flags().GetString(movecli.FlagUpgradePolicy)
462-
if err != nil {
463-
return err
464-
}
465-
466-
upgradePolicy, found := movetypes.UpgradePolicy_value[upgradePolicyStr]
467-
if !found {
468-
return fmt.Errorf("invalid upgrade-policy `%s`", upgradePolicyStr)
469-
}
470-
471-
msg := movetypes.MsgPublish{
472-
Sender: clientCtx.FromAddress.String(),
473-
CodeBytes: module_bundle,
474-
UpgradePolicy: movetypes.UpgradePolicy(upgradePolicy),
475-
}
476-
477-
if err = msg.Validate(ac); err != nil {
478-
return err
479-
}
480-
481-
err = tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
482-
if err != nil {
483-
return err
484-
}
485-
486-
// request contract verify
487-
if flagVerify {
488-
if err := verifyContract(*vc); err != nil {
489-
return errorsmod.Wrap(err, "failed to verify published package")
490-
}
491-
}
492-
493-
return nil
494-
},
495-
}
496-
497-
// add flat set for upgrade policy
498-
cmd.Flags().AddFlagSet(movecli.FlagSetUpgradePolicy())
499-
500-
addMoveDeployFlags(cmd)
501-
addMoveBuildFlags(cmd)
502-
addMoveVerifyFlags(cmd, false)
503-
flags.AddTxFlagsToCmd(cmd)
504-
return cmd
505-
}
506-
507404
func moveVerifyCmd() *cobra.Command {
508405
cmd := &cobra.Command{
509406
Use: "verify [flags]",

0 commit comments

Comments
 (0)