diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ebe2b7eb..cc4af23563 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features * Added support to set a list of specific recipients allowed for send authorizations in the marker module [#1237](https://github.com/provenance-io/provenance/issues/1237). +* Added msg to add, finalize, and activate a marker in a single request [#770](https://github.com/provenance-io/provenance/issues/770). ### Improvements diff --git a/app/params/weights.go b/app/params/weights.go index 22e5c5e984..ecbe1a58b2 100644 --- a/app/params/weights.go +++ b/app/params/weights.go @@ -19,11 +19,11 @@ const ( DefaultWeightRemoveAdministratorProposalContent int = 5 DefaultWeightChangeStatusProposalContent int = 5 DefaultWeightSetDenomMetadataProposalContent int = 5 - DefaultWeightMsgAddMarker int = 100 - DefaultWeightMsgChangeStatus int = 10 - DefaultWeightMsgAddAccess int = 10 - DefaultWeightMsgMintMarker int = 67 - DefaultWeightMsgBurnMarker int = 67 + // Adjusted marker operations to a cumulative weight of 100 + DefaultWeightMsgAddMarker int = 60 + DefaultWeightMsgChangeStatus int = 10 + DefaultWeightMsgAddAccess int = 10 + DefaultWeightMsgAddFinalizeActivateMarker int = 20 // MsgFees DefaultWeightAddMsgFeeProposalContent int = 75 DefaultWeightRemoveMsgFeeProposalContent int = 25 diff --git a/docs/proto-docs.md b/docs/proto-docs.md index de9081b3e1..01d07c1210 100644 --- a/docs/proto-docs.md +++ b/docs/proto-docs.md @@ -112,6 +112,8 @@ - [MsgActivateResponse](#provenance.marker.v1.MsgActivateResponse) - [MsgAddAccessRequest](#provenance.marker.v1.MsgAddAccessRequest) - [MsgAddAccessResponse](#provenance.marker.v1.MsgAddAccessResponse) + - [MsgAddFinalizeActivateMarkerRequest](#provenance.marker.v1.MsgAddFinalizeActivateMarkerRequest) + - [MsgAddFinalizeActivateMarkerResponse](#provenance.marker.v1.MsgAddFinalizeActivateMarkerResponse) - [MsgAddMarkerRequest](#provenance.marker.v1.MsgAddMarkerRequest) - [MsgAddMarkerResponse](#provenance.marker.v1.MsgAddMarkerResponse) - [MsgBurnRequest](#provenance.marker.v1.MsgBurnRequest) @@ -933,7 +935,7 @@ Msg defines the attribute module Msg service. ### AccessGrant -AccessGrant associates a colelction of permisssions with an address for delegated marker account control. +AccessGrant associates a collection of permissions with an address for delegated marker account control. | Field | Type | Label | Description | @@ -1928,6 +1930,37 @@ MsgAddAccessResponse defines the Msg/AddAccess response type + + +### MsgAddFinalizeActivateMarkerRequest +MsgAddFinalizeActivateMarkerRequest defines the Msg/AddFinalizeActivateMarker request type + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `manager` | [string](#string) | | | +| `from_address` | [string](#string) | | | +| `marker_type` | [MarkerType](#provenance.marker.v1.MarkerType) | | | +| `access_list` | [AccessGrant](#provenance.marker.v1.AccessGrant) | repeated | | +| `supply_fixed` | [bool](#bool) | | | +| `allow_governance_control` | [bool](#bool) | | | + + + + + + + + +### MsgAddFinalizeActivateMarkerResponse +MsgAddFinalizeActivateMarkerResponse defines the Msg/AddFinalizeActivateMarker response type + + + + + + ### MsgAddMarkerRequest @@ -2281,6 +2314,7 @@ Msg defines the Marker Msg service. | `IbcTransfer` | [MsgIbcTransferRequest](#provenance.marker.v1.MsgIbcTransferRequest) | [MsgIbcTransferResponse](#provenance.marker.v1.MsgIbcTransferResponse) | Transfer over ibc any marker(including restricted markers) between ibc accounts. The relayer is still needed to accomplish ibc middleware relays. | | | `SetDenomMetadata` | [MsgSetDenomMetadataRequest](#provenance.marker.v1.MsgSetDenomMetadataRequest) | [MsgSetDenomMetadataResponse](#provenance.marker.v1.MsgSetDenomMetadataResponse) | Allows Denom Metadata (see bank module) to be set for the Marker's Denom | | | `GrantAllowance` | [MsgGrantAllowanceRequest](#provenance.marker.v1.MsgGrantAllowanceRequest) | [MsgGrantAllowanceResponse](#provenance.marker.v1.MsgGrantAllowanceResponse) | GrantAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | +| `AddFinalizeActivateMarker` | [MsgAddFinalizeActivateMarkerRequest](#provenance.marker.v1.MsgAddFinalizeActivateMarkerRequest) | [MsgAddFinalizeActivateMarkerResponse](#provenance.marker.v1.MsgAddFinalizeActivateMarkerResponse) | AddFinalizeActivateMarker | | diff --git a/proto/provenance/marker/v1/accessgrant.proto b/proto/provenance/marker/v1/accessgrant.proto index 913d3a3038..4ab790420d 100644 --- a/proto/provenance/marker/v1/accessgrant.proto +++ b/proto/provenance/marker/v1/accessgrant.proto @@ -10,7 +10,7 @@ option java_package = "io.provenance.marker.v1"; option java_multiple_files = true; option java_outer_classname = "AccessGrantProto"; -// AccessGrant associates a colelction of permisssions with an address for delegated marker account control. +// AccessGrant associates a collection of permissions with an address for delegated marker account control. message AccessGrant { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; diff --git a/proto/provenance/marker/v1/tx.proto b/proto/provenance/marker/v1/tx.proto index a5764ba628..935b31aab6 100644 --- a/proto/provenance/marker/v1/tx.proto +++ b/proto/provenance/marker/v1/tx.proto @@ -47,6 +47,8 @@ service Msg { // GrantAllowance grants fee allowance to the grantee on the granter's // account with the provided expiration time. rpc GrantAllowance(MsgGrantAllowanceRequest) returns (MsgGrantAllowanceResponse); + // AddFinalizeActivateMarker + rpc AddFinalizeActivateMarker(MsgAddFinalizeActivateMarkerRequest) returns (MsgAddFinalizeActivateMarkerResponse); } // MsgGrantAllowanceRequest validates permission to create a fee grant based on marker admin access. If @@ -193,4 +195,19 @@ message MsgSetDenomMetadataRequest { } // MsgSetDenomMetadataResponse defines the Msg/SetDenomMetadata response type -message MsgSetDenomMetadataResponse {} \ No newline at end of file +message MsgSetDenomMetadataResponse {} + +// MsgAddFinalizeActivateMarkerRequest defines the Msg/AddFinalizeActivateMarker request type +message MsgAddFinalizeActivateMarkerRequest { + cosmos.base.v1beta1.Coin amount = 1 + [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Coin"]; + string manager = 3; + string from_address = 4; + MarkerType marker_type = 5; + repeated AccessGrant access_list = 6 [(gogoproto.nullable) = false]; + bool supply_fixed = 7; + bool allow_governance_control = 8; +} + +// MsgAddFinalizeActivateMarkerResponse defines the Msg/AddFinalizeActivateMarker response type +message MsgAddFinalizeActivateMarkerResponse {} diff --git a/x/marker/client/cli/cli_test.go b/x/marker/client/cli/cli_test.go index a5249f59c6..72d51ea794 100644 --- a/x/marker/client/cli/cli_test.go +++ b/x/marker/client/cli/cli_test.go @@ -31,6 +31,7 @@ import ( "github.com/provenance-io/provenance/internal/pioconfig" "github.com/provenance-io/provenance/testutil" markercli "github.com/provenance-io/provenance/x/marker/client/cli" + "github.com/provenance-io/provenance/x/marker/types" markertypes "github.com/provenance-io/provenance/x/marker/types" ) @@ -1254,3 +1255,193 @@ func (s *IntegrationTestSuite) TestPaginationWithPageKey() { func getFormattedExpiration(duration int64) string { return time.Now().Add(time.Duration(duration) * time.Second).Format(time.RFC3339) } + +func (s *IntegrationTestSuite) TestAddFinalizeActivateMarkerTxCommands() { + + testCases := []struct { + name string + cmd *cobra.Command + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + { + "create a new marker, finalize it and activate it.", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000newhotdog", + getAccessGrantString(s.testnet.Validators[0].Address, s.accountAddresses[1]), + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "true"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "true"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, 0, + }, + { + "create a new marker, finalize it and activate it, with access grant to one address ", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000newhotdog1", + getAccessGrantString(s.testnet.Validators[0].Address, nil), + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "true"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "true"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, 0, + }, + { + "create a new marker with no access grant ", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000newhotdog1", + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "true"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "true"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, &sdk.TxResponse{}, 0, + }, + { + "create a new marker, finalize it and activate it with dashes and periods", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000newcat-scratch-fever.bobcat", + getAccessGrantString(s.testnet.Validators[0].Address, nil), + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "true"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "true"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, 0, + }, + { + "fail to create add/finalize/activate marker, incorrect allow governance value", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000hotdog", + getAccessGrantString(s.testnet.Validators[0].Address, nil), + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "false"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "wrong"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, &sdk.TxResponse{}, 0, + }, + { + "fail to create add/finalize/activate marker, incorrect supply fixed value", + markercli.GetCmdAddFinalizeActivateMarker(), + []string{ + "1000hotdog", + getAccessGrantString(s.testnet.Validators[0].Address, nil), + fmt.Sprintf("--%s=%s", markercli.FlagType, "RESTRICTED"), + fmt.Sprintf("--%s=%s", markercli.FlagSupplyFixed, "wrong"), + fmt.Sprintf("--%s=%s", markercli.FlagAllowGovernanceControl, "true"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, &sdk.TxResponse{}, 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + clientCtx := s.testnet.Validators[0].ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, tc.cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code) + } + }) + } +} + +func getAccessGrantString(address sdk.AccAddress, anotherAddress sdk.AccAddress) string { + if anotherAddress != nil { + accessGrant := address.String() + ",mint,admin;" + anotherAddress.String() + ",burn" + return accessGrant + } else { + accessGrant := address.String() + ",mint,admin;" + return accessGrant + } +} + +func (s *IntegrationTestSuite) TestParseAccessGrantFromString() { + testCases := []struct { + name string + accessGrantString string + expectPanic bool + expectedResult []types.AccessGrant + }{ + { + "successfully parses empty string", + "", + false, + []types.AccessGrant{}, + }, + { + "fails parsing invalid string", + "blah", + true, + []types.AccessGrant{}, + }, + { + "should fail empty list of permissions", + ",,;", + true, + []types.AccessGrant{}, + }, + { + "should fail address is not valid", + "NotAnAddress,mint;", + true, + []types.AccessGrant{}, + }, + { + "should succeed to add access type", + fmt.Sprintf("%s,mint;", s.accountAddresses[0].String()), + false, + []types.AccessGrant{markertypes.AccessGrant{Address: s.accountAddresses[0].String(), Permissions: []markertypes.Access{markertypes.Access_Mint}}}, + }, + } + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + if tc.expectPanic { + panicFunc := func() { markercli.ParseAccessGrantFromString(tc.accessGrantString) } + s.Assert().Panics(panicFunc) + + } else { + result := markercli.ParseAccessGrantFromString(tc.accessGrantString) + s.Assert().ElementsMatch(result, tc.expectedResult) + } + }) + } +} diff --git a/x/marker/client/cli/tx.go b/x/marker/client/cli/tx.go index 1910bff1e2..333ad1e082 100644 --- a/x/marker/client/cli/tx.go +++ b/x/marker/client/cli/tx.go @@ -70,6 +70,7 @@ func NewTxCmd() *cobra.Command { GetCmdRevokeAuthorization(), GetCmdFeeGrant(), GetIbcTransferTxCmd(), + GetCmdAddFinalizeActivateMarker(), ) return txCmd } @@ -905,6 +906,63 @@ Examples: return cmd } +// GetCmdAddFinalizeActivateMarker implements the add finalize activate marker command +func GetCmdAddFinalizeActivateMarker() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-finalize-activate [coin] [access-grant-string]", + Aliases: []string{"cfa"}, + Args: cobra.ExactArgs(2), + Short: "Creates, Finalizes and Activates a new marker", + Long: strings.TrimSpace(`Creates a new marker, finalizes it and put's it ACTIVATED state managed by the from address +with the given supply amount and denomination provided in the coin argument +`), + Example: fmt.Sprintf(`$ %s tx marker create-finalize-activate 1000hotdogcoin address1,mint,admin;address2,burn --%s=false --%s=false --from=mykey`, FlagType, FlagSupplyFixed, FlagAllowGovernanceControl), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + markerType := "" + coin, err := sdk.ParseCoinNormalized(args[0]) + if err != nil { + return fmt.Errorf("invalid coin %s", args[0]) + } + callerAddr := clientCtx.GetFromAddress() + markerType, err = cmd.Flags().GetString(FlagType) + if err != nil { + return fmt.Errorf("invalid marker type: %w", err) + } + typeValue := types.MarkerType_Coin + if len(markerType) > 0 { + typeValue = types.MarkerType(types.MarkerType_value["MARKER_TYPE_"+markerType]) + if typeValue < 1 { + return fmt.Errorf("invalid marker type: %s; expected COIN|RESTRICTED", markerType) + } + } + supplyFixed, err := cmd.Flags().GetBool(FlagSupplyFixed) + if err != nil { + return fmt.Errorf("incorrect value for %s flag. Accepted: true,false Error: %w", FlagSupplyFixed, err) + } + allowGovernanceControl, err := cmd.Flags().GetBool(FlagAllowGovernanceControl) + if err != nil { + return fmt.Errorf("incorrect value for %s flag. Accepted: true,false Error: %w", FlagAllowGovernanceControl, err) + } + accessGrants := ParseAccessGrantFromString(args[1]) + if len(accessGrants) == 0 { + panic("at least one access grant should be present.") + } + msg := types.NewMsgAddFinalizeActivateMarkerRequest(coin.Denom, coin.Amount, callerAddr, callerAddr, typeValue, supplyFixed, allowGovernanceControl, accessGrants) + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + cmd.Flags().String(FlagType, "COIN", "a marker type to assign (default is COIN)") + cmd.Flags().Bool(FlagSupplyFixed, false, "a true or false value to denote if a supply is fixed (default is false)") + cmd.Flags().Bool(FlagAllowGovernanceControl, false, "a true or false value to denote if marker is allowed governance control (default is false)") + flags.AddTxFlagsToCmd(cmd) + return cmd +} + func getPeriodReset(duration int64) time.Time { return time.Now().Add(getPeriod(duration)) } @@ -912,3 +970,27 @@ func getPeriodReset(duration int64) time.Time { func getPeriod(duration int64) time.Duration { return time.Duration(duration) * time.Second } + +// ParseAccessGrantFromString splits string (example address1,perm1,perm2...;address2, perm1...) to AccessGrant +func ParseAccessGrantFromString(addressPermissionString string) []types.AccessGrant { + parts := strings.Split(addressPermissionString, ";") + grants := make([]types.AccessGrant, 0) + for _, p := range parts { + // ignore if someone put in a ; at the end by mistake + if len(p) == 0 { + continue + } + partsPerAddress := strings.Split(p, ",") + // if it has an address has to have at least one access associated with it + if !(len(partsPerAddress) > 1) { + panic("at least one grant should be provided with address") + } + var permissions types.AccessList + address := sdk.MustAccAddressFromBech32(partsPerAddress[0]) + for _, permission := range partsPerAddress[1:] { + permissions = append(permissions, types.AccessByName(permission)) + } + grants = append(grants, *types.NewAccessGrant(address, permissions)) + } + return grants +} diff --git a/x/marker/handler.go b/x/marker/handler.go index e48f803d1b..30cec88458 100644 --- a/x/marker/handler.go +++ b/x/marker/handler.go @@ -61,6 +61,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler { res, err := msgServer.SetDenomMetadata(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgAddFinalizeActivateMarkerRequest: + res, err := msgServer.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: return nil, sdkerrors.ErrUnknownRequest.Wrapf("unrecognized %s message type: %T", types.ModuleName, msg) } diff --git a/x/marker/handler_test.go b/x/marker/handler_test.go index 593d09086f..2a80ad7e95 100644 --- a/x/marker/handler_test.go +++ b/x/marker/handler_test.go @@ -597,3 +597,56 @@ func (s *HandlerTestSuite) TestMsgSetDenomMetadataRequest() { } s.runTests(cases) } +func (s *HandlerTestSuite) TestMsgAddFinalizeActivateMarkerRequest() { + denom := "hotdog" + denomWithDashPeriod := fmt.Sprintf("%s-my.marker", denom) + activeStatus := types.NewMsgAddFinalizeActivateMarkerRequest(denom, sdk.NewInt(100), s.user1Addr, s.user1Addr, types.MarkerType_Coin, true, true, []types.AccessGrant{*types.NewAccessGrant(s.user1Addr, []types.Access{types.Access_Mint, types.Access_Admin})}) + + accessGrantWrongStatus := types.NewMsgAddFinalizeActivateMarkerRequest(denom, sdk.NewInt(100), s.user1Addr, s.user1Addr, types.MarkerType_Coin, true, true, nil) + + cases := []CommonTest{ + { + "should successfully ADD,FINALIZE,ACTIVATE new marker", + activeStatus, + []string{s.user1}, + "", + types.NewEventMarkerAdd(denom, "100", "proposed", s.user1, types.MarkerType_Coin.String()), + }, + { + "should fail to ADD,FINALIZE,ACTIVATE new marker, validate basic failure", + accessGrantWrongStatus, + []string{s.user1}, + "since this will activate the marker, must have at least one access list defined: invalid request", + nil, + }, + { + "should fail to ADD,FINALIZE,ACTIVATE new marker, marker already exists", + types.NewMsgAddMarkerRequest(denom, sdk.NewInt(100), s.user1Addr, s.user1Addr, types.MarkerType_Coin, true, true), + []string{s.user1}, + fmt.Sprintf("marker address already exists for %s: invalid request", types.MustGetMarkerAddress(denom)), + nil, + }, + { + "should successfully add marker with dash and period", + types.NewMsgAddMarkerRequest(denomWithDashPeriod, sdk.NewInt(1000), s.user1Addr, s.user1Addr, types.MarkerType_Coin, true, true), + []string{s.user1}, + "", + types.NewEventMarkerAdd(denomWithDashPeriod, "1000", "proposed", s.user1, types.MarkerType_Coin.String()), + }, + { + "should successfully mint denom", + types.NewMsgMintRequest(s.user1Addr, sdk.NewInt64Coin(denom, 1000)), + []string{s.user1}, + "", + types.NewEventMarkerMint("1000", denom, s.user1), + }, + { + "should fail to burn denom, user doesn't have permissions", + types.NewMsgBurnRequest(s.user1Addr, sdk.NewInt64Coin(denom, 50)), + []string{s.user1}, + fmt.Sprintf("%s does not have ACCESS_BURN on hotdog markeraccount: invalid request", s.user1), + nil, + }, + } + s.runTests(cases) +} diff --git a/x/marker/keeper/keeper_test.go b/x/marker/keeper/keeper_test.go index 566104677c..2f98c0ef95 100644 --- a/x/marker/keeper/keeper_test.go +++ b/x/marker/keeper/keeper_test.go @@ -677,3 +677,146 @@ func testUserAddress(name string) sdk.AccAddress { addr := types.MustGetMarkerAddress(name) return addr } + +func TestAddFinalizeActivateMarker(t *testing.T) { + app := simapp.Setup(t) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + server := markerkeeper.NewMsgServerImpl(app.MarkerKeeper) + + addr := types.MustGetMarkerAddress("testcoin") + pubkey := secp256k1.GenPrivKey().PubKey() + user := testUserAddress("testcoin") + manager := testUserAddress("manager") + existingBalance := sdk.NewCoin("coin", sdk.NewInt(1000)) + + // prefund the marker address so an account gets created before the marker does. + app.AccountKeeper.SetAccount(ctx, authtypes.NewBaseAccount(user, pubkey, 0, 0)) + require.NoError(t, testutil.FundAccount(app.BankKeeper, ctx, addr, sdk.NewCoins(existingBalance)), "funding account") + require.Equal(t, existingBalance, app.BankKeeper.GetBalance(ctx, addr, "coin"), "account balance must be set") + + // Creating a marker over an account with zero sequence is fine. + // One shot marker creation + _, err := server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), types.NewMsgAddFinalizeActivateMarkerRequest( + "testcoin", + sdk.NewInt(30), + user, + manager, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(manager, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + require.NoError(t, err, "should allow a marker over existing account that has not signed anything.") + + // existing coin balance must still be present + require.Equal(t, existingBalance, app.BankKeeper.GetBalance(ctx, addr, "coin"), "account balances must be preserved") + + m, err := app.MarkerKeeper.GetMarkerByDenom(ctx, "testcoin") + require.NoError(t, err) + require.EqualValues(t, m.GetSupply(), sdk.NewInt64Coin("testcoin", 30)) + require.EqualValues(t, m.GetStatus(), types.StatusActive) + + m, err = app.MarkerKeeper.GetMarker(ctx, user) + require.NoError(t, err) + require.EqualValues(t, m.GetSupply(), sdk.NewInt64Coin("testcoin", 30)) + require.EqualValues(t, m.GetStatus(), types.StatusActive) + + // Creating a marker over an existing marker fails. + _, err = server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), types.NewMsgAddFinalizeActivateMarkerRequest( + "testcoin", + sdk.NewInt(30), + user, + manager, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(manager, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + require.Error(t, err, "fails because marker already exists") + + // Load the created marker + m, err = app.MarkerKeeper.GetMarker(ctx, user) + require.NoError(t, err) + require.EqualValues(t, m.GetSupply(), sdk.NewInt64Coin("testcoin", 30)) + require.EqualValues(t, m.GetStatus(), types.StatusActive) + + // entire supply should have been allocated to marker acount + require.EqualValues(t, app.MarkerKeeper.GetEscrow(ctx, m).AmountOf("testcoin"), sdk.NewInt(30)) +} + +// Creating a marker over an existing account with a positive sequence number fails. +func TestInvalidAccount(t *testing.T) { + app := simapp.Setup(t) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + pubkey := secp256k1.GenPrivKey().PubKey() + server := markerkeeper.NewMsgServerImpl(app.MarkerKeeper) + user := testUserAddress("testcoin") + manager := testUserAddress("manager") + // replace existing test account with a new copy that has a positive sequence number + app.AccountKeeper.SetAccount(ctx, authtypes.NewBaseAccount(user, pubkey, 0, 10)) + + _, err := server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), types.NewMsgAddFinalizeActivateMarkerRequest( + "testcoin", + sdk.NewInt(30), + user, + manager, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(manager, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + require.Error(t, err, "should not allow creation over and existing account with a positive sequence number.") + require.Contains(t, err.Error(), "account at "+user.String()+" is not a marker account: invalid request") +} + +func TestAddFinalizeActivateMarkerUnrestrictedDenoms(t *testing.T) { + app := simapp.Setup(t) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + server := markerkeeper.NewMsgServerImpl(app.MarkerKeeper) + + user := testUserAddress("test") + + // Require a long unrestricted denom + app.MarkerKeeper.SetParams(ctx, types.Params{UnrestrictedDenomRegex: "[a-z]{12,20}"}) + + _, err := server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), + types.NewMsgAddFinalizeActivateMarkerRequest( + "tooshort", + sdk.NewInt(30), + user, + user, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(user, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + require.Error(t, err, "fails with unrestricted denom length fault") + require.Equal(t, fmt.Errorf("invalid denom [tooshort] (fails unrestricted marker denom validation [a-z]{12,20})"), err, "should fail with denom restriction") + + _, err = server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), types.NewMsgAddFinalizeActivateMarkerRequest( + "itslongenough", + sdk.NewInt(30), + user, + user, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(user, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + require.NoError(t, err, "should allow a marker with a sufficiently long denom") + + // Set to an empty string (returns to default expression) + app.MarkerKeeper.SetParams(ctx, types.Params{UnrestrictedDenomRegex: ""}) + _, err = server.AddFinalizeActivateMarker(sdk.WrapSDKContext(ctx), types.NewMsgAddFinalizeActivateMarkerRequest( + "short", + sdk.NewInt(30), + user, + user, + types.MarkerType_Coin, + true, + true, + []types.AccessGrant{*types.NewAccessGrant(user, []types.Access{types.Access_Mint, types.Access_Admin})}, + )) + // succeeds now as the default unrestricted denom expression allows any valid denom (minimum length is 2) + require.NoError(t, err, "should allow any valid denom with a min length of two") +} diff --git a/x/marker/keeper/marker.go b/x/marker/keeper/marker.go index e9d96ae637..0186307ebe 100644 --- a/x/marker/keeper/marker.go +++ b/x/marker/keeper/marker.go @@ -482,7 +482,7 @@ func (k Keeper) FinalizeMarker(ctx sdk.Context, caller sdk.Address, denom string return nil } -// ActivateMarker transistions a marker into the active status, enforcing permissions, supply constraints, and minting +// ActivateMarker transitions a marker into the active status, enforcing permissions, supply constraints, and minting // any supply as required. func (k Keeper) ActivateMarker(ctx sdk.Context, caller sdk.Address, denom string) error { defer telemetry.MeasureSince(time.Now(), types.ModuleName, "activate") @@ -567,7 +567,8 @@ func (k Keeper) CancelMarker(ctx sdk.Context, caller sdk.AccAddress, denom strin escrow := k.bankKeeper.GetBalance(ctx, m.GetAddress(), m.GetDenom()) inCirculation := totalSupply.Sub(escrow.Amount) if inCirculation.GT(sdk.ZeroInt()) { - return fmt.Errorf("cannot cancel marker with %d minted coin in circulation out of %d total."+ + // changing to %v + return fmt.Errorf("cannot cancel marker with %v minted coin in circulation out of %v total."+ " ensure marker account holds the entire supply of %s", inCirculation, totalSupply, denom) } case types.StatusProposed: @@ -621,7 +622,8 @@ func (k Keeper) DeleteMarker(ctx sdk.Context, caller sdk.AccAddress, denom strin escrow := k.bankKeeper.GetAllBalances(ctx, m.GetAddress()) inCirculation := totalSupply.Sub(escrow.AmountOf(denom)) if inCirculation.GT(sdk.ZeroInt()) { - return fmt.Errorf("cannot delete marker with %d minted coin in circulation out of %d total."+ + // use %v since %d doesn't apply to Int (wraps big.Int) + return fmt.Errorf("cannot delete marker with %v minted coin in circulation out of %v total."+ " ensure marker account holds the entire supply of %s", inCirculation, totalSupply, denom) } @@ -635,7 +637,7 @@ func (k Keeper) DeleteMarker(ctx sdk.Context, caller sdk.AccAddress, denom strin return fmt.Errorf("can not destroy marker due to balances in escrow: %s", escrow) } - // get the updated state of the marker afer supply burn... + // get the updated state of the marker after supply burn... m, err = k.GetMarkerByDenom(ctx, denom) if err != nil { return fmt.Errorf("marker not found for %s: %w", denom, err) @@ -818,6 +820,26 @@ func (k Keeper) SetMarkerDenomMetadata(ctx sdk.Context, metadata banktypes.Metad return nil } +// AddFinalizeAndActivateMarker adds marker, finalizes, and then activates it +func (k Keeper) AddFinalizeAndActivateMarker(ctx sdk.Context, marker types.MarkerAccountI) error { + err := k.AddMarkerAccount(ctx, marker) + if err != nil { + return err + } + + // Manager is the same as the manager in add marker request. + err = k.FinalizeMarker(ctx, marker.GetManager(), marker.GetDenom()) + if err != nil { + return err + } + + err = k.ActivateMarker(ctx, marker.GetManager(), marker.GetDenom()) + if err != nil { + return err + } + return nil +} + // accountControlsAllSupply return true if the caller account address possess 100% of the total supply of a marker. // This check is used to determine if an account should be allowed to perform defacto admin operations on a marker. func (k Keeper) accountControlsAllSupply(ctx sdk.Context, caller sdk.AccAddress, m types.MarkerAccountI) bool { diff --git a/x/marker/keeper/msg_server.go b/x/marker/keeper/msg_server.go index 5ea2d8c95c..eaa3a80a27 100644 --- a/x/marker/keeper/msg_server.go +++ b/x/marker/keeper/msg_server.go @@ -445,9 +445,9 @@ func (k msgServer) Transfer(goCtx context.Context, msg *types.MsgTransferRequest return &types.MsgTransferResponse{}, nil } -// Transfer handles a message to send coins from one account to another (used with restricted coins that are not +// IbcTransfer handles a message to ibc send coins from one account to another (used with restricted coins that are not // -// sent using the normal bank send process) +// sent using the normal ibc send process) func (k msgServer) IbcTransfer(goCtx context.Context, msg *types.MsgIbcTransferRequest) (*types.MsgIbcTransferResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -541,3 +541,60 @@ func (k msgServer) SetDenomMetadata( return &types.MsgSetDenomMetadataResponse{}, nil } + +// AddFinalizeActivateMarker Handle a message to add a new marker account, finalize it and activate it in one go. +func (k msgServer) AddFinalizeActivateMarker(goCtx context.Context, msg *types.MsgAddFinalizeActivateMarkerRequest) (*types.MsgAddFinalizeActivateMarkerResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + var err error + // Add marker requests must pass extra validation for denom (in addition to regular coin validation expression) + if err = k.ValidateUnrestictedDenom(ctx, msg.Amount.Denom); err != nil { + return nil, err + } + + // since this is a one shot process should have 1 access list member, to have any value for a marker. + if len(msg.AccessList) == 0 { + return nil, sdkerrors.ErrInvalidRequest.Wrap("since this will activate the marker, must have at least one access list defined") + } + + addr := types.MustGetMarkerAddress(msg.Amount.Denom) + var manager sdk.AccAddress + // if manager not supplied set manager from the --from-address + if msg.Manager != "" { + manager, err = sdk.AccAddressFromBech32(msg.Manager) + } else { + manager, err = sdk.AccAddressFromBech32(msg.FromAddress) + } + if err != nil { + return nil, err + } + account := authtypes.NewBaseAccount(addr, nil, 0, 0) + ma := types.NewMarkerAccount( + account, + sdk.NewCoin(msg.Amount.Denom, msg.Amount.Amount), + manager, + msg.AccessList, + types.StatusProposed, + msg.MarkerType) + ma.SupplyFixed = msg.SupplyFixed + + if k.GetEnableGovernance(ctx) { + ma.AllowGovernanceControl = true + } else { + ma.AllowGovernanceControl = msg.AllowGovernanceControl + } + + if err := k.Keeper.AddFinalizeAndActivateMarker(ctx, ma); err != nil { + ctx.Logger().Error("unable to add, finalize and activate marker", "err", err) + return nil, sdkerrors.ErrInvalidRequest.Wrap(err.Error()) + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + ) + + return &types.MsgAddFinalizeActivateMarkerResponse{}, nil +} diff --git a/x/marker/simulation/operations.go b/x/marker/simulation/operations.go index 4f28d8557f..c9b39d67cb 100644 --- a/x/marker/simulation/operations.go +++ b/x/marker/simulation/operations.go @@ -29,6 +29,8 @@ const ( OpWeightMsgChangeStatus = "op_weight_msg_change_status" //nolint:gosec // not credentials OpWeightMsgAddAccess = "op_weight_msg_add_access" + //nolint:gosec // not credentials + OpWeightMsgAddActivateFinalizeMarker = "op_weight_msg_add_finalize_activate_marker" ) /* @@ -50,9 +52,10 @@ func WeightedOperations( appParams simtypes.AppParams, cdc codec.JSONCodec, k keeper.Keeper, ak authkeeper.AccountKeeperI, bk bankkeeper.Keeper, ) simulation.WeightedOperations { var ( - weightMsgAddMarker int - weightMsgChangeStatus int - weightMsgAddAccess int + weightMsgAddMarker int + weightMsgChangeStatus int + weightMsgAddAccess int + weightMsgAddFinalizeActivateMarker int ) appParams.GetOrGenerate(cdc, OpWeightMsgAddMarker, &weightMsgAddMarker, nil, @@ -73,6 +76,12 @@ func WeightedOperations( }, ) + appParams.GetOrGenerate(cdc, OpWeightMsgAddActivateFinalizeMarker, &weightMsgAddFinalizeActivateMarker, nil, + func(_ *rand.Rand) { + weightMsgAddFinalizeActivateMarker = simappparams.DefaultWeightMsgAddFinalizeActivateMarker + }, + ) + return simulation.WeightedOperations{ simulation.NewWeightedOperation( weightMsgAddMarker, @@ -86,6 +95,10 @@ func WeightedOperations( weightMsgAddAccess, SimulateMsgAddAccess(k, ak, bk), ), + simulation.NewWeightedOperation( + weightMsgAddFinalizeActivateMarker, + SimulateMsgAddFinalizeActivateMarker(k, ak, bk), + ), } } @@ -176,6 +189,31 @@ func SimulateMsgAddAccess(k keeper.Keeper, ak authkeeper.AccountKeeperI, bk bank } } +// SimulateMsgAddFinalizeActivateMarker will bind a NAME under an existing name using a 40% probability of restricting it. +func SimulateMsgAddFinalizeActivateMarker(k keeper.Keeper, ak authkeeper.AccountKeeperI, bk bankkeeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + simAccount, _ := simtypes.RandomAcc(r, accs) + mgrAccount, _ := simtypes.RandomAcc(r, accs) + denom := randomUnrestrictedDenom(r, k.GetUnrestrictedDenomRegex(ctx)) + // random access grants + grants := randomAccessGrants(r, accs, 100) + msg := types.NewMsgAddFinalizeActivateMarkerRequest( + denom, + sdk.NewIntFromUint64(randomUint64(r, k.GetMaxTotalSupply(ctx))), + simAccount.Address, + mgrAccount.Address, + types.MarkerType(r.Intn(2)+1), // coin or restricted_coin + r.Intn(2) > 0, // fixed supply + r.Intn(2) > 0, // allow gov + grants, + ) + + return Dispatch(r, app, ctx, ak, bk, simAccount, chainID, msg, nil) + } +} + // Dispatch sends an operation to the chain using a given account/funds on account for fees. Failures on the server side // are handled as no-op msg operations with the error string as the status/response. func Dispatch( diff --git a/x/marker/simulation/operations_test.go b/x/marker/simulation/operations_test.go index c0b12a5f79..2c95ef2e28 100644 --- a/x/marker/simulation/operations_test.go +++ b/x/marker/simulation/operations_test.go @@ -70,6 +70,7 @@ func (suite *SimTestSuite) TestWeightedOperations() { {simappparams.DefaultWeightMsgChangeStatus, types.ModuleName, fmt.Sprintf("%T", &types.MsgActivateRequest{})}, // Possible names: types.TypeAddAccessRequest, fmt.Sprintf("%T", &types.MsgAddAccessRequest{}) {simappparams.DefaultWeightMsgAddAccess, types.ModuleName, types.TypeAddAccessRequest}, + {simappparams.DefaultWeightMsgAddFinalizeActivateMarker, types.ModuleName, types.TypeAddActivateFinalizeMarkerRequest}, } for i, w := range weightedOps { @@ -83,15 +84,14 @@ func (suite *SimTestSuite) TestWeightedOperations() { } } -// TestSimulateMsgBindName tests the normal scenario of a valid message of type TypeMsgBindName. -// Abonormal scenarios, where the message is created by an errors, are not tested here. +// TestSimulateMsgAddMarker tests the normal scenario of a valid message of type TypeAddMarkerRequest. +// Abnormal scenarios, where the message is created by an errors, are not tested here. func (suite *SimTestSuite) TestSimulateMsgAddMarker() { // setup 3 accounts s := rand.NewSource(1) r := rand.New(s) accounts := suite.getTestingAccounts(r, 3) - suite.app.NameKeeper.SetNameRecord(suite.ctx, "provenance", accounts[0].Address, false) // begin a new block suite.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) @@ -110,6 +110,32 @@ func (suite *SimTestSuite) TestSimulateMsgAddMarker() { suite.Require().Len(futureOperations, 0) } +// TestSimulateMsgAddActivateFinalizeMarker tests the normal scenario of a valid message of type TypeAddActivateFinalizeMarkerRequest. +// Abnormal scenarios, where the message is created by an errors, are not tested here. +func (suite *SimTestSuite) TestSimulateMsgAddActivateFinalizeMarker() { + + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) + + // execute operation + op := simulation.SimulateMsgAddFinalizeActivateMarker(suite.app.MarkerKeeper, suite.app.AccountKeeper, suite.app.BankKeeper) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgAddFinalizeActivateMarkerRequest + types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK, operationMsg.String()) + suite.Require().Equal(types.TypeAddActivateFinalizeMarkerRequest, msg.Type()) + suite.Require().Equal(types.ModuleName, msg.Route()) + suite.Require().Len(futureOperations, 0) +} + func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { accounts := simtypes.RandomAccounts(r, n) diff --git a/x/marker/spec/03_messages.md b/x/marker/spec/03_messages.md index 2263b4b312..d1c717812b 100644 --- a/x/marker/spec/03_messages.md +++ b/x/marker/spec/03_messages.md @@ -278,3 +278,18 @@ This service message is expected to fail if: - Any DenomUnit entries are removed. - DenomUnit Denom fields are modified. - Any aliases are removed from a DenomUnit. + +## Msg/AddFinalizeActivateMarkerRequest + +AddFinalizeActivate requested is used for adding, finalizing, and activating a marker in a single request. + +This service message is expected to fail if: + +- The given denom value is invalid or does not match an existing marker on the system +- The marker is pending: + - And the request is not signed with an administrator address that matches the manager address or: + - The given administrator address does not currently have the "admin" access granted on the marker +- The accesslist: + - Contains more than one entry for a given address + - Contains a grant with an invalid address + - Contains a grant with an invalid access enum value (Unspecified/0) \ No newline at end of file diff --git a/x/marker/types/accessgrant.pb.go b/x/marker/types/accessgrant.pb.go index 9e0781b78c..b604294dac 100644 --- a/x/marker/types/accessgrant.pb.go +++ b/x/marker/types/accessgrant.pb.go @@ -79,7 +79,7 @@ func (Access) EnumDescriptor() ([]byte, []int) { return fileDescriptor_7242c30a84644575, []int{0} } -// AccessGrant associates a colelction of permisssions with an address for delegated marker account control. +// AccessGrant associates a collection of permissions with an address for delegated marker account control. type AccessGrant struct { Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Permissions AccessList `protobuf:"varint,2,rep,packed,name=permissions,proto3,enum=provenance.marker.v1.Access,castrepeated=AccessList" json:"permissions,omitempty"` diff --git a/x/marker/types/msg.go b/x/marker/types/msg.go index 88604502fd..a43dd4ef41 100644 --- a/x/marker/types/msg.go +++ b/x/marker/types/msg.go @@ -18,20 +18,21 @@ import ( ) const ( - TypeAddMarkerRequest = "addmarker" - TypeAddAccessRequest = "addaccess" - TypeDeleteAccessRequest = "deleteaccess" - TypeFinalizeRequest = "finalize" - TypeActivateRequest = "activate" - TypeCancelRequest = "cancel" - TypeDeleteRequest = "delete" - TypeMintRequest = "mint" - TypeBurnRequest = "burn" - TypeWithdrawRequest = "withdraw" - TypeTransferRequest = "transfer" - TypeIbcTransferRequest = "ibctransfer" - TypeSetMetadataRequest = "setmetadata" - TypeGrantAllowance = "grantallowance" + TypeAddMarkerRequest = "addmarker" + TypeAddAccessRequest = "addaccess" + TypeDeleteAccessRequest = "deleteaccess" + TypeFinalizeRequest = "finalize" + TypeActivateRequest = "activate" + TypeCancelRequest = "cancel" + TypeDeleteRequest = "delete" + TypeMintRequest = "mint" + TypeBurnRequest = "burn" + TypeWithdrawRequest = "withdraw" + TypeTransferRequest = "transfer" + TypeIbcTransferRequest = "ibctransfer" + TypeSetMetadataRequest = "setmetadata" + TypeGrantAllowance = "grantallowance" + TypeAddActivateFinalizeMarkerRequest = "addactivatefinalizemarker" ) // Compile time interface check. @@ -49,6 +50,7 @@ var ( _ sdk.Msg = &MsgTransferRequest{} _ sdk.Msg = &MsgIbcTransferRequest{} _ sdk.Msg = &MsgGrantAllowanceRequest{} + _ sdk.Msg = &MsgAddFinalizeActivateMarkerRequest{} ) // Type returns the message action. @@ -93,6 +95,12 @@ func (msg MsgSetDenomMetadataRequest) Type() string { return TypeSetMetadataRequ // Type returns the message action. func (msg MsgGrantAllowanceRequest) Type() string { return TypeGrantAllowance } +// Type returns the message action. +// These legacyMsg support should probably be removed but adding new message to this for consistency for now. +func (msg MsgAddFinalizeActivateMarkerRequest) Type() string { + return TypeAddActivateFinalizeMarkerRequest +} + // NewMsgAddMarkerRequest creates a new marker in a proposed state with a given total supply a denomination func NewMsgAddMarkerRequest( denom string, totalSupply sdkmath.Int, fromAddress sdk.AccAddress, manager sdk.AccAddress, markerType MarkerType, supplyFixed bool, allowGovernanceControl bool, //nolint:interfacer @@ -642,3 +650,53 @@ func (msg MsgGrantAllowanceRequest) GetSignBytes() []byte { func (msg MsgGrantAllowanceRequest) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{sdk.MustAccAddressFromBech32(msg.Administrator)} } + +func NewMsgAddFinalizeActivateMarkerRequest(denom string, totalSupply sdkmath.Int, fromAddress sdk.AccAddress, manager sdk.AccAddress, markerType MarkerType, supplyFixed bool, allowGovernanceControl bool, accessGrants []AccessGrant) *MsgAddFinalizeActivateMarkerRequest { + return &MsgAddFinalizeActivateMarkerRequest{ + Amount: sdk.NewCoin(denom, totalSupply), + Manager: manager.String(), + FromAddress: fromAddress.String(), + MarkerType: markerType, + SupplyFixed: supplyFixed, + AllowGovernanceControl: allowGovernanceControl, + AccessList: accessGrants, + } +} + +// Route returns the name of the module. +func (msg MsgAddFinalizeActivateMarkerRequest) Route() string { return ModuleName } + +// ValidateBasic runs stateless validation checks on the message. +func (msg MsgAddFinalizeActivateMarkerRequest) ValidateBasic() error { + markerCoin := sdk.Coin{ + Denom: msg.Amount.Denom, + Amount: msg.Amount.Amount, + } + // IsValid validates denom and amount is not negative. + if !markerCoin.IsValid() { + return fmt.Errorf("invalid marker denom/total supply: %w", sdkerrors.ErrInvalidCoins) + } + + _, err := sdk.AccAddressFromBech32(msg.Manager) + if err != nil { + return err + } + + // since this is a one shot process should have 1 access list member, to have any value for a marker + if msg.AccessList == nil || len(msg.AccessList) == 0 { + return fmt.Errorf("since this will activate the marker, must have access list defined") + } + return nil +} + +// GetSignBytes encodes the message for signing. +func (msg MsgAddFinalizeActivateMarkerRequest) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners indicates that the message must have been signed by the address provided. +func (msg MsgAddFinalizeActivateMarkerRequest) GetSigners() []sdk.AccAddress { + addr := sdk.MustAccAddressFromBech32(msg.FromAddress) + return []sdk.AccAddress{addr} +} diff --git a/x/marker/types/msg_test.go b/x/marker/types/msg_test.go index 19ff1a8f7d..d9ead06717 100644 --- a/x/marker/types/msg_test.go +++ b/x/marker/types/msg_test.go @@ -4,6 +4,8 @@ import ( "testing" "time" + "cosmossdk.io/math" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/codec" @@ -92,7 +94,7 @@ func TestMsgGrantAllowance(t *testing.T) { } } -func TestMsgAssessCustomMsgFeeValidateBasic(t *testing.T) { +func TestMsgIbcTransferRequestValidateBasic(t *testing.T) { validAddress := "cosmos1sh49f6ze3vn7cdl2amh2gnc70z5mten3y08xck" cases := []struct { @@ -158,3 +160,85 @@ func TestMsgAssessCustomMsgFeeValidateBasic(t *testing.T) { }) } } + +func TestMsgAddFinalizeActivateMarkerRequestValidateBasic(t *testing.T) { + validAddress := sdk.MustAccAddressFromBech32("cosmos1sh49f6ze3vn7cdl2amh2gnc70z5mten3y08xck") + + cases := []struct { + name string + msg MsgAddFinalizeActivateMarkerRequest + errorMsg string + }{ + { + "should fail on invalid marker", + MsgAddFinalizeActivateMarkerRequest{ + Amount: sdk.Coin{ + Amount: math.NewInt(100), + Denom: "", + }, + Manager: "cosmos1sh49f6ze3vn7cdl2amh2gnc70z5mten3y08xck", + FromAddress: "cosmos1sh49f6ze3vn7cdl2amh2gnc70z5mten3y08xck", + MarkerType: MarkerType_Coin, + SupplyFixed: true, + AllowGovernanceControl: true, + AccessList: []AccessGrant{*NewAccessGrant(validAddress, []Access{Access_Mint, Access_Admin})}, + }, + "invalid marker denom/total supply: invalid coins", + }, + { + "should fail on invalid manager address", + MsgAddFinalizeActivateMarkerRequest{ + Amount: sdk.NewInt64Coin("hotdog", 100), + Manager: "", + FromAddress: "", + MarkerType: MarkerType_Coin, + SupplyFixed: true, + AllowGovernanceControl: true, + AccessList: []AccessGrant{*NewAccessGrant(validAddress, []Access{Access_Mint, Access_Admin})}, + }, + "empty address string is not allowed", + }, + { + "should fail on empty access list", + *NewMsgAddFinalizeActivateMarkerRequest( + "hotdog", + sdk.NewInt(100), + validAddress, + validAddress, + MarkerType_Coin, + true, + true, + []AccessGrant{}, + ), + "since this will activate the marker, must have access list defined", + }, + { + "should succeed", + *NewMsgAddFinalizeActivateMarkerRequest( + "hotdog", + sdk.NewInt(100), + validAddress, + validAddress, + MarkerType_Coin, + true, + true, + []AccessGrant{*NewAccessGrant(validAddress, []Access{Access_Mint, Access_Admin})}, + ), + "", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if len(tc.errorMsg) > 0 { + assert.Error(t, err) + assert.Equal(t, tc.errorMsg, err.Error()) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/x/marker/types/tx.pb.go b/x/marker/types/tx.pb.go index 248065971b..9a11db25ba 100644 --- a/x/marker/types/tx.pb.go +++ b/x/marker/types/tx.pb.go @@ -1369,6 +1369,129 @@ func (m *MsgSetDenomMetadataResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgSetDenomMetadataResponse proto.InternalMessageInfo +// MsgAddFinalizeActivateMarkerRequest defines the Msg/AddFinalizeActivateMarker request type +type MsgAddFinalizeActivateMarkerRequest struct { + Amount github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,1,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"amount"` + Manager string `protobuf:"bytes,3,opt,name=manager,proto3" json:"manager,omitempty"` + FromAddress string `protobuf:"bytes,4,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` + MarkerType MarkerType `protobuf:"varint,5,opt,name=marker_type,json=markerType,proto3,enum=provenance.marker.v1.MarkerType" json:"marker_type,omitempty"` + AccessList []AccessGrant `protobuf:"bytes,6,rep,name=access_list,json=accessList,proto3" json:"access_list"` + SupplyFixed bool `protobuf:"varint,7,opt,name=supply_fixed,json=supplyFixed,proto3" json:"supply_fixed,omitempty"` + AllowGovernanceControl bool `protobuf:"varint,8,opt,name=allow_governance_control,json=allowGovernanceControl,proto3" json:"allow_governance_control,omitempty"` +} + +func (m *MsgAddFinalizeActivateMarkerRequest) Reset() { *m = MsgAddFinalizeActivateMarkerRequest{} } +func (m *MsgAddFinalizeActivateMarkerRequest) String() string { return proto.CompactTextString(m) } +func (*MsgAddFinalizeActivateMarkerRequest) ProtoMessage() {} +func (*MsgAddFinalizeActivateMarkerRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_bcb203fb73175ed3, []int{28} +} +func (m *MsgAddFinalizeActivateMarkerRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddFinalizeActivateMarkerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddFinalizeActivateMarkerRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAddFinalizeActivateMarkerRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddFinalizeActivateMarkerRequest.Merge(m, src) +} +func (m *MsgAddFinalizeActivateMarkerRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgAddFinalizeActivateMarkerRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddFinalizeActivateMarkerRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddFinalizeActivateMarkerRequest proto.InternalMessageInfo + +func (m *MsgAddFinalizeActivateMarkerRequest) GetManager() string { + if m != nil { + return m.Manager + } + return "" +} + +func (m *MsgAddFinalizeActivateMarkerRequest) GetFromAddress() string { + if m != nil { + return m.FromAddress + } + return "" +} + +func (m *MsgAddFinalizeActivateMarkerRequest) GetMarkerType() MarkerType { + if m != nil { + return m.MarkerType + } + return MarkerType_Unknown +} + +func (m *MsgAddFinalizeActivateMarkerRequest) GetAccessList() []AccessGrant { + if m != nil { + return m.AccessList + } + return nil +} + +func (m *MsgAddFinalizeActivateMarkerRequest) GetSupplyFixed() bool { + if m != nil { + return m.SupplyFixed + } + return false +} + +func (m *MsgAddFinalizeActivateMarkerRequest) GetAllowGovernanceControl() bool { + if m != nil { + return m.AllowGovernanceControl + } + return false +} + +// MsgAddFinalizeActivateMarkerResponse defines the Msg/AddFinalizeActivateMarker response type +type MsgAddFinalizeActivateMarkerResponse struct { +} + +func (m *MsgAddFinalizeActivateMarkerResponse) Reset() { *m = MsgAddFinalizeActivateMarkerResponse{} } +func (m *MsgAddFinalizeActivateMarkerResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAddFinalizeActivateMarkerResponse) ProtoMessage() {} +func (*MsgAddFinalizeActivateMarkerResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_bcb203fb73175ed3, []int{29} +} +func (m *MsgAddFinalizeActivateMarkerResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAddFinalizeActivateMarkerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAddFinalizeActivateMarkerResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgAddFinalizeActivateMarkerResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddFinalizeActivateMarkerResponse.Merge(m, src) +} +func (m *MsgAddFinalizeActivateMarkerResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgAddFinalizeActivateMarkerResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddFinalizeActivateMarkerResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAddFinalizeActivateMarkerResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgGrantAllowanceRequest)(nil), "provenance.marker.v1.MsgGrantAllowanceRequest") proto.RegisterType((*MsgGrantAllowanceResponse)(nil), "provenance.marker.v1.MsgGrantAllowanceResponse") @@ -1398,91 +1521,97 @@ func init() { proto.RegisterType((*MsgIbcTransferResponse)(nil), "provenance.marker.v1.MsgIbcTransferResponse") proto.RegisterType((*MsgSetDenomMetadataRequest)(nil), "provenance.marker.v1.MsgSetDenomMetadataRequest") proto.RegisterType((*MsgSetDenomMetadataResponse)(nil), "provenance.marker.v1.MsgSetDenomMetadataResponse") + proto.RegisterType((*MsgAddFinalizeActivateMarkerRequest)(nil), "provenance.marker.v1.MsgAddFinalizeActivateMarkerRequest") + proto.RegisterType((*MsgAddFinalizeActivateMarkerResponse)(nil), "provenance.marker.v1.MsgAddFinalizeActivateMarkerResponse") } func init() { proto.RegisterFile("provenance/marker/v1/tx.proto", fileDescriptor_bcb203fb73175ed3) } var fileDescriptor_bcb203fb73175ed3 = []byte{ - // 1252 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xdd, 0x6e, 0x1b, 0xc5, - 0x17, 0xcf, 0xfe, 0x9d, 0xba, 0xf1, 0xb8, 0x4d, 0x9b, 0x69, 0x9a, 0x6e, 0x5c, 0xc5, 0x71, 0xac, - 0xb6, 0x71, 0xff, 0x34, 0xbb, 0x8d, 0x11, 0x12, 0xea, 0x0d, 0xb2, 0x53, 0x52, 0x2a, 0x58, 0x54, - 0x39, 0x95, 0x10, 0xdc, 0x58, 0xe3, 0xdd, 0xc9, 0x66, 0x15, 0xef, 0x8e, 0xbb, 0x33, 0x76, 0x12, - 0x24, 0xde, 0x01, 0xf5, 0x92, 0x47, 0xe0, 0x1a, 0x09, 0xf1, 0x06, 0x15, 0x57, 0x15, 0xe2, 0x02, - 0x21, 0x54, 0xaa, 0xe4, 0x15, 0x78, 0x00, 0xb4, 0x33, 0xb3, 0x9f, 0xb1, 0x37, 0xae, 0x64, 0x01, - 0x57, 0xf6, 0xcc, 0xf9, 0xfc, 0x9d, 0x73, 0xf6, 0x9c, 0xb3, 0x0b, 0xd6, 0x06, 0x3e, 0x19, 0x61, - 0x0f, 0x79, 0x26, 0xd6, 0x5d, 0xe4, 0x1f, 0x62, 0x5f, 0x1f, 0x6d, 0xeb, 0xec, 0x58, 0x1b, 0xf8, - 0x84, 0x11, 0xb8, 0x1c, 0x93, 0x35, 0x41, 0xd6, 0x46, 0xdb, 0x95, 0x55, 0x9b, 0x10, 0xbb, 0x8f, - 0x75, 0xce, 0xd3, 0x1b, 0xee, 0xeb, 0xc8, 0x3b, 0x11, 0x02, 0x95, 0x55, 0x93, 0x50, 0x97, 0xd0, - 0x2e, 0x3f, 0xe9, 0xe2, 0x20, 0x49, 0xcb, 0x36, 0xb1, 0x89, 0xb8, 0x0f, 0xfe, 0xc9, 0xdb, 0xaa, - 0xe0, 0xd1, 0x7b, 0x88, 0x62, 0x7d, 0xb4, 0xdd, 0xc3, 0x0c, 0x6d, 0xeb, 0x26, 0x71, 0xbc, 0x73, - 0x74, 0xef, 0x30, 0xa2, 0x07, 0x07, 0x49, 0xbf, 0xeb, 0xf4, 0x4c, 0x1d, 0x0d, 0x06, 0x7d, 0xc7, - 0x44, 0xcc, 0x21, 0x1e, 0xd5, 0x99, 0x8f, 0x3c, 0xba, 0x9f, 0x06, 0x52, 0xd9, 0x18, 0x8b, 0x53, - 0x42, 0x12, 0x2c, 0xf7, 0xc6, 0xb2, 0x20, 0xd3, 0xc4, 0x94, 0xda, 0x3e, 0xf2, 0x98, 0xe0, 0xab, - 0xff, 0xa8, 0x00, 0xd5, 0xa0, 0xf6, 0x93, 0xe0, 0xaa, 0xd5, 0xef, 0x93, 0xa3, 0x40, 0xa2, 0x83, - 0x5f, 0x0c, 0x31, 0x65, 0x70, 0x19, 0x5c, 0xb2, 0xb0, 0x47, 0x5c, 0x55, 0xa9, 0x29, 0x8d, 0x52, - 0x47, 0x1c, 0xe0, 0x1d, 0x70, 0x15, 0x59, 0xae, 0xe3, 0x39, 0x94, 0xf9, 0x88, 0x11, 0x5f, 0xfd, - 0x1f, 0xa7, 0xa6, 0x2f, 0xa1, 0x0a, 0x2e, 0x73, 0x3b, 0x18, 0xab, 0x05, 0x4e, 0x0f, 0x8f, 0xf0, - 0x63, 0x50, 0x42, 0xa1, 0x25, 0x75, 0xbe, 0xa6, 0x34, 0xca, 0xcd, 0x65, 0x4d, 0x24, 0x41, 0x0b, - 0x93, 0xa0, 0xb5, 0xbc, 0x93, 0xf6, 0xd2, 0xcf, 0x3f, 0x6c, 0x5d, 0xdd, 0xc5, 0x38, 0xf2, 0xeb, - 0x69, 0x27, 0x96, 0xac, 0xdf, 0x06, 0xab, 0x63, 0x1c, 0xa7, 0x03, 0xe2, 0x51, 0x5c, 0xff, 0xa3, - 0x00, 0x6e, 0x18, 0xd4, 0x6e, 0x59, 0x96, 0xc1, 0xc1, 0x87, 0x88, 0x7a, 0xa0, 0x88, 0x5c, 0x32, - 0xf4, 0x18, 0x87, 0x54, 0x6e, 0xae, 0x6a, 0x32, 0xab, 0x41, 0xc6, 0x34, 0x99, 0x11, 0x6d, 0x87, - 0x38, 0x5e, 0x5b, 0x7f, 0xf5, 0x66, 0x7d, 0xee, 0xf7, 0x37, 0xeb, 0x9b, 0xb6, 0xc3, 0x0e, 0x86, - 0x3d, 0xcd, 0x24, 0xae, 0x2c, 0x01, 0xf9, 0xb3, 0x45, 0xad, 0x43, 0x9d, 0x9d, 0x0c, 0x30, 0xe5, - 0x02, 0x1d, 0xa9, 0x39, 0x40, 0xee, 0x22, 0x0f, 0xd9, 0xd8, 0x0f, 0x91, 0xcb, 0x23, 0xdc, 0x00, - 0x57, 0xf6, 0x7d, 0xe2, 0x76, 0x91, 0x65, 0xf9, 0x98, 0x52, 0x0e, 0xbe, 0xd4, 0x29, 0x07, 0x77, - 0x2d, 0x71, 0x05, 0x1f, 0x81, 0x22, 0x65, 0x88, 0x0d, 0xa9, 0x7a, 0xa9, 0xa6, 0x34, 0x16, 0x9b, - 0x75, 0x6d, 0x5c, 0xd1, 0x6a, 0x02, 0xd5, 0x1e, 0xe7, 0xec, 0x48, 0x09, 0xd8, 0x02, 0x65, 0xc1, - 0xd1, 0x0d, 0xbc, 0x52, 0x8b, 0x5c, 0x41, 0x2d, 0x4f, 0xc1, 0xf3, 0x93, 0x01, 0xee, 0x00, 0x37, - 0xfa, 0x0f, 0x3f, 0x01, 0x65, 0x51, 0x23, 0xdd, 0xbe, 0x43, 0x99, 0x7a, 0xb9, 0x56, 0x68, 0x94, - 0x9b, 0x1b, 0xe3, 0x55, 0xb4, 0x38, 0x23, 0x4f, 0x40, 0x7b, 0x3e, 0x08, 0x56, 0x07, 0x08, 0xd9, - 0xcf, 0x1c, 0xca, 0x02, 0xac, 0x74, 0x38, 0x18, 0xf4, 0x4f, 0xba, 0xfb, 0xce, 0x31, 0xb6, 0xd4, - 0x85, 0x9a, 0xd2, 0x58, 0xe8, 0x94, 0xc5, 0xdd, 0x6e, 0x70, 0x05, 0x3f, 0x04, 0x2a, 0x4f, 0x67, - 0xd7, 0x26, 0x23, 0xec, 0x73, 0xf5, 0x5d, 0x93, 0x78, 0xcc, 0x27, 0x7d, 0xb5, 0xc4, 0xd9, 0x57, - 0x38, 0xfd, 0x49, 0x44, 0xde, 0x11, 0xd4, 0xfa, 0x0a, 0x58, 0x4e, 0x67, 0x57, 0xa6, 0xfd, 0xa5, - 0x12, 0xa6, 0x5d, 0x38, 0x37, 0x8b, 0x42, 0xfe, 0x08, 0x14, 0x05, 0x2c, 0xb5, 0xf0, 0x6e, 0xd1, - 0x90, 0x62, 0xb1, 0xb3, 0xa1, 0x4f, 0xd2, 0xd9, 0x6f, 0xc0, 0x8a, 0x41, 0xed, 0xc7, 0xb8, 0x8f, - 0x19, 0x9e, 0x9d, 0xbb, 0x9b, 0xe0, 0x9a, 0x8f, 0x5d, 0x32, 0xc2, 0x56, 0x54, 0x66, 0xa2, 0x0a, - 0x17, 0xe5, 0xb5, 0xac, 0xb4, 0xfa, 0x2a, 0xb8, 0x75, 0xce, 0xbc, 0xf4, 0xec, 0x19, 0x80, 0x06, - 0xb5, 0x77, 0x1d, 0x0f, 0xf5, 0x9d, 0xaf, 0x67, 0xd1, 0x0d, 0xea, 0x37, 0x79, 0x5e, 0x62, 0x8d, - 0x29, 0x43, 0x2d, 0x93, 0x39, 0x23, 0xc4, 0x66, 0x68, 0x28, 0xd6, 0x28, 0x0d, 0x7d, 0x0e, 0xae, - 0x1b, 0xd4, 0xde, 0x09, 0x72, 0xd6, 0x9f, 0x85, 0x99, 0x1b, 0x60, 0x29, 0xa1, 0x2f, 0x65, 0x44, - 0x44, 0x74, 0x76, 0x46, 0x42, 0x7d, 0xd2, 0xc8, 0x77, 0x0a, 0x58, 0x34, 0xa8, 0x6d, 0x38, 0x1e, - 0xfb, 0x27, 0x9b, 0xda, 0x74, 0x1e, 0x2f, 0x81, 0x6b, 0x91, 0x6f, 0x69, 0x7f, 0xdb, 0x43, 0xdf, - 0xfb, 0xaf, 0xfa, 0x2b, 0x7c, 0x93, 0xfe, 0xfe, 0xaa, 0xf0, 0x9a, 0xfc, 0xc2, 0x61, 0x07, 0x96, - 0x8f, 0x8e, 0x66, 0xf1, 0x48, 0xae, 0x01, 0xc0, 0x48, 0xe6, 0x69, 0x2c, 0x31, 0x12, 0xb6, 0x7c, - 0x33, 0x0a, 0xc7, 0x3c, 0x6f, 0x30, 0x39, 0xe1, 0x78, 0x18, 0x84, 0xe3, 0xfb, 0x3f, 0xd7, 0x1b, - 0x53, 0x86, 0x83, 0x86, 0xf1, 0x90, 0xcf, 0x45, 0x8c, 0x4a, 0xa2, 0x7d, 0x2b, 0xd0, 0x3e, 0x97, - 0x5b, 0xc6, 0xbf, 0x9a, 0xa1, 0xc2, 0xb8, 0xd8, 0x4d, 0x31, 0x32, 0xd3, 0xe1, 0xbd, 0x94, 0x09, - 0xaf, 0x44, 0x1e, 0x23, 0x94, 0xc8, 0x7f, 0x51, 0xc0, 0x4d, 0x83, 0xda, 0x4f, 0x7b, 0x66, 0x16, - 0xfc, 0x4b, 0x05, 0x2c, 0x84, 0x6b, 0x97, 0xc4, 0x7f, 0x5f, 0x73, 0x7a, 0xa6, 0x96, 0x5c, 0xcc, - 0xb4, 0x90, 0x83, 0x0f, 0xd3, 0x58, 0x7f, 0xfb, 0x53, 0x19, 0x8f, 0x9d, 0xf3, 0xf1, 0x70, 0x7a, - 0xe6, 0x96, 0x4d, 0xf4, 0xd1, 0x07, 0xba, 0x4b, 0xac, 0x61, 0x1f, 0xd3, 0x60, 0xd5, 0x4b, 0xac, - 0x78, 0x22, 0x48, 0x49, 0x67, 0x23, 0x3f, 0xa6, 0xac, 0x67, 0x95, 0x8f, 0x94, 0x14, 0x26, 0x09, - 0xf7, 0x27, 0x05, 0x54, 0x0c, 0x6a, 0xef, 0x61, 0xf6, 0x38, 0xa8, 0x5c, 0x03, 0x33, 0x64, 0x21, - 0x86, 0x42, 0xcc, 0x43, 0xb0, 0xe0, 0xca, 0x2b, 0x09, 0x79, 0x2d, 0x4e, 0xb9, 0x77, 0x18, 0xa5, - 0x3c, 0x94, 0x6b, 0x3f, 0x92, 0x30, 0x9b, 0xb9, 0x69, 0x3f, 0x16, 0x9b, 0xae, 0x04, 0x16, 0xda, - 0x8c, 0x4c, 0x4d, 0x89, 0x6a, 0x0d, 0xdc, 0x1e, 0xeb, 0xba, 0x80, 0xd6, 0xfc, 0x0b, 0x80, 0x82, - 0x41, 0x6d, 0xd8, 0x05, 0x0b, 0xe1, 0x80, 0x81, 0x8d, 0x09, 0x5b, 0xcf, 0xb9, 0xa9, 0x56, 0xb9, - 0x3f, 0x05, 0xa7, 0x30, 0x14, 0x18, 0x08, 0x07, 0x4b, 0x8e, 0x81, 0xcc, 0x34, 0xcb, 0x31, 0x90, - 0x9d, 0x52, 0xf0, 0x4b, 0x50, 0x14, 0x23, 0x05, 0xde, 0x9b, 0x28, 0x94, 0x9a, 0x61, 0x95, 0xcd, - 0x0b, 0xf9, 0x62, 0xd5, 0x62, 0x90, 0xe4, 0xa8, 0x4e, 0x4d, 0xae, 0x1c, 0xd5, 0xe9, 0x89, 0x04, - 0xf7, 0xc0, 0x7c, 0xd0, 0xf1, 0xe1, 0x9d, 0x89, 0x02, 0x89, 0x61, 0x55, 0xb9, 0x7b, 0x01, 0x57, - 0xac, 0x34, 0x68, 0xcb, 0x39, 0x4a, 0x13, 0x13, 0x25, 0x47, 0x69, 0xb2, 0xb7, 0xc3, 0x1e, 0x28, - 0x45, 0x6b, 0x18, 0xcc, 0xc9, 0x4b, 0x66, 0x7d, 0xac, 0xfc, 0x7f, 0x1a, 0x56, 0x69, 0xe3, 0x10, - 0x5c, 0x49, 0xee, 0x54, 0xf0, 0xc1, 0x05, 0x61, 0x4c, 0x5b, 0xda, 0x9a, 0x92, 0x3b, 0xae, 0xc8, - 0xb0, 0xa5, 0xe7, 0x54, 0x64, 0x66, 0x96, 0xe5, 0x54, 0x64, 0x76, 0x3e, 0xc8, 0x88, 0x89, 0x2d, - 0x3b, 0x3f, 0x62, 0xa9, 0xf7, 0xac, 0xfc, 0x88, 0xa5, 0x97, 0xf6, 0x00, 0x44, 0xd8, 0xae, 0x72, - 0x40, 0x64, 0xba, 0x74, 0x0e, 0x88, 0x6c, 0xef, 0x83, 0x07, 0xa0, 0x9c, 0x68, 0x89, 0xf0, 0xbd, - 0x89, 0x92, 0xe7, 0x87, 0x41, 0xe5, 0xc1, 0x74, 0xcc, 0xd2, 0xd2, 0x11, 0xb8, 0x9e, 0x6d, 0x53, - 0xf0, 0xe1, 0x44, 0x0d, 0x13, 0x9a, 0x71, 0x65, 0xfb, 0x1d, 0x24, 0xa4, 0xe1, 0x17, 0x60, 0x31, - 0xfd, 0x26, 0x0c, 0xb5, 0x89, 0x4a, 0xc6, 0xbe, 0xeb, 0x57, 0xf4, 0xa9, 0xf9, 0x85, 0xc9, 0xb6, - 0xfd, 0xea, 0xb4, 0xaa, 0xbc, 0x3e, 0xad, 0x2a, 0x6f, 0x4f, 0xab, 0xca, 0xb7, 0x67, 0xd5, 0xb9, - 0xd7, 0x67, 0xd5, 0xb9, 0xdf, 0xce, 0xaa, 0x73, 0xe0, 0x96, 0x43, 0xc6, 0x2a, 0x7b, 0xa6, 0x7c, - 0x95, 0x1c, 0x17, 0x31, 0xcb, 0x96, 0x43, 0x12, 0x27, 0xfd, 0x38, 0xfc, 0x62, 0xc1, 0xe7, 0x46, - 0xaf, 0xc8, 0x3f, 0x0a, 0xbc, 0xff, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x85, 0xd4, 0xbc, 0x93, - 0xde, 0x11, 0x00, 0x00, + // 1315 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0x4d, 0x6f, 0x1b, 0xc5, + 0x1b, 0xcf, 0xfe, 0x9d, 0xb8, 0xf6, 0xb8, 0x4d, 0xdb, 0x69, 0xda, 0xae, 0xb7, 0x8a, 0xeb, 0xfa, + 0xdf, 0x17, 0x17, 0x9a, 0xdd, 0xc6, 0x08, 0x09, 0x7a, 0x41, 0x76, 0x4a, 0x4b, 0x05, 0x8b, 0x2a, + 0xa7, 0x12, 0x82, 0x8b, 0x35, 0xde, 0x9d, 0x6c, 0x56, 0xf1, 0xee, 0xb8, 0x3b, 0x63, 0x27, 0x41, + 0xe2, 0x03, 0x70, 0x43, 0x39, 0xf2, 0x11, 0x38, 0x71, 0x40, 0x42, 0x7c, 0x83, 0x8a, 0x53, 0x85, + 0x38, 0x20, 0x84, 0x4a, 0x95, 0x7c, 0x11, 0xb4, 0x33, 0xb3, 0x5e, 0xef, 0xc6, 0xde, 0x38, 0x60, + 0xf1, 0x72, 0x8a, 0x67, 0xe6, 0x79, 0xfb, 0x3d, 0xcf, 0x33, 0xf3, 0xfc, 0xb2, 0x60, 0xb5, 0x1f, + 0x90, 0x21, 0xf6, 0x91, 0x6f, 0x61, 0xc3, 0x43, 0xc1, 0x0e, 0x0e, 0x8c, 0xe1, 0xba, 0xc1, 0xf6, + 0xf4, 0x7e, 0x40, 0x18, 0x81, 0x2b, 0xf1, 0xb1, 0x2e, 0x8e, 0xf5, 0xe1, 0xba, 0x56, 0x76, 0x08, + 0x71, 0x7a, 0xd8, 0xe0, 0x32, 0xdd, 0xc1, 0x96, 0x81, 0xfc, 0x7d, 0xa1, 0xa0, 0x95, 0x2d, 0x42, + 0x3d, 0x42, 0x3b, 0x7c, 0x65, 0x88, 0x85, 0x3c, 0x5a, 0x71, 0x88, 0x43, 0xc4, 0x7e, 0xf8, 0x4b, + 0xee, 0x56, 0x84, 0x8c, 0xd1, 0x45, 0x14, 0x1b, 0xc3, 0xf5, 0x2e, 0x66, 0x68, 0xdd, 0xb0, 0x88, + 0xeb, 0x1f, 0x3b, 0xf7, 0x77, 0x46, 0xe7, 0xe1, 0x42, 0x9e, 0xdf, 0x72, 0xbb, 0x96, 0x81, 0xfa, + 0xfd, 0x9e, 0x6b, 0x21, 0xe6, 0x12, 0x9f, 0x1a, 0x2c, 0x40, 0x3e, 0xdd, 0x4a, 0x02, 0xd1, 0x6e, + 0x4c, 0xc4, 0x29, 0x21, 0x09, 0x91, 0xdb, 0x13, 0x45, 0x90, 0x65, 0x61, 0x4a, 0x9d, 0x00, 0xf9, + 0x4c, 0xc8, 0xd5, 0xbe, 0x57, 0x80, 0x6a, 0x52, 0xe7, 0x71, 0xb8, 0xd5, 0xec, 0xf5, 0xc8, 0x6e, + 0xa8, 0xd1, 0xc6, 0xcf, 0x07, 0x98, 0x32, 0xb8, 0x02, 0x96, 0x6c, 0xec, 0x13, 0x4f, 0x55, 0xaa, + 0x4a, 0xbd, 0xd8, 0x16, 0x0b, 0x78, 0x13, 0x9c, 0x43, 0xb6, 0xe7, 0xfa, 0x2e, 0x65, 0x01, 0x62, + 0x24, 0x50, 0xff, 0xc7, 0x4f, 0x93, 0x9b, 0x50, 0x05, 0x67, 0xb8, 0x1f, 0x8c, 0xd5, 0x1c, 0x3f, + 0x8f, 0x96, 0xf0, 0x7d, 0x50, 0x44, 0x91, 0x27, 0x75, 0xb1, 0xaa, 0xd4, 0x4b, 0x8d, 0x15, 0x5d, + 0x14, 0x41, 0x8f, 0x8a, 0xa0, 0x37, 0xfd, 0xfd, 0xd6, 0xc5, 0x1f, 0xbf, 0x5b, 0x3b, 0xf7, 0x08, + 0xe3, 0x51, 0x5c, 0x4f, 0xda, 0xb1, 0x66, 0xed, 0x1a, 0x28, 0x4f, 0x08, 0x9c, 0xf6, 0x89, 0x4f, + 0x71, 0xed, 0xb7, 0x1c, 0xb8, 0x64, 0x52, 0xa7, 0x69, 0xdb, 0x26, 0x07, 0x1f, 0x21, 0xea, 0x82, + 0x3c, 0xf2, 0xc8, 0xc0, 0x67, 0x1c, 0x52, 0xa9, 0x51, 0xd6, 0x65, 0x55, 0xc3, 0x8a, 0xe9, 0xb2, + 0x22, 0xfa, 0x06, 0x71, 0xfd, 0x96, 0xf1, 0xe2, 0xd5, 0xf5, 0x85, 0x5f, 0x5f, 0x5d, 0xbf, 0xe3, + 0xb8, 0x6c, 0x7b, 0xd0, 0xd5, 0x2d, 0xe2, 0xc9, 0x16, 0x90, 0x7f, 0xd6, 0xa8, 0xbd, 0x63, 0xb0, + 0xfd, 0x3e, 0xa6, 0x5c, 0xa1, 0x2d, 0x2d, 0x87, 0xc8, 0x3d, 0xe4, 0x23, 0x07, 0x07, 0x11, 0x72, + 0xb9, 0x84, 0x37, 0xc0, 0xd9, 0xad, 0x80, 0x78, 0x1d, 0x64, 0xdb, 0x01, 0xa6, 0x94, 0x83, 0x2f, + 0xb6, 0x4b, 0xe1, 0x5e, 0x53, 0x6c, 0xc1, 0x07, 0x20, 0x4f, 0x19, 0x62, 0x03, 0xaa, 0x2e, 0x55, + 0x95, 0xfa, 0x72, 0xa3, 0xa6, 0x4f, 0x6a, 0x5a, 0x5d, 0xa0, 0xda, 0xe4, 0x92, 0x6d, 0xa9, 0x01, + 0x9b, 0xa0, 0x24, 0x24, 0x3a, 0x61, 0x54, 0x6a, 0x9e, 0x1b, 0xa8, 0x66, 0x19, 0x78, 0xb6, 0xdf, + 0xc7, 0x6d, 0xe0, 0x8d, 0x7e, 0xc3, 0x0f, 0x40, 0x49, 0xf4, 0x48, 0xa7, 0xe7, 0x52, 0xa6, 0x9e, + 0xa9, 0xe6, 0xea, 0xa5, 0xc6, 0x8d, 0xc9, 0x26, 0x9a, 0x5c, 0x90, 0x17, 0xa0, 0xb5, 0x18, 0x26, + 0xab, 0x0d, 0x84, 0xee, 0x47, 0x2e, 0x65, 0x21, 0x56, 0x3a, 0xe8, 0xf7, 0x7b, 0xfb, 0x9d, 0x2d, + 0x77, 0x0f, 0xdb, 0x6a, 0xa1, 0xaa, 0xd4, 0x0b, 0xed, 0x92, 0xd8, 0x7b, 0x14, 0x6e, 0xc1, 0x77, + 0x80, 0xca, 0xcb, 0xd9, 0x71, 0xc8, 0x10, 0x07, 0xdc, 0x7c, 0xc7, 0x22, 0x3e, 0x0b, 0x48, 0x4f, + 0x2d, 0x72, 0xf1, 0x2b, 0xfc, 0xfc, 0xf1, 0xe8, 0x78, 0x43, 0x9c, 0xd6, 0xae, 0x80, 0x95, 0x64, + 0x75, 0x65, 0xd9, 0x0f, 0x94, 0xa8, 0xec, 0x22, 0xb8, 0x79, 0x34, 0xf2, 0x7b, 0x20, 0x2f, 0x60, + 0xa9, 0xb9, 0xd3, 0x65, 0x43, 0xaa, 0xc5, 0xc1, 0x46, 0x31, 0xc9, 0x60, 0xbf, 0x00, 0x57, 0x4c, + 0xea, 0x3c, 0xc4, 0x3d, 0xcc, 0xf0, 0xfc, 0xc2, 0xbd, 0x03, 0xce, 0x07, 0xd8, 0x23, 0x43, 0x6c, + 0x8f, 0xda, 0x4c, 0x74, 0xe1, 0xb2, 0xdc, 0x96, 0x9d, 0x56, 0x2b, 0x83, 0xab, 0xc7, 0xdc, 0xcb, + 0xc8, 0x9e, 0x02, 0x68, 0x52, 0xe7, 0x91, 0xeb, 0xa3, 0x9e, 0xfb, 0xf9, 0x3c, 0x5e, 0x83, 0xda, + 0x65, 0x5e, 0x97, 0xd8, 0x62, 0xc2, 0x51, 0xd3, 0x62, 0xee, 0x10, 0xb1, 0x39, 0x3a, 0x8a, 0x2d, + 0x4a, 0x47, 0x1f, 0x83, 0x0b, 0x26, 0x75, 0x36, 0xc2, 0x9a, 0xf5, 0xe6, 0xe1, 0xe6, 0x12, 0xb8, + 0x38, 0x66, 0x2f, 0xe1, 0x44, 0x64, 0x74, 0x7e, 0x4e, 0x22, 0x7b, 0xd2, 0xc9, 0xd7, 0x0a, 0x58, + 0x36, 0xa9, 0x63, 0xba, 0x3e, 0xfb, 0x3b, 0x1f, 0xb5, 0xd9, 0x22, 0xbe, 0x08, 0xce, 0x8f, 0x62, + 0x4b, 0xc6, 0xdb, 0x1a, 0x04, 0xfe, 0xbf, 0x35, 0x5e, 0x11, 0x9b, 0x8c, 0xf7, 0x67, 0x85, 0xf7, + 0xe4, 0x27, 0x2e, 0xdb, 0xb6, 0x03, 0xb4, 0x3b, 0x8f, 0x2b, 0xb9, 0x0a, 0x00, 0x23, 0xa9, 0xdb, + 0x58, 0x64, 0x24, 0x7a, 0xf2, 0xad, 0x51, 0x3a, 0x16, 0xf9, 0x03, 0x93, 0x91, 0x8e, 0xfb, 0x61, + 0x3a, 0xbe, 0xf9, 0xfd, 0x7a, 0x7d, 0xc6, 0x74, 0xd0, 0x28, 0x1f, 0xf2, 0x5e, 0xc4, 0xa8, 0x24, + 0xda, 0xd7, 0x02, 0xed, 0x33, 0xc9, 0x32, 0xfe, 0xd1, 0x0a, 0xe5, 0x26, 0xe5, 0x6e, 0x86, 0x91, + 0x99, 0x4c, 0xef, 0x52, 0x2a, 0xbd, 0x12, 0x79, 0x8c, 0x50, 0x22, 0xff, 0x49, 0x01, 0x97, 0x4d, + 0xea, 0x3c, 0xe9, 0x5a, 0x69, 0xf0, 0x07, 0x0a, 0x28, 0x44, 0xb4, 0x4b, 0xe2, 0xbf, 0xab, 0xbb, + 0x5d, 0x4b, 0x1f, 0x27, 0x66, 0x7a, 0x24, 0xc1, 0x87, 0x69, 0x6c, 0xbf, 0xf5, 0xa1, 0xcc, 0xc7, + 0xc6, 0xf1, 0x7c, 0xb8, 0x5d, 0x6b, 0xcd, 0x21, 0xc6, 0xf0, 0x6d, 0xc3, 0x23, 0xf6, 0xa0, 0x87, + 0x69, 0x48, 0xf5, 0xc6, 0x28, 0x9e, 0x48, 0xd2, 0x78, 0xb0, 0xa3, 0x38, 0x66, 0xec, 0x67, 0x95, + 0x8f, 0x94, 0x04, 0x26, 0x09, 0xf7, 0x07, 0x05, 0x68, 0x26, 0x75, 0x36, 0x31, 0x7b, 0x18, 0x76, + 0xae, 0x89, 0x19, 0xb2, 0x11, 0x43, 0x11, 0xe6, 0x01, 0x28, 0x78, 0x72, 0x4b, 0x42, 0x5e, 0x8d, + 0x4b, 0xee, 0xef, 0x8c, 0x4a, 0x1e, 0xe9, 0xb5, 0x1e, 0x48, 0x98, 0x8d, 0xcc, 0xb2, 0xef, 0x09, + 0xa6, 0x2b, 0x81, 0x45, 0x3e, 0x47, 0xae, 0x66, 0x44, 0xb5, 0x0a, 0xae, 0x4d, 0x0c, 0x5d, 0x42, + 0xfb, 0x36, 0x07, 0xfe, 0x2f, 0x06, 0x6c, 0x34, 0x5f, 0xa2, 0xe7, 0xff, 0x3f, 0xc6, 0xfd, 0x52, + 0xfc, 0x6d, 0xe9, 0xaf, 0xf3, 0xb7, 0xfc, 0xfc, 0xf8, 0xdb, 0x99, 0xd3, 0xf1, 0xb7, 0x42, 0x26, + 0x7f, 0xbb, 0x0d, 0x6e, 0x66, 0x57, 0x4c, 0x94, 0xb6, 0xf1, 0xe5, 0x59, 0x90, 0x33, 0xa9, 0x03, + 0x3b, 0xa0, 0x10, 0x49, 0xc2, 0xfa, 0x94, 0x84, 0x1c, 0x23, 0x2c, 0xda, 0xdd, 0x19, 0x24, 0x85, + 0xa3, 0xd0, 0x41, 0x14, 0x42, 0x86, 0x83, 0x14, 0x51, 0xc9, 0x70, 0x90, 0x26, 0x20, 0xf0, 0x53, + 0x90, 0x17, 0x6c, 0x01, 0xde, 0x9e, 0xaa, 0x94, 0xa0, 0x27, 0xda, 0x9d, 0x13, 0xe5, 0x62, 0xd3, + 0x82, 0x23, 0x64, 0x98, 0x4e, 0x90, 0x92, 0x0c, 0xd3, 0x49, 0xb2, 0x01, 0x37, 0xc1, 0x62, 0x38, + 0xcc, 0xe1, 0xcd, 0xa9, 0x0a, 0x63, 0x3c, 0x44, 0xbb, 0x75, 0x82, 0x54, 0x6c, 0x34, 0x9c, 0xb8, + 0x19, 0x46, 0xc7, 0xc8, 0x42, 0x86, 0xd1, 0xf1, 0xb1, 0x0d, 0xbb, 0xa0, 0x38, 0x62, 0xd8, 0x30, + 0xa3, 0x2e, 0xa9, 0xff, 0x0c, 0xb4, 0x37, 0x66, 0x11, 0x95, 0x3e, 0x76, 0xc0, 0xd9, 0x71, 0xba, + 0x0c, 0xef, 0x9d, 0x90, 0xc6, 0xa4, 0xa7, 0xb5, 0x19, 0xa5, 0xe3, 0x8e, 0x8c, 0xa6, 0x75, 0x46, + 0x47, 0xa6, 0x68, 0x4a, 0x46, 0x47, 0xa6, 0x47, 0xbf, 0xcc, 0x98, 0xb8, 0x70, 0xd9, 0x19, 0x4b, + 0x3c, 0xa3, 0xd9, 0x19, 0x4b, 0xde, 0xdf, 0x10, 0x44, 0x34, 0x89, 0x32, 0x40, 0xa4, 0x06, 0x70, + 0x06, 0x88, 0xf4, 0x58, 0x83, 0xdb, 0xa0, 0x34, 0x36, 0xed, 0xe0, 0x9b, 0x53, 0x35, 0x8f, 0xcf, + 0x79, 0xed, 0xde, 0x6c, 0xc2, 0xd2, 0xd3, 0x2e, 0xb8, 0x90, 0x9e, 0x40, 0xf0, 0xfe, 0x54, 0x0b, + 0x53, 0xe6, 0xac, 0xb6, 0x7e, 0x0a, 0x0d, 0xe9, 0xf8, 0x39, 0x58, 0x4e, 0x7e, 0xe4, 0x80, 0xfa, + 0x54, 0x23, 0x13, 0x3f, 0xe3, 0x68, 0xc6, 0xcc, 0xf2, 0xd2, 0xe5, 0x81, 0x02, 0xca, 0x53, 0x1f, + 0x67, 0xf8, 0x6e, 0x56, 0x03, 0x64, 0x8e, 0x60, 0xed, 0xc1, 0x9f, 0x51, 0x15, 0x41, 0xb5, 0x9c, + 0x17, 0x87, 0x15, 0xe5, 0xe5, 0x61, 0x45, 0x79, 0x7d, 0x58, 0x51, 0xbe, 0x3a, 0xaa, 0x2c, 0xbc, + 0x3c, 0xaa, 0x2c, 0xfc, 0x72, 0x54, 0x59, 0x00, 0x57, 0x5d, 0x32, 0xd1, 0xee, 0x53, 0xe5, 0xb3, + 0x71, 0x7a, 0x12, 0x8b, 0xac, 0xb9, 0x64, 0x6c, 0x65, 0xec, 0x45, 0x5f, 0xc8, 0xf8, 0x40, 0xef, + 0xe6, 0xf9, 0x47, 0xa8, 0xb7, 0xfe, 0x08, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x26, 0x97, 0xbf, 0x4e, + 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1527,6 +1656,8 @@ type MsgClient interface { // GrantAllowance grants fee allowance to the grantee on the granter's // account with the provided expiration time. GrantAllowance(ctx context.Context, in *MsgGrantAllowanceRequest, opts ...grpc.CallOption) (*MsgGrantAllowanceResponse, error) + // AddFinalizeActivateMarker + AddFinalizeActivateMarker(ctx context.Context, in *MsgAddFinalizeActivateMarkerRequest, opts ...grpc.CallOption) (*MsgAddFinalizeActivateMarkerResponse, error) } type msgClient struct { @@ -1663,6 +1794,15 @@ func (c *msgClient) GrantAllowance(ctx context.Context, in *MsgGrantAllowanceReq return out, nil } +func (c *msgClient) AddFinalizeActivateMarker(ctx context.Context, in *MsgAddFinalizeActivateMarkerRequest, opts ...grpc.CallOption) (*MsgAddFinalizeActivateMarkerResponse, error) { + out := new(MsgAddFinalizeActivateMarkerResponse) + err := c.cc.Invoke(ctx, "/provenance.marker.v1.Msg/AddFinalizeActivateMarker", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // Finalize @@ -1695,6 +1835,8 @@ type MsgServer interface { // GrantAllowance grants fee allowance to the grantee on the granter's // account with the provided expiration time. GrantAllowance(context.Context, *MsgGrantAllowanceRequest) (*MsgGrantAllowanceResponse, error) + // AddFinalizeActivateMarker + AddFinalizeActivateMarker(context.Context, *MsgAddFinalizeActivateMarkerRequest) (*MsgAddFinalizeActivateMarkerResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -1743,6 +1885,9 @@ func (*UnimplementedMsgServer) SetDenomMetadata(ctx context.Context, req *MsgSet func (*UnimplementedMsgServer) GrantAllowance(ctx context.Context, req *MsgGrantAllowanceRequest) (*MsgGrantAllowanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GrantAllowance not implemented") } +func (*UnimplementedMsgServer) AddFinalizeActivateMarker(ctx context.Context, req *MsgAddFinalizeActivateMarkerRequest) (*MsgAddFinalizeActivateMarkerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddFinalizeActivateMarker not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -2000,6 +2145,24 @@ func _Msg_GrantAllowance_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Msg_AddFinalizeActivateMarker_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAddFinalizeActivateMarkerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).AddFinalizeActivateMarker(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/provenance.marker.v1.Msg/AddFinalizeActivateMarker", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).AddFinalizeActivateMarker(ctx, req.(*MsgAddFinalizeActivateMarkerRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "provenance.marker.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -2060,6 +2223,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "GrantAllowance", Handler: _Msg_GrantAllowance_Handler, }, + { + MethodName: "AddFinalizeActivateMarker", + Handler: _Msg_AddFinalizeActivateMarker_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "provenance/marker/v1/tx.proto", @@ -3049,6 +3216,115 @@ func (m *MsgSetDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *MsgAddFinalizeActivateMarkerRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAddFinalizeActivateMarkerRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddFinalizeActivateMarkerRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.AllowGovernanceControl { + i-- + if m.AllowGovernanceControl { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x40 + } + if m.SupplyFixed { + i-- + if m.SupplyFixed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } + if len(m.AccessList) > 0 { + for iNdEx := len(m.AccessList) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AccessList[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + if m.MarkerType != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.MarkerType)) + i-- + dAtA[i] = 0x28 + } + if len(m.FromAddress) > 0 { + i -= len(m.FromAddress) + copy(dAtA[i:], m.FromAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.FromAddress))) + i-- + dAtA[i] = 0x22 + } + if len(m.Manager) > 0 { + i -= len(m.Manager) + copy(dAtA[i:], m.Manager) + i = encodeVarintTx(dAtA, i, uint64(len(m.Manager))) + i-- + dAtA[i] = 0x1a + } + { + size := m.Amount.Size() + i -= size + if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *MsgAddFinalizeActivateMarkerResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgAddFinalizeActivateMarkerResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAddFinalizeActivateMarkerResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -3470,6 +3746,49 @@ func (m *MsgSetDenomMetadataResponse) Size() (n int) { return n } +func (m *MsgAddFinalizeActivateMarkerRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Manager) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.FromAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.MarkerType != 0 { + n += 1 + sovTx(uint64(m.MarkerType)) + } + if len(m.AccessList) > 0 { + for _, e := range m.AccessList { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if m.SupplyFixed { + n += 2 + } + if m.AllowGovernanceControl { + n += 2 + } + return n +} + +func (m *MsgAddFinalizeActivateMarkerResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -6186,6 +6505,296 @@ func (m *MsgSetDenomMetadataResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgAddFinalizeActivateMarkerRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAddFinalizeActivateMarkerRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddFinalizeActivateMarkerRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Manager", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Manager = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MarkerType", wireType) + } + m.MarkerType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MarkerType |= MarkerType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccessList", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccessList = append(m.AccessList, AccessGrant{}) + if err := m.AccessList[len(m.AccessList)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplyFixed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SupplyFixed = bool(v != 0) + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowGovernanceControl", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowGovernanceControl = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgAddFinalizeActivateMarkerResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgAddFinalizeActivateMarkerResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAddFinalizeActivateMarkerResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0