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

Include ValidatorIndex in the dispute statement #961

Open
rphmeier opened this issue Jul 10, 2021 · 3 comments
Open

Include ValidatorIndex in the dispute statement #961

rphmeier opened this issue Jul 10, 2021 · 3 comments
Assignees
Labels
I4-refactor Code needs refactoring.

Comments

@rphmeier
Copy link
Contributor

rphmeier commented Jul 10, 2021

paritytech/polkadot#3348 (comment)

@eskimor Has been pushing strongly to include ValidatorIndex in the dispute statement. Our major disagreement has been over the fact that the SignedDisputeStatement can't actually check whether the public key corresponds to the session info.

I propose that we introduce a type in the vein of std::panic::AssertUnwindSafe for the purpose of encouraging that the caller to be very explicit and very careful about checking the index.

/// While this type does no checking on its own, it's a good way to force the caller to assert that they have indeed checked
/// that the associated public key does indeed correspond to the validator index at the given session.
AssertSessionValidator(SessionIndex, ValidatorPublic, ValidatorIndex);

Instead of wrapping these types independently, I think that SignedDisputeStatement should wrap the AssertSessionValidator so the constructors of the function have to explicitly accept it. The API of SignedDisputeSession should have an accessor to the AssertSessionValidator to be used as statement.validator().session(), statement.validator().id(), and statement.validator().index().

This makes it clear to the receiver is a SignedDisputeStatement that they are dealing with an asserted-valid type and thus will make it more apparent that receiving code is reasonably foregoing expensive validator-set membership checks. Although the API is clunkier than statement.validator_index(), I would much rather read code a year from now where I'd ask "what's that validator() call about and why is this not verifying the index is correct?" instead of "why the f*** isn't this verifying the index??".

@eskimor
Copy link
Member

eskimor commented Jun 16, 2022

Revisiting this again (as I have to touch relevant code). To me the safest approach is still to only include the ValidatorIndex in the signed data, together with the SessionIndex. This way the only way to actually check the signature is to look up the ValidatorIndex in some session. While in theory the checker could use the wrong session, the SessionIndex is part of the signed data, so the checking code would need to use the correct index for the signing context in order to verify correctly, but the wrong index for looking up the session.

Looking at the CheckedSigned::try_from_unchecked signature:

	pub fn try_from_unchecked<H: Encode>(
		unchecked: UncheckedSigned<Payload, RealPayload>,
		context: &SigningContext<H>,
		key: &ValidatorId,
	) -> Result<CheckedSigned> {

we indeed leave unnecessary room for error here. I would propose to change it to
the following:

impl CheckedSigned {
  pub fn try_from_unchecked(
    unchecked: UncheckedSigned,
    relay_parent: Hash,
    session_info: LookedUpSessionInfo,
   ) -> Result<CheckedSigned> {
   }
}

where LookedUpSessionInfo would look like this:

struct LookedUpSessionInfo {
  index: SessionIndex,
  info: SessionInfo,
}

There will likely only be a single code in the source tree, taking a
SessionIndex and returning LookedUpSessionInfo with that index. Room for err
would be close to zero and by above signature of try_from_unchecked we have a
guarantee that the same index is used for the signed payload. In theory we could
make the LookedUpSessionInfo type protected to actually have even stronger
guarantees. In practice this does not work without unsafe or other hacks as
the type would need to live in primitives, while the lookup code depends on
primitives, so we would get a cycle. Still to mess this up, you almost have to
be a malicious contributor with collaborating reviewers.

eskimor referenced this issue in paritytech/polkadot Jun 16, 2022
into the dispute coordinator. This also gets rid of a redundant
signature check. Both should have some impact on backing performance.

Reasoning (aka why this is fine):

For the signature check: As mentioned, it is a redundant check. The
signature has already been checked at this point. This is even made
obvious by the used types. The smart constructor is not perfect as
discussed [here](https://github.com/paritytech/polkadot/issues/3455),
but still a reasonable security.

For not importing to the dispute-coordinator: This should be fine as the
dispute coordinator does scrape backing votes from chain. This suffices
in practice as a super majority of validators must have seen a backing
fork in order for a candidate to get included and only included
candidates pose a threat to our system. The import from chain is
preferable over direct import of backing votes for two reasons:

1. The import is batched, greatly improving import performance. (All
   backing votes for a candidate are imported with a single import.)
2. We do less work in general as not every candidate for which
   statements are gossiped might actually make it on a chain. The
   dispute coordinator as with the previous implementation would still
   import and keep those votes around for six sessions.

While redundancy is good for reliability in the event of bugs, this also
comes at a non negible cost. The dispute-coordinator right now is the
subsystem with the highest load, despite the fact that it should not be
doing much during mormal operation.

We'll see on Versi how much of a performance improvement this PR
provides.
eskimor referenced this issue in paritytech/polkadot Jun 16, 2022
into the dispute coordinator. This also gets rid of a redundant
signature check. Both should have some impact on backing performance.
In general this PR should make us scale better in the number of parachains.

Reasoning (aka why this is fine):

For the signature check: As mentioned, it is a redundant check. The
signature has already been checked at this point. This is even made
obvious by the used types. The smart constructor is not perfect as
discussed [here](https://github.com/paritytech/polkadot/issues/3455),
but is still a reasonable security.

For not importing to the dispute-coordinator: This should be good as the
dispute coordinator does scrape backing votes from chain. This suffices
in practice as a super majority of validators must have seen a backing
fork in order for a candidate to get included and only included
candidates pose a threat to our system. The import from chain is
preferable over direct import of backing votes for two reasons:

1. The import is batched, greatly improving import performance. All
   backing votes for a candidate are imported with a single import.
   And indeed we were able to see in metrics that importing votes
   from chain is fast.
2. We do less work in general as not every candidate for which
   statements are gossiped might actually make it on a chain. The
   dispute coordinator as with the current implementation would still
   import and keep those votes around for six sessions.

While redundancy is good for reliability in the event of bugs, this also
comes at a non negligible cost. The dispute-coordinator right now is the
subsystem with the highest load, despite the fact that it should not be
doing much during mormal operation and it is only getting worse
with more parachains as the load is a direct function of the number of statements.

We'll see on Versi how much of a performance improvement this PR
@rphmeier
Copy link
Contributor Author

rphmeier commented Jun 19, 2022

We shouldn't put the entire SessionInfo into the signed data type because it's relatively heavy and we need to pass around thousands of signed messages. The AssertSessionValidator datatype seems like it does roughly the same thing otherwise.

@eskimor
Copy link
Member

eskimor commented Jun 20, 2022

Oh yeah, I wasn't suggesting that. Just that we pass a reference to the SessionInfo to the checking function, so it can pick the right validator key for signature checking based on the passed SessionIndex which it will also use in the SigningContext.

Reading your text again, I guess we basically mean the same thing. (I also initially read your idea, that you want to put that AssertSessionValidator into the signed type 😆 ).

So if I got this right, instead of passing in the SessionInfo you would pass in the AssertSessionValidator type into the checking function. Both would result in doing the wrong thing becoming bluntly obvious and really hard to do by accident.

eskimor referenced this issue in paritytech/polkadot Aug 16, 2022
* Don't import backing statements directly

into the dispute coordinator. This also gets rid of a redundant
signature check. Both should have some impact on backing performance.
In general this PR should make us scale better in the number of parachains.

Reasoning (aka why this is fine):

For the signature check: As mentioned, it is a redundant check. The
signature has already been checked at this point. This is even made
obvious by the used types. The smart constructor is not perfect as
discussed [here](https://github.com/paritytech/polkadot/issues/3455),
but is still a reasonable security.

For not importing to the dispute-coordinator: This should be good as the
dispute coordinator does scrape backing votes from chain. This suffices
in practice as a super majority of validators must have seen a backing
fork in order for a candidate to get included and only included
candidates pose a threat to our system. The import from chain is
preferable over direct import of backing votes for two reasons:

1. The import is batched, greatly improving import performance. All
   backing votes for a candidate are imported with a single import.
   And indeed we were able to see in metrics that importing votes
   from chain is fast.
2. We do less work in general as not every candidate for which
   statements are gossiped might actually make it on a chain. The
   dispute coordinator as with the current implementation would still
   import and keep those votes around for six sessions.

While redundancy is good for reliability in the event of bugs, this also
comes at a non negligible cost. The dispute-coordinator right now is the
subsystem with the highest load, despite the fact that it should not be
doing much during mormal operation and it is only getting worse
with more parachains as the load is a direct function of the number of statements.

We'll see on Versi how much of a performance improvement this PR

* Get rid of dead code.

* Dont send approval vote

* Make it pass CI

* Bring back tests for fixing them later.

* Explicit signature check.

* Resurrect approval-voting tests (not fixed yet)

* Send out approval votes in dispute-distribution.

Use BTreeMap for ordered dispute votes.

* Bring back an important warning.

* Fix approval voting tests.

* Don't send out dispute message on import + test

+ Some cleanup.

* Guide changes.

Note that the introduced complexity is actually redundant.

* WIP: guide changes.

* Finish guide changes about dispute-coordinator

conceputally. Requires more proof read still.

Also removed obsolete implementation details, where the code is better
suited as the source of truth.

* Finish guide changes for now.

* Remove own approval vote import logic.

* Implement logic for retrieving approval-votes

into approval-voting and approval-distribution subsystems.

* Update roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md

Co-authored-by: asynchronous rob <rphmeier@gmail.com>

* Review feedback.

In particular: Add note about disputes of non included candidates.

* Incorporate Review Remarks

* Get rid of superfluous space.

* Tidy up import logic a bit.

Logical vote import is now separated, making the code more readable and
maintainable.

Also: Accept import if there is at least one invalid signer that has not
exceeded its spam slots, instead of requiring all of them to not exceed
their limits. This is more correct and a preparation for vote batching.

* We don't need/have empty imports.

* Fix tests and bugs.

* Remove error prone redundancy.

* Import approval votes on dispute initiated/concluded.

* Add test for approval vote import.

* Make guide checker happy (hopefully)

* Another sanity check + better logs.

* Reasoning about boundedness.

* Use `CandidateIndex` as opposed to `CoreIndex`.

* Remove redundant import.

* Review remarks.

* Add metric for calls to request signatures

* More review remarks.

* Add metric on imported approval votes.

* Include candidate hash in logs.

* More trace log

* Break cycle.

* Add some tracing.

* Cleanup allowed messages.

* fmt

* Tracing + timeout for get inherent data.

* Better error.

* Break cycle in all places.

* Clarified comment some more.

* Typo.

* Break cycle approval-distribution - approval-voting.

Co-authored-by: asynchronous rob <rphmeier@gmail.com>
@tdimitrov tdimitrov assigned tdimitrov and unassigned eskimor May 4, 2023
@Sophia-Gold Sophia-Gold transferred this issue from paritytech/polkadot Aug 24, 2023
@the-right-joyce the-right-joyce added I4-refactor Code needs refactoring. and removed I8-refactor labels Aug 25, 2023
claravanstaden added a commit to Snowfork/polkadot-sdk that referenced this issue Dec 8, 2023
* Support reserve deposit for control operations

* Pay as agent_owner

* Add AgentAccountDescription converter

* Revamp smoke test config fee for control operations

* Add SovereignAccountOf to runtime config

* Fix format

* More refactor

* Configurable base fee plus static per-operation fee multiplier

* Update smoke test accordingly

* Update cumulus

* Fix format

* Remove call index from the cross-chain interface

* Update test fixture

* Fix format

* Configurable dispatch_gas

* Update relayer

* Refactor to charge fee for outbound commands

* More refactor

* Update cargo.lock

* Chore

* Fix clippy

* Chore format

* Update cumulus

* Reward message relayer

* Fix smoke tests

* Set default dispatch gas

* Fix for origin of control operations & Charge fee without gas cost

* Update parachain/pallets/outbound-queue/src/lib.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Update parachain/pallets/outbound-queue/src/lib.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Specify the fee for xcm export & upfront charge for create_agent only

* Remove deprecated config

* Fix format

* Set decent default for outbound configs

* Make create-channel upfront charged & start template relayer for other non-charged control commands like TransferNativeFromAgent

* Disable base fee for sudo operations

* Update gas cost

* Fix cargo tarpaulin

* Update RegisterCallIndex as runtime const

* Fix cargo tarpaulin

* Update cumulus

* Update cumulus

* Add OutboundFeeConfig

* Fund template sovereign account

* Rename as agent_location

* Fix clippy

* Validate ticket with gas check

* Move the charge logic to control pallet & More refactor

* Fix clippy

* Disable format temporarily for less distraction

* Refactor estimate by message

* More refactor

* Fix clippy

* Introduce VersionedMessageToXcmConverter

* Fix clippy

* More cleanup

* Fix test & Remove format

* Add estimate rpc

* Estimate by command index & Add smoke test accordingly

* Fix upgrade test

* Initialize with more funds & Add script for fund

* Update contracts/test/Gateway.t.sol

Co-authored-by: Clara van Staden <claravanstaden64@gmail.com>

* Rename event as OutboundFeeConfigUpdated

* For comment

* Chore

* Refactor with structured OriginInfo

* Clean derive macros

* Leave enough space for upgrade

* Runtime api for compute_fee_reward

* Use TreasuryAccount more specific

* Improve comments

* Improve smoke test

* Update smoketest/src/helper.rs

Co-authored-by: Clara van Staden <claravanstaden64@gmail.com>

* Update smoketest/src/helper.rs

Co-authored-by: Clara van Staden <claravanstaden64@gmail.com>

* Some cleanup

* Update cumulus

* Test for fee with config changed

* A thin shell wrapper funding agent

* More tests

* foo

* foo

* fix tests

* compilation works

* Update cumulus

* improve benchmarks

* fix benchmarks

* update cumulus

* fix clippy errors

* Update Cargo.lock

* update cumulus

* Remove obsolete fee estimation code

* Use full polkadot repository URL in Cargo.toml

* Update cumulus fix for smoke test

* Fix format

* Introduce VersionedMessageToXcmConverter

* Fix xcm instruction

* Chore

* remove relayers for template node

* Improve the implementation of the control pallet

* fix broken bindings generator for smoketests

* update cumulus submodule

* Update benchmarks

* Fix clippy

* Cleanup

* Revert "remove relayers for template node"

This reverts commit 2a9633ba2f688021a7bb59f95d7d48fbf20c302f.

* Fix agent id

* Update inbound MessageConverter

* Add runtime api for generating agent ids

* Improve benchmarking code

* Fix for smoke test to create agent

* Update cumulus

* mark some config items as pallet constants

* Some polish

* Polish

* Minor improvements to reward logic in Gateway

* Improve Gateway tests

* update cumulus submodule

* Fix convert

---------

Co-authored-by: Vincent Geddes <vincent@snowfork.com>
Co-authored-by: Clara van Staden <claravanstaden64@gmail.com>
Co-authored-by: Vincent Geddes <vincent.geddes@hey.com>
helin6 pushed a commit to boolnetwork/polkadot-sdk that referenced this issue Feb 5, 2024
…h#961)

* pad input if too short

* pad input in modexp

* pad all input fields + fix wrong test

* fix modexp gas cost

* remove dbg!

* remove redundant arg + import vec!

* use copy_from_slice

* clippy

* clippy
bkchr pushed a commit that referenced this issue Apr 10, 2024
* Bump Rococo's spec_version

* Use dev node for Rococo helper script

* Add helper scripts for relaying Rococo<>Wococo headers

* Change Wococo<>Rococo scripts to use Alice for initialization

* Add Wococo node helper script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I4-refactor Code needs refactoring.
Projects
Status: Backlog
Development

No branches or pull requests

4 participants