Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate a MsgWirePayForMessage via CLI #32

Merged
merged 11 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/tendermint/tm-db v0.6.3
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 // indirect
golang.org/x/sys v0.0.0-20210223095934-7937bea0104d // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea
google.golang.org/grpc v1.33.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -810,8 +810,8 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210223095934-7937bea0104d h1:u0GOGnBJ3EKE/tNqREhhGiCzE9jFXydDo2lf7hOwGuc=
golang.org/x/sys v0.0.0-20210223095934-7937bea0104d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
Expand Down
81 changes: 81 additions & 0 deletions x/lazyledgerapp/client/cli/payformessage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cli

import (
"encoding/hex"
"errors"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/lazyledger/lazyledger-app/x/lazyledgerapp/types"
"github.com/spf13/cobra"
)

// CmdCreatePayForMessage returns a cobra command that uses the key ring backend
// and locally running node to create and broadcast a new WirePayForMessage
// transaction.
func CmdCreatePayForMessage() *cobra.Command {
cmd := &cobra.Command{
Use: "payForMessage [hexNamespace] [hexMessage]",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other Tx are in JSON encoding or hex, too? (I mean on the cli)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good question. I'm not sure. In other tx, each argument is parsed individually, and the only ones handling raw bytes are using either amino or the Bech32 address encoding. For example lazyledger-appd tx decode [amino-byte-string] [flags] uses the amino byte string, and all addresses are inputted as a Bech32 string. Should it use amino? Something else to handle bytes?

Copy link
Member

@liamsi liamsi Feb 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it use amino?

NOOOOOOO! please don't :-D

But seriously, let's go with hex bytes for now. Let's open an issue about the UX/UI of the CLI. I'm also not sure what would be best here. We can address this much later anyway (before mainnet). Probably the main usage won't be over the CLI but from other chains too.

And I find payForMessage [hexNamespace] [hexMessage] clear and simple enough.

Short: "Creates a new WirePayForMessage",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

// get the account name
accName := clientCtx.GetFromName()
if accName == "" {
return errors.New("no account name provided, please use the --from flag")
}

// get info on the key
keyInfo, err := clientCtx.Keyring.Key(accName)
if err != nil {
return err
}

// decode the namespace
namespace, err := hex.DecodeString(args[0])
if err != nil {
return err
}

// decode the message
message, err := hex.DecodeString(args[1])
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For better UX, maybe you can wrap error and provide info what argument (namespace or message) is wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch! You just saved someone some time 🙂 not all heroes wear capes 😉

resolved db5a91c

}

// create the PayForMessage
pfmMsg, err := types.NewMsgWirePayForMessage(
namespace,
message,
keyInfo.GetPubKey().Bytes(),
&types.TransactionFee{}, // transaction fee is not yet used
types.SquareSize,
)
if err != nil {
return err
}

// sign the PayForMessage's ShareCommitments
err = pfmMsg.SignShareCommitments(accName, clientCtx.Keyring)
if err != nil {
return err
}

// run message checks
if err = pfmMsg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), pfmMsg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
2 changes: 1 addition & 1 deletion x/lazyledgerapp/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func GetTxCmd() *cobra.Command {
RunE: client.ValidateCmd,
}

// this line is used by starport scaffolding # 1
cmd.AddCommand(CmdCreatePayForMessage())

return cmd
}
16 changes: 14 additions & 2 deletions x/lazyledgerapp/keeper/msg_server.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
package keeper

import "github.com/lazyledger/lazyledger-app/x/lazyledgerapp/types"
import (
"context"

"github.com/lazyledger/lazyledger-app/x/lazyledgerapp/types"
)

var _ types.MsgServer = msgServer{}

// MsgServer is the server API for Msg service.
type MsgServer interface {
// PayForMessage allows the user to post data to made be available.
PayForMessage(context.Context, *types.MsgWirePayForMessage) (*types.MsgPayForMessageResponse, error)
// PayForMessage allows the user to post data to made be available.
SignedTransactionDataPayForMessage(context.Context, *types.SignedTransactionDataPayForMessage) (*types.SignedTransactionDataPayForMessageResponse, error)
}

Comment on lines +11 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the relation of this interface to the MsgServer interface in x/lazyledgerapp/types/tx.pb.go?

Copy link
Member Author

@evan-forbes evan-forbes Feb 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MsgServer interface in x/lazyledgerapp/types/tx.pb.go only accounts for rpc endpoints, as the generated code assumes that there will always be 1 enpoint per 1 handler. That is not the case in our situation, where we need 2 handlers, but only 1 endpoint.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason again to only have one endpoint here?

Copy link
Member Author

@evan-forbes evan-forbes Feb 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because each MsgWirePayForMessage will have the information for multiple SignedTransactionDataPayForMessages in it, and one SignedTransactionDataPayForMessage is picked during PreprocessTxs, so having an endpoint for SignedTransactionDataPayForMessage could be confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense!

type msgServer struct {
Keeper
}

// NewMsgServerImpl returns an implementation of the bank MsgServer interface
// for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
func NewMsgServerImpl(keeper Keeper) MsgServer {
return &msgServer{Keeper: keeper}
}
46 changes: 45 additions & 1 deletion x/lazyledgerapp/types/payformessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
fmt "fmt"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lazyledger/lazyledger-core/crypto/merkle"
Expand All @@ -24,7 +25,50 @@ const (
// MsgWirePayForMessage
///////////////////////////////////////

var _ sdk.MsgRequest = &MsgWirePayForMessage{}
var _ sdk.Msg = &MsgWirePayForMessage{}

// NewMsgWirePayForMessage creates a new MsgWirePayForMessage by using the
// namespace and message to generate share commitments for the provided square sizes
// Note that the share commitments generated still need to be signed using the Sign
// method
func NewMsgWirePayForMessage(namespace, message, pubK []byte, fee *TransactionFee, sizes ...uint64) (*MsgWirePayForMessage, error) {
out := &MsgWirePayForMessage{
Fee: fee,
Nonce: 0,
MessageNameSpaceId: namespace,
MessageSize: uint64(len(message)),
Message: message,
MessageShareCommitment: make([]ShareCommitAndSignature, len(sizes)),
PublicKey: pubK,
}

// generate the share commitments
for i, size := range sizes {
commit, err := CreateCommitment(size, namespace, message)
if err != nil {
return nil, err
}
out.MessageShareCommitment[i] = ShareCommitAndSignature{K: size, ShareCommitment: commit}
}
return out, nil
}

// SignShareCommitments use the provided Keyring to sign each of the share commits
// generated during the creation of the MsgWirePayForMessage
func (msg *MsgWirePayForMessage) SignShareCommitments(accName string, ring keyring.Keyring) error {
for i, commit := range msg.MessageShareCommitment {
bytesToSign, err := msg.GetCommitmentSignBytes(commit.K)
if err != nil {
return err
}
sig, _, err := ring.Sign(accName, bytesToSign)
if err != nil {
return err
}
msg.MessageShareCommitment[i].Signature = sig
}
return nil
}
Comment on lines +59 to +72
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dope! Can we create at least a small unit test for this method?


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

Expand Down
2 changes: 0 additions & 2 deletions x/lazyledgerapp/types/tx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.