Skip to content

Commit

Permalink
Single tx to add finalize and activate marker (#1281)
Browse files Browse the repository at this point in the history
* create method to create marker in one method.

* Add marker, finalize and activate marker in 1 step.

* adding more methods and tests.

* Adding test.

* more tests and adding to the handler.

* Adding cli method.

* Grants must be set, and cli method.

* Methods to use json for AccessGrant object for the cli.

* more cli tests.

* handler_test's

* adding sim test operation for this new path.

* fixing weight for sim tests.

* Adjusted marker operations to a cumulative weight of 100

* Add test to verify permission

* fix alias for command

* add tests to parser

* Add spec for new msg

* Add changelog entry

* remove a few redundant comments

* remove validate basic panic, add validate basic tests

* fix test setup

* fix expected error text

* remove redundant validate basic, update error message wrap, fix expected value in test

Co-authored-by: Carlton N Hanna <[email protected]>
  • Loading branch information
Arnab Mitra and nullpointer0x00 authored Jan 5, 2023
1 parent 64fe65a commit 16f6d72
Show file tree
Hide file tree
Showing 19 changed files with 1,549 additions and 116 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 5 additions & 5 deletions app/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 35 additions & 1 deletion docs/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -933,7 +935,7 @@ Msg defines the attribute module Msg service.
<a name="provenance.marker.v1.AccessGrant"></a>

### 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 |
Expand Down Expand Up @@ -1928,6 +1930,37 @@ MsgAddAccessResponse defines the Msg/AddAccess response type



<a name="provenance.marker.v1.MsgAddFinalizeActivateMarkerRequest"></a>

### 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) | | |






<a name="provenance.marker.v1.MsgAddFinalizeActivateMarkerResponse"></a>

### MsgAddFinalizeActivateMarkerResponse
MsgAddFinalizeActivateMarkerResponse defines the Msg/AddFinalizeActivateMarker response type






<a name="provenance.marker.v1.MsgAddMarkerRequest"></a>

### MsgAddMarkerRequest
Expand Down Expand Up @@ -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 | |

<!-- end services -->

Expand Down
2 changes: 1 addition & 1 deletion proto/provenance/marker/v1/accessgrant.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 18 additions & 1 deletion proto/provenance/marker/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -193,4 +195,19 @@ message MsgSetDenomMetadataRequest {
}

// MsgSetDenomMetadataResponse defines the Msg/SetDenomMetadata response type
message MsgSetDenomMetadataResponse {}
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 {}
191 changes: 191 additions & 0 deletions x/marker/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
}
})
}
}
Loading

0 comments on commit 16f6d72

Please sign in to comment.