Skip to content

Commit a4aad23

Browse files
authored
Node: Add adminserver command to generate template for accountant modify balance (wormhole-foundation#3905)
* Node / Adminserver: Command to modify gacct balance * Code review rework * More rework
1 parent b8676f0 commit a4aad23

File tree

4 files changed

+188
-36
lines changed

4 files changed

+188
-36
lines changed

node/cmd/guardiand/admintemplate.go

Lines changed: 151 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/btcsuite/btcutil/bech32"
1212
"github.com/ethereum/go-ethereum/common"
13+
"github.com/holiman/uint256"
1314
"github.com/mr-tron/base58"
1415
"github.com/spf13/pflag"
1516
"github.com/tendermint/tendermint/libs/rand"
@@ -60,6 +61,16 @@ var ibcUpdateChannelChainChainId *string
6061
var recoverChainIdEvmChainId *string
6162
var recoverChainIdNewChainId *string
6263

64+
var accountantModifyBalanceModule *string
65+
var accountantModifyBalanceTargetChainId *string
66+
var accountantModifyBalanceSequence *string
67+
var accountantModifyBalanceChainId *string
68+
var accountantModifyBalanceTokenChainId *string
69+
var accountantModifyBalanceTokenAddress *string
70+
var accountantModifyBalanceAction *string
71+
var accountantModifyBalanceAmount *string
72+
var accountantModifyBalanceReason *string
73+
6374
var governanceContractAddress *string
6475
var governanceTargetAddress *string
6576
var governanceTargetChain *string
@@ -177,6 +188,21 @@ func init() {
177188
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(moduleFlagSet)
178189
TemplateCmd.AddCommand(AdminClientRecoverChainIdCmd)
179190

191+
// flags for the accountant-modify-balance command
192+
accountantModifyBalanceFlagSet := pflag.NewFlagSet("accountant-modify-balance", pflag.ExitOnError)
193+
accountantModifyBalanceModule = accountantModifyBalanceFlagSet.String("module", "GlobalAccountant", "Module identifier of the accountant")
194+
accountantModifyBalanceTargetChainId = accountantModifyBalanceFlagSet.String("target-chain-id", "", "ID of the chain to receive this modification")
195+
accountantModifyBalanceSequence = accountantModifyBalanceFlagSet.String("sequence", "", "The sequence number of this modification. Each modification must be uniquely identifiable just by its sequence number")
196+
accountantModifyBalanceChainId = accountantModifyBalanceFlagSet.String("chain-id", "", "Chain ID of the account to be modified")
197+
accountantModifyBalanceTokenChainId = accountantModifyBalanceFlagSet.String("token-chain-id", "", "Chain ID of the native chain for the token")
198+
accountantModifyBalanceTokenAddress = accountantModifyBalanceFlagSet.String("token-address", "", "Address of the token on its native chain, hex string encoded")
199+
accountantModifyBalanceAction = accountantModifyBalanceFlagSet.String("action", "", "Kind of modification to be made (1 = add, 2 = sub)")
200+
accountantModifyBalanceAmount = accountantModifyBalanceFlagSet.String("amount", "", `Amount to be modified (decimal formatted string indicating the"raw" amount, not adjusted by the decimals of the token`)
201+
accountantModifyBalanceReason = accountantModifyBalanceFlagSet.String("reason", "", "human-readable reason for the modification")
202+
AdminClientAccountantModifyBalanceCmd.Flags().AddFlagSet(accountantModifyBalanceFlagSet)
203+
AdminClientAccountantModifyBalanceCmd.Flags().AddFlagSet(moduleFlagSet)
204+
TemplateCmd.AddCommand(AdminClientAccountantModifyBalanceCmd)
205+
180206
// flags for general-purpose governance call command
181207
generalPurposeGovernanceFlagSet := pflag.NewFlagSet("general-purpose-governance", pflag.ExitOnError)
182208
governanceContractAddress = generalPurposeGovernanceFlagSet.String("governance-contract", "", "Governance contract address")
@@ -226,6 +252,12 @@ var AdminClientRecoverChainIdCmd = &cobra.Command{
226252
Run: runRecoverChainIdTemplate,
227253
}
228254

255+
var AdminClientAccountantModifyBalanceCmd = &cobra.Command{
256+
Use: "accountant-modify-balance",
257+
Short: "Generate an empty accountant modify balance template at specified path",
258+
Run: runAccountantModifyBalanceTemplate,
259+
}
260+
229261
var AdminClientCircleIntegrationUpdateWormholeFinalityCmd = &cobra.Command{
230262
Use: "circle-integration-update-wormhole-finality",
231263
Short: "Generate an empty circle integration update wormhole finality template at specified path",
@@ -348,7 +380,7 @@ func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
348380

349381
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
350382
if err != nil {
351-
panic(err)
383+
log.Fatal("failed to marshal request: ", err)
352384
}
353385
fmt.Print(string(b))
354386
}
@@ -381,7 +413,7 @@ func runContractUpgradeTemplate(cmd *cobra.Command, args []string) {
381413

382414
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
383415
if err != nil {
384-
panic(err)
416+
log.Fatal("failed to marshal request: ", err)
385417
}
386418
fmt.Print(string(b))
387419
}
@@ -414,7 +446,7 @@ func runTokenBridgeRegisterChainTemplate(cmd *cobra.Command, args []string) {
414446

415447
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
416448
if err != nil {
417-
panic(err)
449+
log.Fatal("failed to marshal request: ", err)
418450
}
419451
fmt.Print(string(b))
420452
}
@@ -448,7 +480,7 @@ func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
448480

449481
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
450482
if err != nil {
451-
panic(err)
483+
log.Fatal("failed to marshal request: ", err)
452484
}
453485
fmt.Print(string(b))
454486
}
@@ -490,7 +522,104 @@ func runRecoverChainIdTemplate(cmd *cobra.Command, args []string) {
490522

491523
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
492524
if err != nil {
493-
panic(err)
525+
log.Fatal("failed to marshal request: ", err)
526+
}
527+
fmt.Print(string(b))
528+
}
529+
530+
func runAccountantModifyBalanceTemplate(cmd *cobra.Command, args []string) {
531+
if *accountantModifyBalanceModule == "" {
532+
log.Fatal("--module must be specified.")
533+
}
534+
if *accountantModifyBalanceTargetChainId == "" {
535+
log.Fatal("--target-chain-id must be specified.")
536+
}
537+
targetChainID, err := parseChainID(*accountantModifyBalanceTargetChainId)
538+
if err != nil {
539+
log.Fatal("failed to parse target chain id: ", err)
540+
}
541+
if *accountantModifyBalanceSequence == "" {
542+
log.Fatal("--sequence must be specified")
543+
}
544+
sequence, err := strconv.ParseUint(*accountantModifyBalanceSequence, 10, 64)
545+
if err != nil {
546+
log.Fatal("failed to parse sequence as uint64: ", err)
547+
}
548+
if *accountantModifyBalanceChainId == "" {
549+
log.Fatal("--chain-id must be specified.")
550+
}
551+
chainID, err := parseChainID(*accountantModifyBalanceChainId)
552+
if err != nil {
553+
log.Fatal("failed to parse chain id: ", err)
554+
}
555+
if *accountantModifyBalanceTokenChainId == "" {
556+
log.Fatal("--token-chain-id must be specified.")
557+
}
558+
tokenChainID, err := parseChainID(*accountantModifyBalanceTokenChainId)
559+
if err != nil {
560+
log.Fatal("failed to parse token chain id: ", err)
561+
}
562+
if *accountantModifyBalanceTokenAddress == "" {
563+
log.Fatal("--token-address must be specified.")
564+
}
565+
tokenAddress, err := parseAddress(*accountantModifyBalanceTokenAddress)
566+
if err != nil {
567+
log.Fatal("failed to parse token address: ", err)
568+
}
569+
if *accountantModifyBalanceAction == "" {
570+
log.Fatal("--action must be specified")
571+
}
572+
action, err := strconv.ParseUint(*accountantModifyBalanceAction, 10, 8)
573+
if err != nil {
574+
log.Fatal("failed to parse modification action as uint8: ", err)
575+
}
576+
if action != uint64(nodev1.ModificationKind_MODIFICATION_KIND_ADD) && action != uint64(nodev1.ModificationKind_MODIFICATION_KIND_SUBTRACT) {
577+
log.Fatal("invalid modification action, must be 1 (add) or 2 (subtract)")
578+
}
579+
if *accountantModifyBalanceAmount == "" {
580+
log.Fatal("--amount must be specified.")
581+
}
582+
amount_big := big.NewInt(0)
583+
amount_big, ok := amount_big.SetString(*accountantModifyBalanceAmount, 10)
584+
if !ok {
585+
log.Fatal("failed to parse amount")
586+
}
587+
_, overflow := uint256.FromBig(amount_big)
588+
if overflow {
589+
log.Fatal("amount overflowed uint256")
590+
}
591+
if *accountantModifyBalanceReason == "" {
592+
log.Fatal("--reason must be specified.")
593+
}
594+
if len(*accountantModifyBalanceReason) > vaa.AccountantModifyBalanceReasonLength {
595+
log.Fatalf("reason is too long, can be at most %d bytes", vaa.AccountantModifyBalanceReasonLength)
596+
}
597+
m := &nodev1.InjectGovernanceVAARequest{
598+
CurrentSetIndex: uint32(*templateGuardianIndex),
599+
Messages: []*nodev1.GovernanceMessage{
600+
{
601+
Sequence: rand.Uint64(),
602+
Nonce: rand.Uint32(),
603+
Payload: &nodev1.GovernanceMessage_AccountantModifyBalance{
604+
AccountantModifyBalance: &nodev1.AccountantModifyBalance{
605+
Module: *accountantModifyBalanceModule,
606+
TargetChainId: uint32(targetChainID),
607+
Sequence: uint64(sequence),
608+
ChainId: uint32(chainID),
609+
TokenChain: uint32(tokenChainID),
610+
TokenAddress: tokenAddress,
611+
Kind: nodev1.ModificationKind(action),
612+
Amount: *accountantModifyBalanceAmount,
613+
Reason: *accountantModifyBalanceReason,
614+
},
615+
},
616+
},
617+
},
618+
}
619+
620+
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
621+
if err != nil {
622+
log.Fatal("failed to marshal request: ", err)
494623
}
495624
fmt.Print(string(b))
496625
}
@@ -529,7 +658,7 @@ func runCircleIntegrationUpdateWormholeFinalityTemplate(cmd *cobra.Command, args
529658

530659
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
531660
if err != nil {
532-
panic(err)
661+
log.Fatal("failed to marshal request: ", err)
533662
}
534663
fmt.Print(string(b))
535664
}
@@ -584,7 +713,7 @@ func runCircleIntegrationRegisterEmitterAndDomainTemplate(cmd *cobra.Command, ar
584713

585714
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
586715
if err != nil {
587-
panic(err)
716+
log.Fatal("failed to marshal request: ", err)
588717
}
589718
fmt.Print(string(b))
590719
}
@@ -623,7 +752,7 @@ func runCircleIntegrationUpgradeContractImplementationTemplate(cmd *cobra.Comman
623752

624753
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
625754
if err != nil {
626-
panic(err)
755+
log.Fatal("failed to marshal request: ", err)
627756
}
628757
fmt.Print(string(b))
629758
}
@@ -661,7 +790,7 @@ func runWormchainStoreCodeTemplate(cmd *cobra.Command, args []string) {
661790

662791
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
663792
if err != nil {
664-
panic(err)
793+
log.Fatal("failed to marshal request: ", err)
665794
}
666795
fmt.Print(string(b))
667796
}
@@ -700,7 +829,7 @@ func runWormchainInstantiateContractTemplate(cmd *cobra.Command, args []string)
700829

701830
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
702831
if err != nil {
703-
panic(err)
832+
log.Fatal("failed to marshal request: ", err)
704833
}
705834
fmt.Print(string(b))
706835
}
@@ -739,7 +868,7 @@ func runWormchainMigrateContractTemplate(cmd *cobra.Command, args []string) {
739868

740869
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
741870
if err != nil {
742-
panic(err)
871+
log.Fatal("failed to marshal request: ", err)
743872
}
744873
fmt.Print(string(b))
745874
}
@@ -783,7 +912,7 @@ func runWormchainWasmInstantiateAllowlistTemplate(action nodev1.WormchainWasmIns
783912

784913
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
785914
if err != nil {
786-
panic(err)
915+
log.Fatal("failed to marshal request: ", err)
787916
}
788917
fmt.Print(string(b))
789918
}
@@ -820,7 +949,7 @@ func runGatewayScheduleUpgradeTemplate(cmd *cobra.Command, args []string) {
820949

821950
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
822951
if err != nil {
823-
panic(err)
952+
log.Fatal("failed to marshal request: ", err)
824953
}
825954
fmt.Print(string(b))
826955
}
@@ -839,7 +968,7 @@ func runGatewayCancelUpgradeTemplate(cmd *cobra.Command, args []string) {
839968

840969
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
841970
if err != nil {
842-
panic(err)
971+
log.Fatal("failed to marshal request: ", err)
843972
}
844973
fmt.Print(string(b))
845974
}
@@ -866,7 +995,7 @@ func runGatewayIbcComposabilityMwSetContractTemplate(cmd *cobra.Command, args []
866995

867996
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
868997
if err != nil {
869-
panic(err)
998+
log.Fatal("failed to marshal request: ", err)
870999
}
8711000
fmt.Print(string(b))
8721001
}
@@ -923,7 +1052,7 @@ func runIbcUpdateChannelChainTemplate(module nodev1.IbcUpdateChannelChainModule)
9231052

9241053
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
9251054
if err != nil {
926-
panic(err)
1055+
log.Fatal("failed to marshal request: ", err)
9271056
}
9281057
fmt.Print(string(b))
9291058

@@ -957,7 +1086,7 @@ func runWormholeRelayerSetDefaultDeliveryProviderTemplate(cmd *cobra.Command, ar
9571086

9581087
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
9591088
if err != nil {
960-
panic(err)
1089+
log.Fatal("failed to marshal request: ", err)
9611090
}
9621091
fmt.Print(string(b))
9631092
}
@@ -1008,7 +1137,7 @@ func runGeneralPurposeGovernanceEvmCallTemplate(cmd *cobra.Command, args []strin
10081137

10091138
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
10101139
if err != nil {
1011-
panic(err)
1140+
log.Fatal("failed to marshal request: ", err)
10121141
}
10131142
fmt.Print(string(b))
10141143
}
@@ -1051,7 +1180,7 @@ func runGeneralPurposeGovernanceSolanaCallTemplate(cmd *cobra.Command, args []st
10511180

10521181
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
10531182
if err != nil {
1054-
panic(err)
1183+
log.Fatal("failed to marshal request: ", err)
10551184
}
10561185
fmt.Print(string(b))
10571186
}
@@ -1097,10 +1226,10 @@ func parseChainID(name string) (vaa.ChainID, error) {
10971226
return s, nil
10981227
}
10991228

1100-
// parse as uint32
1101-
i, err := strconv.ParseUint(name, 10, 32)
1229+
// parse as uint16
1230+
i, err := strconv.ParseUint(name, 10, 16)
11021231
if err != nil {
1103-
return 0, fmt.Errorf("failed to parse as name or uint32: %v", err)
1232+
return 0, fmt.Errorf("failed to parse as name or uint16: %v", err)
11041233
}
11051234

11061235
return vaa.ChainID(i), nil

node/pkg/adminrpc/adminserver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ func accountantModifyBalance(req *nodev1.AccountantModifyBalance, timestamp time
251251
return nil, errors.New("invalid new token address (expected 32 bytes)")
252252
}
253253

254-
if len(req.Reason) > 32 {
255-
return nil, errors.New("the reason should not be larger than 32 bytes")
254+
if len(req.Reason) > vaa.AccountantModifyBalanceReasonLength {
255+
return nil, fmt.Errorf("the reason should not be larger than %d bytes", vaa.AccountantModifyBalanceReasonLength)
256256
}
257257

258258
amount_big := big.NewInt(0)

0 commit comments

Comments
 (0)