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

V.E PoC #1

Open
wants to merge 5 commits into
base: release/v0.50.x
Choose a base branch
from
Open

V.E PoC #1

wants to merge 5 commits into from

Conversation

Raneet10
Copy link
Owner

Description

PoC for using Side-txs with Vote Extensions


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title
  • added ! to the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • followed the guidelines for building modules
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • included comments for documenting Go code
  • updated the relevant documentation or specification
  • reviewed "Files changed" and left comments if necessary
  • run make lint and make test
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed ! in the type prefix if API or client breaking change
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic
  • reviewed API design and naming
  • reviewed documentation is accurate
  • reviewed tests and test coverage
  • manually tested (if applicable)

@github-actions

This comment has been minimized.

@Raneet10 Raneet10 changed the title Raneet10/comet poc V.E PoC Sep 15, 2023
}

var eventRecord types.EventRecord
k.cdc.Unmarshal(bz, &eventRecord)

Check warning

Code scanning / gosec

Errors unhandled. Warning

Errors unhandled.
simapp/abci.go Fixed Show fixed Hide fixed

// SendEventRecord defines an operation for updating the x/staking module
// parameters.
rpc SendEventRecord(MsgEventRecord) returns (MsgSendEventRecordResponse);
Copy link
Collaborator

Choose a reason for hiding this comment

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

How are you testing? Broadcasting the same event to all nodes? Otherwise behavior of extend vote may be non-deterministic.

Copy link
Owner Author

Choose a reason for hiding this comment

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

As discussed yesterday, a validator would be leveraging the CLI to broadcast the tx like so :
build/simd tx staking event --from cosmos1czfy9xfjzgphjjufmhfcxx2j7450qkmfuavs65 --keyring-backend=test --keyring-dir=.testnets/chain-YcCES5/node0/simcli --chain-id chain-YcCES5

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this the only case @Raneet10 (leveraging the CLI I mean)?

simapp/abci.go Outdated

_, err := rand.Read(buf)
// Fetch from buffer
eventRecord, err := h.app.StakingKeeper.GetEventRecordFromBuffer(ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the node didn't execute processProposal, will vote SKIP.

https://docs.cometbft.com/main/spec/abci/abci++_comet_expected_behavior.html

Could change the behavior to fill the buffer here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Note also that the me method is called for every round. Is there any situation in which nodes would want to update their votes?

And round numbers are not available here.

Copy link
Owner Author

@Raneet10 Raneet10 Sep 22, 2023

Choose a reason for hiding this comment

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

If the node didn't execute processProposal, will vote SKIP.

https://docs.cometbft.com/main/spec/abci/abci++_comet_expected_behavior.html

Could change the behavior to fill the buffer here.

That's a good point, noted.

Note also that the me method is called for every round. Is there any situation in which nodes would want to update their votes?

And round numbers are not available here.

Not sure which method you referred to here, but guessing that it's ExtendVote , we'd generally expect honest nodes to deterministically vote irrespective of the rounds but it might depend from module to module (would need to think of vulnerabilities and edge-cases per module here). We can of course have additional checks to ensure we don't get spammed with similar side-txs.

simapp/abci.go Outdated Show resolved Hide resolved
simapp/abci.go Outdated
if hasTwoThirdsSigs {
fmt.Println("PrepareProposal: INJECTING VEs!")

for _, v := range req.LocalLastCommit.Votes {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A malicious node could censor side transactions here and nodes executing processProposal would not have a means to detect it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Noted, we'll modify the approach in the updated PoC.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Hey @lasarojc , if the malicious node were to send empty or wrong VEs, would there be any way that the other nodes can detect it ? I guess they can query their local state and catch but is it possible to do it on the app level or will the Comet handle it ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

For CometBFT, the VE is just an a sequence of bytes. The sequence being empty is a valid case (the validator didn't have anything to add to the vote). Notice that an empty VE must still be signed.
The contents of the VE must make sense to the App and it is the app's job to verify it and reject it if is bogus.

// and reject the proposal in case we don't have a majority.
// A downside is liveness can get negatively affected in case of invalid VEs.
func (app *SimApp) NewProcessProposalHandler() sdk.ProcessProposalHandler {
return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does not verify if the side transactions were properly encoded, double proposed or indeed have a majority.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Good point and as mentioned above, we will update in the new PoC.

Copy link
Owner Author

Choose a reason for hiding this comment

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

The RequestProcessProposal.ProposedLastCommit does not seem to have ExtendedVoteInfo to check for majority. Fetching that from txs bytes may not be a good idea because of censorship/bad V.E data. What do you think, am I missing anything?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Have those checks been implemented?

Copy link
Collaborator

Choose a reason for hiding this comment

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

the API does not deliver the extended commit info in process proposal. The recommended approach for now is to extract the set of VE from the special transaction in txs.
In that sense, the proposer will be able to sensor some VE, but must include at least the 2f+1 it used.

simapp/abci.go Outdated Show resolved Hide resolved

// SendEventRecord defines an operation for updating the x/staking module
// parameters.
rpc SendEventRecord(MsgEventRecord) returns (MsgSendEventRecordResponse);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this the only case @Raneet10 (leveraging the CLI I mean)?

6. FinalizeBlock -> Finalize and execute txs.
7. CommitBlock -> Self explanatory.
*/

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Raneet10 is this the confirmed flow?
@VAIBHAVJINDAL3012 can you add your concerns here wrt "sepcial tx"?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, Encoding the VE and putting it in a block is a special tx. I meant the same.

// and reject the proposal in case we don't have a majority.
// A downside is liveness can get negatively affected in case of invalid VEs.
func (app *SimApp) NewProcessProposalHandler() sdk.ProcessProposalHandler {
return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Have those checks been implemented?

simapp/abci.go Outdated
var eventData *stakingtypes.EventRecord
for _, v := range req.Txs {
// Have a way to segregate b/w signed VEs and regular txs. Assuming for VEs, byte length would be 8
if len(v) >= 8 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this always the case? Can other txs have the same length?

Copy link
Owner Author

Choose a reason for hiding this comment

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

The point here is that we will need a distinct way of having separation between normal txs and V.Es. That's why the comment :
// Have a way to segregate b/w signed VEs and regular txs. Assuming for VEs, byte length would be 8

// PreFinalizeBlock -> Extract VEs from previous block and persist in DB.
func (app *SimApp) NewPreFinalizeBlockHookHandler() sdk.PreFinalizeBlockHook {
return func(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
if req.Height > 5 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why 5?

Copy link
Owner Author

Choose a reason for hiding this comment

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

The V.E. in the devnet I was testing were enabled from 5.

}

if len(vote.ExtensionSignature) == 0 {
return fmt.Errorf("vote extensions enabled; received empty vote extension signature at height %d", currentHeight)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does it need to be error? Can we have no vote extensions for some txs (not side-txs)?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yes we can , but they have to be signed. cc: @lasarojc

baseapp/abci.go Outdated
Comment on lines 400 to 406
Time: req.Time,
ProposerAddress: req.ProposerAddress,
NextValidatorsHash: req.NextValidatorsHash,
AppHash: app.LastCommitID().Hash,
}
app.setState(execModePrepareProposal, header)

Choose a reason for hiding this comment

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

Change potentially affects state.

Call sequence:

(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).PrepareProposal (baseapp/abci.go:390)

@lasarojc
Copy link
Collaborator

lasarojc commented Nov 8, 2023

Yes we can , but they have to be signed. cc: @lasarojc

Once enabled, VE must be included on every round. They may be empty, though.

@@ -172,3 +179,161 @@ func (k Keeper) GetValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate

return valUpdates.Updates, nil
}

// Copied from baseapp/abci_utils.go
Copy link
Collaborator

@lasarojc lasarojc Nov 9, 2023

Choose a reason for hiding this comment

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

This function has been updated by the SDK team to address issue 17518 and the changes need to be reflected here as well.

Copy link
Owner Author

Choose a reason for hiding this comment

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

// A downside is liveness can get negatively affected.
func (app *SimApp) NewProcessProposalHandler() sdk.ProcessProposalHandler {
return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
if req.Height > 5 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

As in the the staking/keeper.go helper, use

    cp := ctx.ConsensusParams()
	extsEnabled := cp.Abci != nil && currentHeight >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0

Copy link
Owner Author

Choose a reason for hiding this comment

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

continue
}

if ve.Result == Vote_YES {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A single YES is enough to persist the VE/execute the SideTx. Should it instead tally the votes to decide on executing or not?

Copy link
Owner Author

Choose a reason for hiding this comment

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

@lasarojc lasarojc changed the base branch from raneet10/temp-pr-branch to release/v0.50.x November 10, 2023 12:41
for _, msg := range msgs {
switch msg.(type) {
// TODO: Redirect ExtendVote calls to individual module
case *stakingtypes.MsgEventRecord:
Copy link
Collaborator

@lasarojc lasarojc Nov 10, 2023

Choose a reason for hiding this comment

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

Note for when implementing: handle or forbid having multiple MsgEventRecord/SideTx in the same block.

Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the Stale label Dec 11, 2023
@github-actions github-actions bot closed this Dec 16, 2023
@Raneet10 Raneet10 reopened this Dec 18, 2023
if ve.Result == Vote_YES {
if err := json.Unmarshal(ve.Data, &eventData); err == nil {
fmt.Println("PERSISTING VE DATA!", "HEIGHT: ", ctx.BlockHeight())
app.StakingKeeper.SetEventRecord(ctx, *eventData)

Check warning

Code scanning / gosec

Errors unhandled. Warning

Errors unhandled.
@github-actions github-actions bot removed the Stale label Dec 19, 2023
Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the Stale label Jan 18, 2024
@github-actions github-actions bot closed this Jan 22, 2024
@marcello33 marcello33 reopened this Feb 7, 2024
@github-actions github-actions bot removed the Stale label Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment