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

Refactor how messages are processed #129

Merged
merged 39 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5adcc74
delete old generated app
evan-forbes Sep 29, 2021
d4f715d
update proto to use tendermint instead of celestia-core
evan-forbes Sep 29, 2021
3fde1ac
regenerate and adjust application
evan-forbes Sep 29, 2021
aba62ee
use cosmoscmd instead of copying everything over
evan-forbes Sep 29, 2021
7b8d57f
regenerate and adjust module boilerplate
evan-forbes Sep 29, 2021
465354a
copy over and adjust client code
evan-forbes Sep 29, 2021
120178d
copy over and adjust core WirePayForMessage along with SignedTransact…
evan-forbes Sep 29, 2021
6521896
use go 1.17
evan-forbes Sep 29, 2021
f4668c0
linter
evan-forbes Sep 29, 2021
f50a6be
clean up test
evan-forbes Sep 29, 2021
204f736
stop using the governace module
evan-forbes Sep 29, 2021
8c4af90
delete unsused files
evan-forbes Sep 30, 2021
eeef99b
shorten address prefix
evan-forbes Sep 30, 2021
470d7f4
refactor proto
evan-forbes Sep 30, 2021
e3ba168
flesh out refactor of pfm and signedPFM
evan-forbes Oct 1, 2021
84335c4
finish most of payment module refactor
evan-forbes Oct 5, 2021
650a630
update proto
evan-forbes Oct 5, 2021
fe9e33d
linter
evan-forbes Oct 5, 2021
a0d11a2
run go mod tidy
evan-forbes Oct 5, 2021
fa251e2
small update to proto
evan-forbes Oct 5, 2021
ddc3d20
slight refactor of processingWPFM and add test
evan-forbes Oct 5, 2021
7be2249
use a more standard naming scheme for sdk proto messages
evan-forbes Oct 5, 2021
b823270
clean up todos and final touches
evan-forbes Oct 6, 2021
5340112
docs
evan-forbes Oct 6, 2021
74e5518
improve error message
evan-forbes Oct 6, 2021
211a724
improved docs
evan-forbes Oct 6, 2021
ed9d1af
add punctuation
evan-forbes Oct 7, 2021
43b1303
change file name after rebase
evan-forbes Oct 8, 2021
18bbd57
remove comment
evan-forbes Oct 8, 2021
b5e777b
fix proto
evan-forbes Oct 8, 2021
57b8dfd
remove generated iota
evan-forbes Oct 8, 2021
ca10bb7
better docs for SignShareCommitment
evan-forbes Oct 8, 2021
5958359
use more idiomatic comparisons
evan-forbes Oct 8, 2021
d4981ed
better docs for SignShareCommitments
evan-forbes Oct 8, 2021
703aaec
keep comment
evan-forbes Oct 8, 2021
f11c413
move function over to test
evan-forbes Oct 8, 2021
7faab6f
Merge branch 'evan/refactor-wpfm' of github.com:celestiaorg/lazyledge…
evan-forbes Oct 8, 2021
677d924
change celestia-core tag to more idiomatic tag
evan-forbes Oct 12, 2021
cb9810a
actually use nsLen for the error
evan-forbes Oct 12, 2021
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
103 changes: 28 additions & 75 deletions app/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ package app

import (
"bytes"
"errors"
"fmt"
"sort"

"github.com/celestiaorg/celestia-app/x/payment/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/pkg/consts"
core "github.com/tendermint/tendermint/proto/tendermint/types"
)

// This file should contain all of the altered ABCI methods

// PreprocessTxs fullfills the celestia-core version of the ACBI interface, by
// performing basic validation for the incoming txs, and by cleanly separating
// share messages from transactions
Expand All @@ -30,32 +27,49 @@ func (app *App) PreprocessTxs(txs abci.RequestPreprocessTxs) abci.ResponsePrepro
continue
}

authTx, ok := tx.(signing.Tx)
if !ok {
continue
}

// don't process the tx if the transaction doesn't contain a
// PayForMessage sdk.Msg
if !hasWirePayForMessage(tx) {
// MsgPayForMessage sdk.Msg
if !hasWirePayForMessage(authTx) {
processedTxs = append(processedTxs, rawTx)
continue
}

// only support transactions that contain a single sdk.Msg
if len(tx.GetMsgs()) != 1 {
if len(authTx.GetMsgs()) != 1 {
continue
}

msg := tx.GetMsgs()[0]
msg := authTx.GetMsgs()[0]
wireMsg, ok := msg.(*types.MsgWirePayForMessage)
if !ok {
continue
}

// run basic validation on the transaction
err = tx.ValidateBasic()
err = authTx.ValidateBasic()
evan-forbes marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
continue
}

// process the message
coreMsg, signedTx, err := app.processMsg(msg)
// parse wire message and create a single message
coreMsg, unsignedPFM, sig, err := types.ProcessWirePayForMessage(wireMsg, app.SquareSize())
if err != nil {
continue
}

// create the signed PayForMessage using the fees, gas limit, and sequence from
// the original transaction, along with the appropriate signature.
signedTx, err := types.BuildPayForMessageTxFromWireTx(authTx, app.txConfig.NewTxBuilder(), sig, unsignedPFM)
if err != nil {
app.Logger().Error("failure to create signed PayForMessage", err)
continue
}

// increment the share counter by the number of shares taken by the message
sharesTaken := uint64(len(coreMsg.Data) / types.ShareSize)
shareCounter += sharesTaken
Expand All @@ -65,14 +79,12 @@ func (app *App) PreprocessTxs(txs abci.RequestPreprocessTxs) abci.ResponsePrepro
break
}

// encode the processed tx
rawProcessedTx, err := app.appCodec.Marshal(signedTx)
rawProcessedTx, err := app.txConfig.TxEncoder()(signedTx)
if err != nil {
continue
}

// add the message and tx to the output
shareMsgs = append(shareMsgs, &coreMsg)
shareMsgs = append(shareMsgs, coreMsg)
processedTxs = append(processedTxs, rawProcessedTx)
}

Expand All @@ -87,75 +99,16 @@ func (app *App) PreprocessTxs(txs abci.RequestPreprocessTxs) abci.ResponsePrepro
}
}

// pfmURL is the URL expected for pfm. NOTE: this will be deleted when we upgrade from
// sdk v0.44.0
var pfmURL = sdk.MsgTypeURL(&types.MsgWirePayForMessage{})

func hasWirePayForMessage(tx sdk.Tx) bool {
for _, msg := range tx.GetMsgs() {
msgName := sdk.MsgTypeURL(msg)
if msgName == pfmURL {
if msgName == types.URLMsgWirePayforMessage {
return true
}
// note: this is what we will use in the future as proto.MessageName is
// deprecated
// svcMsg, ok := msg.(sdk.ServiceMsg) if !ok {
// continue
// } if svcMsg.SerivceMethod == types.TypeMsgPayforMessage {
// return true
// }
}
return false
}

// processMsgs will perform the processing required by PreProcessTxs for a set
// of sdk.Msg's from a single sdk.Tx
func (app *App) processMsg(msg sdk.Msg) (core.Message, *types.TxSignedTransactionDataPayForMessage, error) {
squareSize := app.SquareSize()
// reject all msgs in tx if a single included msg is not correct type
wireMsg, ok := msg.(*types.MsgWirePayForMessage)
if !ok {
return core.Message{},
nil,
errors.New("transaction contained a message type other than types.MsgWirePayForMessage")
}

// make sure that a ShareCommitAndSignature of the correct size is
// included in the message
var shareCommit types.ShareCommitAndSignature
for _, commit := range wireMsg.MessageShareCommitment {
if commit.K == squareSize {
shareCommit = commit
}
}
// K == 0 means there was no share commit with the desired current square size
if shareCommit.K == 0 {
return core.Message{},
nil,
fmt.Errorf("No share commit for correct square size. Current square size: %d", squareSize)
}

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

// wrap the signed transaction data
sTxData, err := wireMsg.SignedTransactionDataPayForMessage(squareSize)
if err != nil {
return core.Message{}, nil, err
}

signedData := &types.TxSignedTransactionDataPayForMessage{
Message: sTxData,
Signature: shareCommit.Signature,
PublicKey: wireMsg.PublicKey,
}

return coreMsg, signedData, nil
}

// SquareSize returns the current square size. Currently, the square size is
// hardcoded. todo(evan): don't hardcode the square size
func (app *App) SquareSize() uint64 {
Expand Down
155 changes: 39 additions & 116 deletions app/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/spf13/cast"
Expand All @@ -28,6 +26,7 @@ import (
"github.com/tendermint/spm/cosmoscmd"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/pkg/consts"
core "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
Expand All @@ -39,40 +38,6 @@ func init() {
simapp.GetSimulatorFlags()
}

func TestProcessMsg(t *testing.T) {
kb := keyring.NewInMemory()
info, _, err := kb.NewMnemonic(testingKeyAcc, keyring.English, "", "", hd.Secp256k1)
if err != nil {
t.Error(err)
}
ns := []byte{1, 1, 1, 1, 1, 1, 1, 1}
message := bytes.Repeat([]byte{1}, 256)

// create a signed MsgWirePayFroMessage
msg := generateSignedWirePayForMessage(t, types.SquareSize, ns, message, kb)

testApp := setupApp(t, info.GetPubKey())

tests := []struct {
name string
args sdk.Msg
want core.Message
}{
{
name: "basic",
args: msg,
want: core.Message{NamespaceId: msg.MessageNameSpaceId, Data: msg.Message},
},
}
for _, tt := range tests {
result, _, err := testApp.processMsg(tt.args)
if err != nil {
t.Error(err)
}
assert.Equal(t, tt.want, result, tt.name)
}
}

func TestPreprocessTxs(t *testing.T) {
kb := keyring.NewInMemory()
info, _, err := kb.NewMnemonic(testingKeyAcc, keyring.English, "", "", hd.Secp256k1)
Expand Down Expand Up @@ -151,7 +116,7 @@ func setupApp(t *testing.T, pub cryptotypes.PubKey) *App {
anteOpt,
)

genesisState := NewDefaultGenesisState(encCfg.Marshaler)
genesisState := newDefaultGenesisState(encCfg.Marshaler)

genesisState, err := addGenesisAccount(sdk.AccAddress(pub.Address().Bytes()), genesisState, encCfg.Marshaler)
if err != nil {
Expand Down Expand Up @@ -244,19 +209,10 @@ func addGenesisAccount(addr sdk.AccAddress, appState map[string]json.RawMessage,

func generateRawTx(t *testing.T, txConfig client.TxConfig, ns, message []byte, ring keyring.Keyring) (rawTx []byte) {
// create a msg
msg := generateSignedWirePayForMessage(t, types.SquareSize, ns, message, ring)

info, err := ring.Key(testingKeyAcc)
if err != nil {
t.Error(err)
}
msg := generateSignedWirePayForMessage(t, consts.MaxSquareSize, ns, message, ring)

// this is returning a tx.wrapper
builder := txConfig.NewTxBuilder()
err = builder.SetMsgs(msg)
if err != nil {
t.Error(err)
}
krs := generateKeyringSigner(t, "test")
builder := krs.NewTxBuilder()

coin := sdk.Coin{
Denom: "token",
Expand All @@ -267,97 +223,64 @@ func generateRawTx(t *testing.T, txConfig client.TxConfig, ns, message []byte, r
builder.SetGasLimit(10000)
builder.SetTimeoutHeight(99)

signingData := authsigning.SignerData{
ChainID: "test-chain",
AccountNumber: 0,
Sequence: 0,
}
tx, err := krs.BuildSignedTx(builder, msg)
require.NoError(t, err)

// Important set the Signature to nil BEFORE actually signing
sigData := signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_DIRECT,
Signature: nil,
}
// encode the tx
rawTx, err = txConfig.TxEncoder()(tx)
require.NoError(t, err)

sig := signing.SignatureV2{
PubKey: info.GetPubKey(),
Data: &sigData,
Sequence: 0,
}
return rawTx
}

// set the empty signature
err = builder.SetSignatures(sig)
if err != nil {
if err != nil {
t.Error(err)
}
}
func generateSignedWirePayForMessage(t *testing.T, k uint64, ns, message []byte, ring keyring.Keyring) *types.MsgWirePayForMessage {
signer := generateKeyringSigner(t, "test")

// Generate the bytes to be signed.
bytesToSign, err := txConfig.
SignModeHandler().
GetSignBytes(
signing.SignMode_SIGN_MODE_DIRECT,
signingData,
builder.GetTx(),
)
msg, err := types.NewWirePayForMessage(ns, message, k)
if err != nil {
t.Error(err)
}

// Sign those bytes
sigBytes, _, err := ring.Sign(testingKeyAcc, bytesToSign)
err = msg.SignShareCommitments(signer, signer.NewTxBuilder())
if err != nil {
t.Error(err)
}

// Construct the SignatureV2 struct
sigData = signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_DIRECT,
Signature: sigBytes,
}
return msg
}

sigV2 := signing.SignatureV2{
PubKey: info.GetPubKey(),
Data: &sigData,
Sequence: 0,
}
func generateKeyring(t *testing.T, accts ...string) keyring.Keyring {
t.Helper()
kb := keyring.NewInMemory()

// set the actual signature
err = builder.SetSignatures(sigV2)
if err != nil {
for _, acc := range accts {
_, _, err := kb.NewMnemonic(acc, keyring.English, "", "", hd.Secp256k1)
if err != nil {
t.Error(err)
}
}

// finish the tx
tx := builder.GetTx()

// encode the tx
rawTx, err = txConfig.TxEncoder()(tx)
_, err := kb.NewAccount(testAccName, testMnemo, "1234", "", hd.Secp256k1)
if err != nil {
t.Error(err)
panic(err)
}

return rawTx
return kb
}

func generateSignedWirePayForMessage(t *testing.T, k uint64, ns, message []byte, ring keyring.Keyring) *types.MsgWirePayForMessage {
info, err := ring.Key(testingKeyAcc)
if err != nil {
t.Error(err)
}

msg, err := types.NewMsgWirePayForMessage(ns, message, info.GetPubKey().Bytes(), &types.TransactionFee{}, k)
if err != nil {
t.Error(err)
}
func generateKeyringSigner(t *testing.T, accts ...string) *types.KeyringSigner {
kr := generateKeyring(t, accts...)
return types.NewKeyringSigner(kr, testAccName, testChainID)
}

err = msg.SignShareCommitments(testingKeyAcc, ring)
if err != nil {
t.Error(err)
}
const (
// nolint:lll
testMnemo = `ramp soldier connect gadget domain mutual staff unusual first midnight iron good deputy wage vehicle mutual spike unlock rocket delay hundred script tumble choose`
testAccName = "test-account"
testChainID = "test-chain-1"
)

return msg
// newDefaultGenesisState generates the default state for the application.
func newDefaultGenesisState(cdc codec.JSONCodec) GenesisState {
return ModuleBasics.DefaultGenesis(cdc)
}
Loading