Skip to content

Commit

Permalink
Update docs for payment module (celestiaorg#948)
Browse files Browse the repository at this point in the history
## TODO
- [x] Split out changes that are only relevant post ADR 008
implementation and target feature branch
- [x] Document gas cost for a message
- [x] [Potentially] remove outdated code blocks from README.md

## Future PRs
- [ ] Params section needs to be updated after params are added to
payment module celestiaorg#893
- [ ] [Potentially] add client section (motivated by
https://github.com/cosmos/cosmos-sdk/tree/main/x/auth#client)
  • Loading branch information
rootulp authored and rach-id committed Nov 16, 2022
1 parent 0e8d77b commit 39d3027
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 105 deletions.
11 changes: 3 additions & 8 deletions x/payment/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@ package cli

import (
"fmt"
// "strings"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
// "github.com/cosmos/cosmos-sdk/client/flags"
// sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/celestiaorg/celestia-app/x/payment/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/spf13/cobra"
)

// GetQueryCmd returns the cli query commands for this module
// GetQueryCmd returns the CLI query commands for this module
func GetQueryCmd(queryRoute string) *cobra.Command {
// Group payment queries under a subcommand
cmd := &cobra.Command{
Expand Down
6 changes: 2 additions & 4 deletions x/payment/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import (
"fmt"
"time"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
// "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/celestiaorg/celestia-app/x/payment/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/spf13/cobra"
)

var DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds())
Expand Down
4 changes: 4 additions & 0 deletions x/payment/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// payment is a Cosmos SDK module that enables users to pay for data to be
// published to the Celestia blockchain. Please see ./specs/docs.md for the full
// specification of this module.
package payment
4 changes: 2 additions & 2 deletions x/payment/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

const payForDataGasDescriptor = "pay for data"

// Keeper handles all the state changes for the celestia-app module.
// Keeper handles all the state changes for the payment module.
type Keeper struct {
cdc codec.BinaryCodec
}
Expand All @@ -28,7 +28,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}

// MsgPayForData moves a user's coins to the module address and burns them.
// PayForData consumes gas based on the message size.
func (k Keeper) PayForData(goCtx context.Context, msg *types.MsgPayForData) (*types.MsgPayForDataResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

Expand Down
6 changes: 3 additions & 3 deletions x/payment/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
// RegisterInvariants registers the capability module's invariants.
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}

// InitGenesis performs the capability module's genesis initialization It returns
// no validator updates.
// InitGenesis performs the capability module's genesis initialization. It
// returns an empty list of validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate {
var genState types.GenesisState
// Initialize global index to index in genesis state
Expand All @@ -158,7 +158,7 @@ func (AppModule) ConsensusVersion() uint64 { return 2 }
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

// EndBlock executes all ABCI EndBlock logic respective to the capability module. It
// returns no validator updates.
// returns an empty list of validator updates.
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
6 changes: 3 additions & 3 deletions x/payment/payfordata.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"github.com/celestiaorg/nmt/namespace"
)

// SubmitPayForData constructs, signs and synchronously submits a PayForData
// transaction, returning a sdk.TxResponse upon submission.
// SubmitPayForData builds, signs, and synchronously submits a PayForData
// transaction. It returns a sdk.TxResponse after submission.
func SubmitPayForData(
ctx context.Context,
signer *types.KeyringSigner,
Expand Down Expand Up @@ -48,7 +48,7 @@ func SubmitPayForData(
return txResp.TxResponse, nil
}

// BuildPayForData constructs a PayForData transaction.
// BuildPayForData builds a PayForData transaction.
func BuildPayForData(
ctx context.Context,
signer *types.KeyringSigner,
Expand Down
97 changes: 13 additions & 84 deletions x/payment/spec/docs.md
Original file line number Diff line number Diff line change
@@ -1,117 +1,46 @@
# Abstract
# `x/payment`

## Abstract

The payment module is responsible for paying for arbitrary data that will be added to the Celestia blockchain. While the data being submitted can be arbitrary, the exact placement of that data is important for the transaction to be valid. This is why the payment module utilizes a malleated transaction scheme. Malleated transactions allow for users to create a single transaction, that can later be malleated by the block producer to create a variety of different valid transactions that are still signed over by the user. To accomplish this, users create a single `MsgWirePayForData` transaction, which is composed of metadata and signatures for multiple variations of the transaction that will be included onchain. After the transaction is submitted to the network, the block producer selects the appropriate signature and creates a valid `MsgPayForData` transaction depending on the square size for that block. This new malleated `MsgPayForData` transaction is what ends up onchain.

Further reading: [Message Block Layout](https://github.com/celestiaorg/celestia-specs/blob/master/src/rationale/message_block_layout.md)

## State

- The sender’s account balance, via the bank keeper’s [`Burn`](https://github.com/cosmos/cosmos-sdk/blob/531bf5084516425e8e3d24bae637601b4d36a191/x/bank/spec/01_state.md) method.
- The standard incrememnt of the sender's account number via the [auth module](https://github.com/cosmos/cosmos-sdk/blob/531bf5084516425e8e3d24bae637601b4d36a191/x/auth/spec/02_state.md).

## Messages

- [`MsgWirePayForData`](https://github.com/celestiaorg/celestia-app/blob/b4c8ebdf35db200a9b99d295a13de01110802af4/x/payment/types/tx.pb.go#L32-L40)
The payment module doesn't maintain it's own state.

While this transaction is created and signed by the user, it never actually ends up onchain. Instead, it is used to create a new "malleated" transaction that does get included onchain.
When a PayForData message is processed, it consumes gas based on the message size.

- [`MsgPayForData`](https://github.com/celestiaorg/celestia-app/blob/b4c8ebdf35db200a9b99d295a13de01110802af4/x/payment/types/tx.pb.go#L208-L216)
## Messages

The malleated transaction that is created from metadata contained in the original `MsgWirePayForData`. It also burns some of the sender’s funds.
- [`MsgWirePayForData`](https://github.com/celestiaorg/celestia-app/blob/29e0a2751182499f7dc03598eabfc8d049ae62cb/x/payment/types/tx.pb.go#L32-L40) is a message that is created and signed by the user but it never ends up on-chain.
- [`MsgPayForData`](https://github.com/celestiaorg/celestia-app/blob/29e0a2751182499f7dc03598eabfc8d049ae62cb/x/payment/types/tx.pb.go#L209-L219) is a "malleated" transaction that is created from metadata in the original `MsgWirePayForData`. `MsgPayForData` does end up on-chain.

## PrepareProposal

The malleation process occurs during the PrepareProposal step.

```go
// ProcessWirePayForData will perform the processing required by PrepareProposal.
// It parses the MsgWirePayForData to produce the components needed to create a
// single MsgPayForData
func ProcessWirePayForData(msg *MsgWirePayForData, squareSize uint64) (*tmproto.Message, *MsgPayForData, []byte, error) {
// make sure that a ShareCommitAndSignature of the correct size is
// included in the message
var shareCommit *ShareCommitAndSignature
for _, commit := range msg.MessageShareCommitment {
if commit.K == squareSize {
shareCommit = &commit
}
}
if shareCommit == nil {
return nil,
nil,
nil,
fmt.Errorf("message does not commit to current square size: %d", squareSize)
}

// add the message to the list of core message to be returned to ll-core
coreMsg := tmproto.Message{
NamespaceId: msg.GetMessageNamespaceId(),
Data: msg.GetMessage(),
}

// wrap the signed transaction data
pfd, err := msg.unsignedPayForData(squareSize)
if err != nil {
return nil, nil, nil, err
}

return &coreMsg, pfd, shareCommit.Signature, nil
}

// PrepareProposal fullfills the celestia-core version of the ACBI interface by
// preparing the proposal block data. The square size is determined by first
// estimating it via the size of the passed block data. Then the included
// MsgWirePayForData messages are malleated into MsgPayForData messages by
// separating the message and transaction that pays for that message. Lastly,
// this method generates the data root for the proposal block and passes it the
// blockdata.
func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
squareSize := app.estimateSquareSize(req.BlockData)

dataSquare, data := SplitShares(app.txConfig, squareSize, req.BlockData)

eds, err := da.ExtendShares(squareSize, dataSquare)
if err != nil {
app.Logger().Error(
"failure to erasure the data square while creating a proposal block",
"error",
err.Error(),
)
panic(err)
}

dah := da.NewDataAvailabilityHeader(eds)
data.Hash = dah.Hash()
data.OriginalSquareSize = squareSize

return abci.ResponsePrepareProposal{
BlockData: data,
}
}
```

<!-- markdownlint-enable MD010 -->

## Events

- [`NewPayForDataEvent`](https://github.com/celestiaorg/celestia-app/pull/213/files#diff-1ce55bda42cf160deca2e5ea1f4382b65f3b689c7e00c88085d7ce219e77303dR17-R21)
Emit an event that has the signer's address and size of the message that is paid for.
- [`NewPayForDataEvent`](https://github.com/celestiaorg/celestia-app/pull/213/files#diff-1ce55bda42cf160deca2e5ea1f4382b65f3b689c7e00c88085d7ce219e77303dR17-R21) is emitted with the signer's address and size of the message that is paid for.

## Parameters

There are no parameters yet, but we might add

- BaseFee
- SquareSize
- ShareSize

### Usage

`celestia-app tx payment payForData <hex encoded namespace> <hex encoded data> [flags]`
```shell
celestia-app tx payment payForData <hex encoded namespace> <hex encoded data> [flags]
```

### Programmatic Usage

There are tools to programmatically create, sign, and broadcast `MsgWirePayForDatas`
There are tools to programmatically create, sign, and broadcast `MsgWirePayForData`s

```go
// create the raw WirePayForData transaction
Expand Down
2 changes: 1 addition & 1 deletion x/payment/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const (
AttributeKeySize = "size"
)

// NewPayForDataEvent constructs a new payformessge sdk.Event
// NewPayForDataEvent constructs a new payfordata sdk.Event
func NewPayForDataEvent(signer string, size uint64) sdk.Event {
return sdk.NewEvent(
EventTypePayForData,
Expand Down

0 comments on commit 39d3027

Please sign in to comment.