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

Voting power and delegation state query #3971

Closed
JimLarson opened this issue Oct 13, 2021 · 10 comments
Closed

Voting power and delegation state query #3971

JimLarson opened this issue Oct 13, 2021 · 10 comments
Assignees
Labels
cosmic-swingset package: cosmic-swingset enhancement New feature or request Governance Governance needs-design
Milestone

Comments

@JimLarson
Copy link
Contributor

What is the Problem Being Solved?

We want to have elections based on delegated staking tokens, with validators being able to vote the tokens delegated to them as a proxy, unless the delegator wishes to vote explicitly. Various inconsistencies can result if the staking state is measured at different times for different participants, and it's impractical/undesirable to prohibit staking changes for an extended period of time.

We'd also like the solution to be relatively simple to implement and use.

Description of the Design

Downcall from JS to Cosmos specifying an array of validator addresses and an array of delegator addresses.

Response message gives:

  • For each mentioned validator, the total number of staking tokens delegated to them.
  • For each mentioned delegator:
    • Their delegations to the mentioned validators, each delegation is a validator and an amount
    • The total amount delegated to unmentioned validators
  • A tag which will eventually hold the staking epoch, but will initially hold the current block height
  • In the response, delegators and validators can be referenced by index in the request, rather than by address, to save space.

Requests can be made partway through voting to get early partial results, knowing that votes and strengths might change before the end.

The degenerate case of asking for info about a single address can be used to pre-qualify for voting or for other uses.

JS API TBD

Security Considerations

Taking staking data at a single point in time avoids various anomalies and opportunities for double-counting.

Requesting and returning all in a batch has a vulnerability in message size. By design we minimize the size of the response, but it still scales with the number of voters in an election. When epoched staking is implemented and integrated, the staking state will be stable long enough to read a consistent snapshot of the data via repeated calls, with the returned epoch tag enabling detection of an epoch boundary.

Test Plan

Unit tests with mocked-out staking state.

Eventually need end-to-end integration tests with governance and real staking commands.

@JimLarson JimLarson added enhancement New feature or request needs-design Governance Governance labels Oct 13, 2021
@JimLarson JimLarson self-assigned this Oct 13, 2021
@JimLarson
Copy link
Contributor Author

CC @Chris-Hibbert @dckc @michaelfig

@JimLarson
Copy link
Contributor Author

See #3969 for complementary changes to the governance logic.

@JimLarson
Copy link
Contributor Author

See #3969 for the complementary Javascript side of things. See #3788 for attestation contracts.

@JimLarson
Copy link
Contributor Author

Options for the bridge response message. Though we have some longer-term workarounds, I am concerned about cardinality (number of voters and size of message) in the medium term. We can trim down the staking state by omitting or aggregating state not related to the specified voters, but there are some small-integer-multiple differences in how to express the data.

Consider the following options for responding to a request message like (addresses are much longer in reality):

{
  "type": "LIEN_GET_STAKING", 
  "validators": ["val123456", "val234567", "val345678", ...],
  "delegators": ["acc123456", "acc234567", "acc345678", ...]
}

Option 1: Full format:

{
  "epoch_tag": "block98765",
  "validators": [
    { "validator_address": "val123456", "tokens": 982734 },
    { "validator_address": "val234567", "tokens": 28734 },
    { "validator_address": "val345678", "tokens": 173455 },
    ...
  ],
  "delegator_states": [
    {
      "delegator_address": "acc123456",
      "delegations": [
        { "validator_address": "val234567", "tokens": 498234 },
        { "validator_address": "val345678", "tokens": 12358 },
        ...
      ],
      "other_delegations": 28394
    },
    {
      "delegator_address": "acc234567",
      "delegations: [
        { "validator_address": "val123456", "tokens": 18436 },
        ...
      ],
      "other_delegations": 368548734
    },
    ...
  ]
}

Option 2: Compact format - addresses omitted by position or indexing:

{
  "epoch_tag": "block98765",
  "validator_tokens": [982734, 28734, 173455, ...],
  "delegator_states": [
    {
      "delegations": [
        { "validator_index": 2, "tokens": 498234 },
        { "validator_index": 3, "tokens": 12358 },
        ...
      ],
      "other_delegations": 28394
    },
    {
      "delegations: [
        { "validator_index": 1, "tokens": 18436 },
        ...
      ],
      "other_delegations": 368548734
    },
    ...
  ]
}

Option 3: Compact-vector - change array-of-objects into object-of-arrays:

{
  "epoch_tag": "block98765",
  "validator_tokens": [982734, 28734, 173455, ...],
  "delegator_states": [
    {
      "validator_indexes": [2, 3, ...],
      "delegation_tokens": [498234, 12358, ...],
      "other_delegations": 28394
    },
    {
      "validator_indexes": [1, ...],
      "delegation_tokens": [18436, ...],
      "other_delegations": 368548734
    },
    ...
  ]
}

My current preference is Option 2 - no need to retransmit the bulky addresses. Option 3 seems like a step too far - but on the other hand we're already needing to correlate different arrays as part of the compaction.

@dckc
Copy link
Member

dckc commented Oct 14, 2021

Option 3: Compact-vector looks familiar from life science research datasets in dataframes in R, pandas, etc. It would work for me.

@michaelfig
Copy link
Member

2 or 3 are both good, with my preference also being 3, but a few nits (probably you don't really care about these quite yet):

  • Please also return a top-level "denom": "ubld"
  • consider shortening some of the bulky repeated property names
  • please use "value" instead of "tokens"
  • each "value" should be an sdk.Int which serialises to a JSON string, not a JSON number.

@JimLarson
Copy link
Contributor Author

Ah, yes, I was implementing the token quantities as sdk.Int, marshaling to string, I just wrote it wrong here. I'll implement option 3 with the other suggested changes.

@Tartuffo
Copy link
Contributor

@dtribble Do we really need stake-weighted voting at the JS level for Mainnet 1 (vs Cosmos level).

@Tartuffo
Copy link
Contributor

We want to address with governance proposals that can submit arbitrary actions via bootstrap. For example, at Cosmos level, can submit change to gov param via vault.

If we don't do this, we must do: #4352

@Tartuffo Tartuffo added MN-1 and removed MN-1 labels Jan 26, 2022
@Tartuffo
Copy link
Contributor

Tartuffo commented Feb 2, 2022

This work was done in #3985, waiting for end to end testing.

@Tartuffo Tartuffo removed the MN-1 label Feb 7, 2022
@Tartuffo Tartuffo added this to the Mainnet 1 milestone Mar 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cosmic-swingset package: cosmic-swingset enhancement New feature or request Governance Governance needs-design
Projects
None yet
Development

No branches or pull requests

4 participants