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

Implement PreprocessTxs #21

Merged
merged 10 commits into from
Feb 23, 2021
Merged

Implement PreprocessTxs #21

merged 10 commits into from
Feb 23, 2021

Conversation

evan-forbes
Copy link
Member

@evan-forbes evan-forbes commented Feb 6, 2021

Description

This PR implements the new PreprocessTxs ABCI method, along with a refactor of the WirePayForMessage message that PreprocessTxs acts upon.

Notes: a slightly modified branch of the cosmos-sdk is required.

TODO

  • Refactor PayForMessage -> WirePayForMessage
  • Remove Fees
  • Incorporate into the rest of the sdk
  • Finish testing
  • debug CI failures
  • squash commits

closes: tendermint/spec#22


  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

proto/lazyledgerapp/tx.proto Outdated Show resolved Hide resolved
@liamsi
Copy link
Member

liamsi commented Feb 14, 2021

I've skimmed through the code and it looks pretty complete and good 👍🏼 Can you track the changes you plan to incorporate in a list of todos in the opening comment? It would a reviewer understand what parts are going to change (if any).

the basic layout is finished but there are a few design decisions that need to be made before finishing this first draft.

If there are still some open design decisions, let's discuss them here, or in the corresponding issue.

@evan-forbes evan-forbes reopened this Feb 16, 2021
@evan-forbes
Copy link
Member Author

whoops, accidentally hit tab 3x + enter to close the PR...

The first draft testing is at a "good-enough-to-start-reviewing" stage, but there will definitely need to be some additions in the near future. I'm going to mark this ready for review, and start working on the CI issues.

Notes:

  • As discussed earlier, square size is currently hard coded.
  • Some of the naming can be confusing, as this draft follows the naming conventions introduced in the spec, ABCI, lazyledger-core, and the sdk. Specifically, there are a lot of things that use Message to describe themselves, but the sdk's concept of a Message is quite different from that of the spec and lazyledger-core
  • The entire public key is currently included in each WirePayForMessage 😬 We should be able to change this by verifying the signature of the SignedTransactionDataPayForMessage in an antehandler, instead of the the ValidateBasic method.

@evan-forbes evan-forbes marked this pull request as ready for review February 16, 2021 23:05
@codecov-io
Copy link

codecov-io commented Feb 17, 2021

Codecov Report

❗ No coverage uploaded for pull request base (master@0e72863). Click here to learn what that means.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master      tendermint/spec#21   +/-   ##
=========================================
  Coverage          ?   15.04%           
=========================================
  Files             ?       14           
  Lines             ?     1888           
  Branches          ?        0           
=========================================
  Hits              ?      284           
  Misses            ?     1588           
  Partials          ?       16           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0e72863...3578791. Read the comment docs.

@liamsi
Copy link
Member

liamsi commented Feb 17, 2021

Specifically, there are a lot of things that use Message to describe themselves, but the sdk's concept of a Message is quite different from that of the spec and lazyledger-core

Yeah, maybe the package name can help to differentiate both? For example would sdk.Message and lazyledger.Message be clear enough? As an alternative, we can rename "our" Messages to sth else. Here and in the spec maybe (certainly out of scope for this PR).

The entire public key is currently included in each WirePayForMessage 😬 We should be able to change this by verifying the signature of the SignedTransactionDataPayForMessage in an antehandler, instead of the the ValidateBasic method.

Sounds like this should be tracked in an issue!

Txs: processedTxs,
Messages: &core.Messages{MessagesList: shareMsgs},
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Note that in PreProcess the app also needs to track the (original / mempool) Tx that were processed, s.t. on re-check it can tell ll-core to remove them from the mempool.

This has the caveat that currently only the proposer will call preprocess: the app needs to know if a proposed block didn't make it through consensus (e.g. because of timeouts) and other nodes to be able to evict their mempools too...
@adlerjohn you and I need to think about, too.

Copy link
Member

Choose a reason for hiding this comment

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

Not necessarily? Conflicting transactions (which includes duplicates in the mempool) between the block and the mempool are removed with CheckTx, so PreProcess doesn't technically need to do that?

Copy link
Member

@liamsi liamsi Feb 19, 2021

Choose a reason for hiding this comment

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

Looks like I'm confused about this again, then 🤔
How does the app know which (mempool) Tx made it into the block if the app doesn't track this?

Sure, it "sees" the Tx during each deliver Tx but only the already processed which are different from the mempool Tx potenially.

Copy link
Member

Choose a reason for hiding this comment

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

Leaving this here for reference (quoting @adlerjohn):

You don't need to know which txs from the mempool were included in a block, you only need to know which mempool transactions conflict with the ones in a block.
So running CheckTx of all txs in the mempool after you commit a block is sufficient.
If the tx in the mempool conflicts. It'll have the same nonce and sender.

So my concern was the mapping between mempool tx <-> block tx but as mentioned by John that mapping is essentially there via nonce and sender.

app/abci.go Outdated Show resolved Hide resolved
app/abci.go Outdated Show resolved Hide resolved
app/abci.go Outdated Show resolved Hide resolved
app/abci.go Outdated Show resolved Hide resolved
Copy link
Member

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

I've added a few minor comments. This is almost good to go.

I'll @ John at some of the parts of the code, where I think either his input would be valuable, or, where he should at least be aware of the implementation details (simply that he is aware).

Comment on lines 196 to 207
// CreateCommit generates the commit bytes for a given message, namespace, and
// squaresize using a namespace merkle tree and the rules described at
// https://github.com/lazyledger/lazyledger-specs/blob/master/rationale/message_block_layout.md#non-interactive-default-rules
func CreateCommit(k uint64, namespace, message []byte) ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

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

@adlerjohn
Copy link
Member

For posterity, tendermint/spec#28 tracks removing redundant pubkey in WirePayForMessage.

app/abci.go Outdated Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Outdated Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Outdated Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Outdated Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Outdated Show resolved Hide resolved
x/lazyledgerapp/types/payformessage.go Outdated Show resolved Hide resolved
adlerjohn
adlerjohn previously approved these changes Feb 20, 2021
Copy link
Member

@adlerjohn adlerjohn left a comment

Choose a reason for hiding this comment

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

Changes look good to me

liamsi
liamsi previously approved these changes Feb 21, 2021
Copy link
Member

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

Same here 👍🏼 Great work @evan-forbes 🚀

@evan-forbes
Copy link
Member Author

I forgot to make a PR for the change needed in the cosmos-sdk that needs to be merged before this can be merged.

fix bug left from sdk that stops proto-gen from working properly

add access to the tx encoder and decoder

 add all the basic proto messages needed for PayForMessage

run make protoc-gen
remove placeholder type that causes a compilation error

lazyledgerapp: add pay for message to the handler

added verification methods to payformessage

connected payformessage to rest of sdk

refactored preprocessing

update the branch of the sdk that allows for running tx outside of DeliverTx

proto: use the users public key instead their address

keeper: remove burning fees

verify signatures using public key

added notes for next todo

remove compile time error

proto: remove enums that are not going to be used for the mvp

proto: added tx type for pay for message

lazyledgerapp/types: fleshed out and finalized PayForMessage types
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
…entation, remove redundant ValidateBasicChecks

payformessage: use constants and explanation of panic

use namespace and share constants from ll-core

app: added comments to constant copy and pasted from the sdk

review feedback: switch to using constant for namespaceID size

review feedback: change name of GetCommitSignBytes to GetCommitmentSignBytes

review feedback: use the max square size from lazyledger-core instead of 64

fix doc typo

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

review feedback: docs update for the public key method

switch to using constants in the docs too

Update x/lazyledgerapp/types/payformessage.go

Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com>

switch to updated PR for cosmos-sdk change and update deps
…hare commitment instead of not allowing chains

update failing test to new expected result now that the square size is 128 instead of 64
app/abci.go Outdated
Comment on lines 67 to 73
// execute the tx in runTxModeDeliver mode (3)
// execution includes all validation checks burning fees
// currently, no fees are burned
_, _, err = app.BaseApp.TxRunner()(runTxModeDeliver, rawTx)
if err != nil {
continue
}
Copy link
Member

Choose a reason for hiding this comment

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

Actually, didn't we say to not execute the Tx immediately until we add explicit ABCI methods for that purpose?
See: https://github.com/tendermint/spec/issues/208#issuecomment-721158558
and tendermint/spec#254

Also, if run the Tx during preprocess, won't that app still try to execute the Tx from the previous block during, too?

Copy link
Member Author

@evan-forbes evan-forbes Feb 22, 2021

Choose a reason for hiding this comment

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

The sdk uses the runTx method to run stateful checks and execute any state changing transactions. While the runTxModeDeliver (signal to keep changes to the state) flag is being passed to runTx, the handler doesn't do anything (see below).

Also, if run the Tx during preprocess, won't that app still try to execute the Tx from the previous block during, too?

Under the hood, there are two distinct transactions, so we can specify which state needs to change during PreprocessTxs and which need to change during DeliverTx. There is MsgWirePayForMessage, which is passed to PreprocessTxs and is being pushed through runTx during PreprocessTxs. There's also SignedTransactionDataPayForMessage, which is derived from MsgWirePayForMessage as described in the spec, which is not being pushed through runTx until DeliverTx and is instead returned by PreprocessTxs. Each is ran separately, and each has its own signature.

The actual actions that occur during transaction execution are dictated in the module's Keeper. We can look at what the handler for MsgWirePayForMessage does here, which is nothing atm. There is not currently a handler for SignedTransactionDataPayForMessage, which will throw an error if it is ran later via DeliverTx. While throwing an error if SignedTransactionDataPayForMessage is passed to DeliverTx was intentional, I think having a handler for it that always throws an error would be more explicit. actually, this shouldn't throw an error! I'll include a handler that doesn't do anything.

This brings up that I should have better documentation for all of this "under-the-hood" stuff, even if some of it is temporary. Where would the best place for that be? I was planning on making a full blown integration test later #24, but this might need to be done in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, the runTxModeDeliver sounds like it will actually deliver the Txs. That is what confused me. Thanks for clarifying.

This brings up that I should have better documentation for all of this "under-the-hood" stuff, even if some of it is temporary. Where would the best place for that be?

This brings us back to that ADR discussion. Maybe we should document this kind of decision in light-weight ADRs that either precede or accompany PRs. And yes, (integration) tests would be a great way to increase confidence that everything behaves as we expect.

Copy link
Member

Choose a reason for hiding this comment

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

After talking with @evan-forbes in person, we've decided to drop the runTx call and rely soley on checkTx for now. We will still have to take care of this in the future but we can likely tackle this together with immediate execution (which, as far as I understand is required for fee burning anyway).

use the latest version the lazyledger/cosmos-sdk instead of the modified version
fix SignedTransactionDataPayForMessage generation so that padding is added to the message if necessary

change name of CreateCommit to CreateCommitment
@evan-forbes
Copy link
Member Author

a few things have been changed:

  • a new PreprocessTxs test has been added,
  • the handler for SignedTransactionDataPayForMessage has been added
  • a bug fix that ensures padding is added to the message before it is signed
  • runTx has been removed from PreprocessTxs
  • updated to the latest version of the sdk as opposed to using the branch that had runTx exported

remove extra redundant check
liamsi
liamsi previously approved these changes Feb 23, 2021
Copy link
Member

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

Left a minor nit. LGTM! Great work!

Please refrain from force pushing to already reviewed branches as it makes it difficult to know what was modified in the mean time.

Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com>
Copy link
Member

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

👌

@evan-forbes evan-forbes merged commit 1e64b39 into master Feb 23, 2021
@evan-forbes evan-forbes deleted the evan/PayForMsg-from-scractch branch February 23, 2021 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clarification on "The condition that assumes a reception of X messages..."
4 participants