Skip to content

Commit

Permalink
[Miner] chore: scaffold create-claim message (#43)
Browse files Browse the repository at this point in the history
* chore: scaffold create claim message

`ignite scaffold message create-claim session_header:SessionHeader root_hash --signer SupplierAddress --module supplier`
(NB: generated a temporary SessionHeader duplicate in the supplier module so the above would work; subsequently, removed and updated protobuf import and usage.)

* refactor: use `bytes` type for `MsgCreateClaim#root_hash` field

* chore:  add TODO comment in msg handler

* chore: add TODOs

Co-authored-by: Daniel Olshansky <[email protected]>

---------

Co-authored-by: Daniel Olshansky <[email protected]>
  • Loading branch information
bryanchriswhite and Olshansk authored Oct 17, 2023
1 parent 0405651 commit ab0a1f1
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 3 deletions.
30 changes: 30 additions & 0 deletions docs/static/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76031,11 +76031,41 @@ definitions:
description: params holds all the parameters of this module.
type: object
description: QueryParamsResponse is response type for the Query/Params RPC method.
pocket.session.SessionHeader:
type: object
properties:
application_address:
type: string
title: The address of the application this session is for
session_block_start_height:
type: string
format: int64
description: The height at which this session started
title: >-
TODO(@Olshansk): Uncomment the line below once the `ServiceId` proto
is defined

service.ServiceId service_id = 2; // The ID of the service this
session is servicing
session_id:
type: string
description: A unique pseudoranom ID for this session
title: >-
NOTE: session_id can be derived from the above values using on-chain
but is included in the header for convenience
description: >-
SessionHeader is a lightweight header for a session that can be passed
around.

It is the minimal amount of data required to hydrate & retrieve all data
relevant to the session.
pocket.shared.Supplier:
type: object
properties:
address:
type: string
pocket.supplier.MsgCreateClaimResponse:
type: object
pocket.supplier.MsgStakeSupplierResponse:
type: object
pocket.supplier.MsgUnstakeSupplierResponse:
Expand Down
17 changes: 14 additions & 3 deletions proto/pocket/supplier/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ syntax = "proto3";

package pocket.supplier;

import "pocket/session/session.proto";

option go_package = "pocket/x/supplier/types";

// Msg defines the Msg service.
service Msg {
rpc StakeSupplier (MsgStakeSupplier) returns (MsgStakeSupplierResponse);
rpc StakeSupplier (MsgStakeSupplier ) returns (MsgStakeSupplierResponse );
rpc UnstakeSupplier (MsgUnstakeSupplier) returns (MsgUnstakeSupplierResponse);
rpc CreateClaim (MsgCreateClaim ) returns (MsgCreateClaimResponse );
}

message MsgUnstakeSupplier {
string address = 1;
}
Expand All @@ -20,4 +22,13 @@ message MsgStakeSupplier {

message MsgUnstakeSupplierResponse {}

message MsgStakeSupplierResponse {}
message MsgStakeSupplierResponse {}

message MsgCreateClaim {
string supplier_address = 1;
pocket.session.SessionHeader session_header = 2;
bytes root_hash = 3;
}

message MsgCreateClaimResponse {}

1 change: 1 addition & 0 deletions x/supplier/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func GetTxCmd() *cobra.Command {

cmd.AddCommand(CmdStakeSupplier())
cmd.AddCommand(CmdUnstakeSupplier())
cmd.AddCommand(CmdCreateClaim())
// this line is used by starport scaffolding # 1

return cmd
Expand Down
57 changes: 57 additions & 0 deletions x/supplier/client/cli/tx_create_claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cli

import (
"encoding/base64"
"strconv"

"encoding/json"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"

sessiontypes "pocket/x/session/types"
"pocket/x/supplier/types"
)

// TODO(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic.

var _ = strconv.Itoa(0)

func CmdCreateClaim() *cobra.Command {
cmd := &cobra.Command{
Use: "create-claim [session-header] [root-hash-base64]",
Short: "Broadcast message create-claim",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
argSessionHeader := new(sessiontypes.SessionHeader)
err = json.Unmarshal([]byte(args[0]), argSessionHeader)
if err != nil {
return err
}
argRootHash, err := base64.StdEncoding.DecodeString(args[1])
if err != nil {
return err
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgCreateClaim(
clientCtx.GetFromAddress().String(),
argSessionHeader,
argRootHash,
)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
42 changes: 42 additions & 0 deletions x/supplier/keeper/msg_server_create_claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package keeper

import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"pocket/x/supplier/types"
)

func (k msgServer) CreateClaim(goCtx context.Context, msg *types.MsgCreateClaim) (*types.MsgCreateClaimResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

/*
INCOMPLETE: Handling the message
## Validation
### Session validation
1. [ ] claimed session ID == retrieved session ID
2. [ ] this supplier is in the session's suppliers list
### Msg distribution validation (depends on session validation)
1. [ ] pseudo-randomize earliest block offset
2. [ ] governance-based earliest block offset
### Claim validation
1. [ ] session validation
2. [ ] msg distribution validation
## Persistence
1. [ ] create claim message
- supplier address
- session header
- claim
2. [ ] last block height commitment; derives:
- last block committed hash, must match proof path
- session ID (?)
*/
_ = ctx

return &types.MsgCreateClaimResponse{}, nil
}
23 changes: 23 additions & 0 deletions x/supplier/module_simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const (
// TODO: Determine the simulation weight value
defaultWeightMsgUnstakeSupplier int = 100

opWeightMsgCreateClaim = "op_weight_msg_create_claim"
// TODO: Determine the simulation weight value
defaultWeightMsgCreateClaim int = 100

// this line is used by starport scaffolding # simapp/module/const
)

Expand Down Expand Up @@ -82,6 +86,17 @@ func (am AppModule) WeightedOperations(simState module.SimulationState) []simtyp
suppliersimulation.SimulateMsgUnstakeSupplier(am.accountKeeper, am.bankKeeper, am.keeper),
))

var weightMsgCreateClaim int
simState.AppParams.GetOrGenerate(simState.Cdc, opWeightMsgCreateClaim, &weightMsgCreateClaim, nil,
func(_ *rand.Rand) {
weightMsgCreateClaim = defaultWeightMsgCreateClaim
},
)
operations = append(operations, simulation.NewWeightedOperation(
weightMsgCreateClaim,
suppliersimulation.SimulateMsgCreateClaim(am.accountKeeper, am.bankKeeper, am.keeper),
))

// this line is used by starport scaffolding # simapp/module/operation

return operations
Expand All @@ -106,6 +121,14 @@ func (am AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.Wei
return nil
},
),
simulation.NewWeightedProposalMsg(
opWeightMsgCreateClaim,
defaultWeightMsgCreateClaim,
func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) sdk.Msg {
suppliersimulation.SimulateMsgCreateClaim(am.accountKeeper, am.bankKeeper, am.keeper)
return nil
},
),
// this line is used by starport scaffolding # simapp/module/OpMsg
}
}
29 changes: 29 additions & 0 deletions x/supplier/simulation/create_claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package simulation

import (
"math/rand"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"pocket/x/supplier/keeper"
"pocket/x/supplier/types"
)

func SimulateMsgCreateClaim(
ak types.AccountKeeper,
bk types.BankKeeper,
k keeper.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)
msg := &types.MsgCreateClaim{
SupplierAddress: simAccount.Address.String(),
}

// TODO: Handling the CreateClaim simulation

return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "CreateClaim simulation not implemented"), nil, nil
}
}
4 changes: 4 additions & 0 deletions x/supplier/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgStakeSupplier{}, "supplier/StakeSupplier", nil)
cdc.RegisterConcrete(&MsgUnstakeSupplier{}, "supplier/UnstakeSupplier", nil)
cdc.RegisterConcrete(&MsgCreateClaim{}, "supplier/CreateClaim", nil)
// this line is used by starport scaffolding # 2
}

Expand All @@ -18,6 +19,9 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
&MsgStakeSupplier{},
&MsgUnstakeSupplier{},
)
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgCreateClaim{},
)
// this line is used by starport scaffolding # 3

msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
Expand Down
49 changes: 49 additions & 0 deletions x/supplier/types/message_create_claim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package types

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

sessiontypes "pocket/x/session/types"
)

const TypeMsgCreateClaim = "create_claim"

var _ sdk.Msg = &MsgCreateClaim{}

func NewMsgCreateClaim(supplierAddress string, sessionHeader *sessiontypes.SessionHeader, rootHash []byte) *MsgCreateClaim {
return &MsgCreateClaim{
SupplierAddress: supplierAddress,
SessionHeader: sessionHeader,
RootHash: rootHash,
}
}

func (msg *MsgCreateClaim) Route() string {
return RouterKey
}

func (msg *MsgCreateClaim) Type() string {
return TypeMsgCreateClaim
}

func (msg *MsgCreateClaim) GetSigners() []sdk.AccAddress {
supplierAddress, err := sdk.AccAddressFromBech32(msg.SupplierAddress)
if err != nil {
panic(err)
}
return []sdk.AccAddress{supplierAddress}
}

func (msg *MsgCreateClaim) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

func (msg *MsgCreateClaim) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.SupplierAddress)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid supplierAddress address (%s)", err)
}
return nil
}
42 changes: 42 additions & 0 deletions x/supplier/types/message_create_claim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package types

import (
"testing"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/stretchr/testify/require"
"pocket/testutil/sample"
)

// TODO(@bryanchriswhite): Add unit tests for message validation when adding the business logic.

func TestMsgCreateClaim_ValidateBasic(t *testing.T) {
tests := []struct {
name string
msg MsgCreateClaim
err error
}{
{
name: "invalid address",
msg: MsgCreateClaim{
SupplierAddress: "invalid_address",
},
err: sdkerrors.ErrInvalidAddress,
}, {
name: "valid address",
msg: MsgCreateClaim{
SupplierAddress: sample.AccAddress(),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.msg.ValidateBasic()
if tt.err != nil {
require.ErrorIs(t, err, tt.err)
return
}
require.NoError(t, err)
})
}
}

0 comments on commit ab0a1f1

Please sign in to comment.