Skip to content

Commit

Permalink
integrate PayForMessage into PreprocessTxs
Browse files Browse the repository at this point in the history
delete unused utility func

change the respone type name to appease the linter

go mod tidy

app: just save the encoding config instead of the only the tx encoder and decoders

types: register PayForMessage types in the codec registry

break up testing into two chunks. document process

 add a sanity check for signing and verifying signatures

lazyledgerapp: sign the commit bytes instead of the message bytes

add genesis accounts, and attempt to debug why the signature data is getting erased

clean up tests a bit, and fix bug causing the inability to verify the signature

app: add sorting by namespace ids for returned core.Messages

clean up unused code

slight reorg of tests

unused code caught by linter

only pass successfully processed txs

update test

fix accidental changes to go.mod

mod.go: fixed the dep that was causing weird ci errors and failed proto generation

init simapp flags when testing

run make build
  • Loading branch information
evan-forbes committed Feb 21, 2021
1 parent a829d80 commit 9afafdb
Show file tree
Hide file tree
Showing 12 changed files with 615 additions and 247 deletions.
141 changes: 107 additions & 34 deletions app/abci.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package app

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

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lazyledger/lazyledger-app/x/lazyledgerapp/types"
abci "github.com/lazyledger/lazyledger-core/abci/types"
core "github.com/lazyledger/lazyledger-core/proto/tendermint/types"
Expand All @@ -13,75 +19,142 @@ import (
// share messages from transactions
// todo(evan): refactor out a for loop.
func (app *App) PreprocessTxs(txs abci.RequestPreprocessTxs) abci.ResponsePreprocessTxs {
squareSize := app.SquareSize()
shareCounter := uint64(0)
var shareMsgs []*core.Message
var processedTxs [][]byte
for _, rawTx := range txs.Txs {
// decode the Tx
tx, err := app.txDecoder(rawTx)
tx, err := app.txConfig.TxDecoder()(rawTx)
if err != nil {
continue
}

// run basic validation on the transaction
err = tx.ValidateBasic()
if err != nil {
// don't do anything if the transaction doesn't contain a PayForMessage sdk.Msg
if !hasWirePayForMessage(tx) {
processedTxs = append(processedTxs, rawTx)
continue
}

// don't allow transactions with multiple messages to be ran
// only support transactions that contain a single sdk.Msg for now
if len(tx.GetMsgs()) != 1 {
continue
}

msg := tx.GetMsgs()[0]

// run basic validation on the msg
err = msg.ValidateBasic()
// run basic validation on the transaction
err = tx.ValidateBasic()
if err != nil {
continue
}

// quickly check the stated type of the message
if msg.Type() != types.TypeMsgPayforMessage {
// process and validate the message
coreMsg, signedTx, err := app.processMsg(msg)
if err != nil {
continue
}

// double check the actual type of the message
wireMsg, ok := msg.(*types.MsgWirePayForMessage)
if !ok {
// execute the tx in runTxModeDeliver mode (3)
// execution includes all validation checks burning fees
// currently, no fees are burned
_, _, err = app.BaseApp.TxRunner()(3, rawTx)
if err != nil {

continue
}

// todo(evan): this needs to turn the transaction into a SignedTransactionDataPayForMessage
// // discard the share commitments that won't be used
// var shareCommit types.ShareCommitAndSignature
// for _, commit := range wireMsg.MessageShareCommitment {
// if commit.K == app.SquareSize() {
// shareCommit = commit
// break
// }
// }
// increment the share counter by the number of shares taken by the message
sharesTaken := uint64(len(coreMsg.Data) / 256)
shareCounter += sharesTaken

// make sure to get rid of excess txs or do something with them
// if there are too many shares stop processing and return the transactions
// this is related to issues 67 and 77 of lazyledger-core
if shareCounter > squareSize {
break
}

// execute the tx in runTxModeDeliver mode (3)
// execution includes all validation checks burning fees
_, _, err = app.BaseApp.TxRunner()(3, rawTx)
// encode the processed tx
rawProcessedTx, err := app.appCodec.MarshalBinaryBare(signedTx)
if err != nil {
continue
}

// the message is valid and paid for, include it in the response
shareMsgs = append(
shareMsgs,
&core.Message{
NamespaceId: wireMsg.GetMessageNameSpaceId(),
Data: wireMsg.Message,
},
)
// add the message and tx to the output
shareMsgs = append(shareMsgs, &coreMsg)
processedTxs = append(processedTxs, rawProcessedTx)
}

// sort messages lexographically
sort.Slice(shareMsgs, func(i, j int) bool {
return bytes.Compare(shareMsgs[i].NamespaceId, shareMsgs[j].NamespaceId) < 0
})

return abci.ResponsePreprocessTxs{
Txs: txs.Txs,
Txs: processedTxs,
Messages: &core.Messages{MessagesList: shareMsgs},
}
}

func hasWirePayForMessage(tx sdk.Tx) bool {
for _, msg := range tx.GetMsgs() {
if msg.Type() == 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)
}

// run basic validation on the msg
err := wireMsg.ValidateBasic()
if err != nil {
return core.Message{}, nil, err
}

// 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
}
Loading

0 comments on commit 9afafdb

Please sign in to comment.