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

Make a final decision on first approach to slashing #2475

Closed
aesedepece opened this issue Jun 24, 2024 · 26 comments
Closed

Make a final decision on first approach to slashing #2475

aesedepece opened this issue Jun 24, 2024 · 26 comments
Assignees

Comments

@aesedepece
Copy link
Member

aesedepece commented Jun 24, 2024

Currently, we don't have a slashing mechanism in Witnet 2.0 branches. We have to discuss the different proposals and decide whether to implement one for the first release candidate or for upcoming ones.

@guidiaz
Copy link
Contributor

guidiaz commented Jun 24, 2024

Some previous discussions about this topic:

Some interesting reading:

@guidiaz
Copy link
Contributor

guidiaz commented Jun 25, 2024

Some proposals from my end to be discussed:

@drcpu-github
Copy link
Collaborator

Just to make sure I'm following, we are only debating power slashing here, right?

@drcpu-github
Copy link
Collaborator

Some notes:

  1. The currently proposed mechanism is delayed slashing, not at the boundary of a superblock, but rather in epoch n+1 when epoch n had no block proposed. I think this tackles the weaknesses in your second (and third) proposal. I'm not quite sure why you would only do it at the boundary of a super epoch, but maybe I missed something in our previous discussions.
  2. There is no doubling of the rf implemented because that makes it truly variable and so it needs to be saved somewhere, not just as a code constant.
  3. I think I still don't see the difference between next-epoch slashing and same-epoch slashing from the perspective of chain operation. Same-epoch slashing also seems pretty difficult to me because of the way block receiving and consolidation is implemented, but maybe I'm missing something.

@aesedepece
Copy link
Member Author

I think the most reasonable take is to:

  1. Consider that the top rf most powerful validators (stake entries, actually!) are eligible for block proposing.
  2. Consolidate the received block candidate with the highest power (let's call this h), or none if no candidates were received.
  3. Power-slash every stake entry with a power higher than the one that was consolidated.

I see this as a simple and elegant solution that disincentivizes power hoarding and largely mitigates the potential harm to network liveness and oracle service quality that powerful yet lazy, malicious or faulty validators could have.

@aesedepece
Copy link
Member Author

For more color on the proposal above:

  • Broadcasting logic stays the same — the best received and validated block candidate is broadcast when gossiping block candidates.
  • Power-slashing happens in the same epoch. By the end of each epoch, when the winning block gets consolidated, the slashes are applied accordingly so that the eligibility for the next epoch already takes into account the updated powers.
  • I find interesting the idea of slashing eligible stakes within the rf power elite but less powerful than the winning one (e.g. you receive candidates from 3rd and 4rd, consolidate 3rd and slash 1st, 2nd and 4th). However, the consolidation of a certain block candidate (and eventual signaling through beacons) only evinces that you received no more powerful candidates, but the fact that you received less powerful block candidates is hidden from beacons. This is to say that I would run away from this type of slashing for now because, paradoxically, it could be a source of forks and therefore work against liveness of the network which is what we're trying to go after with this debate.

@drcpu-github
Copy link
Collaborator

  • Power-slashing happens in the same epoch. By the end of each epoch, when the winning block gets consolidated, the slashes are applied accordingly so that the eligibility for the next epoch already takes into account the updated powers.

I'm a bit confused by this statement. Unless I misunderstand the code, block consolidation happens at the beginning of the next epoch, not at the end of the current epoch. This also implies that slashing needs to happen at that time and not earlier.

This is not an issue for data request and block mining. Block mining already is postponed through a ctx.run_later call which results in a block being built mid-epoch (so long after the power changes). Data request mining happens in the EpochNotification handle function a couple of lines after slashing the power if no block was consolidated. I think both of these mechanisms result in the node always having a correct view of the stake powers when using them to check its eligibility.

@aesedepece
Copy link
Member Author

aesedepece commented Jun 26, 2024

I'm a bit confused by this statement. Unless I misunderstand the code, block consolidation happens at the beginning of the next epoch, not at the end of the current epoch. This also implies that slashing needs to happen at that time and not earlier.

Sorry I was speaking top of my head. It is exactly as you mentioned. I was speaking rather from the perspective of protocol design than the particular implementation in witnet-rust. The logic is still the same. The bottom line is that coin ages get adjusted upon consolidation just like UTXO set or any other data structures that belong to the chain state are.

@drcpu-github
Copy link
Collaborator

drcpu-github commented Jun 26, 2024

Sorry I was speaking top of my head.

No worries, just wanted to make sure we were completely on the same page as this is a pretty important decision and has a significant impact on the consensus algorithm.

3. Power-slash every stake entry with a power higher than the one that was consolidated.

Note that his is currently not implemented for the simple reason that, in my mind, it is a much more severe penalization mechanism. My goal with the slashing was purely to preserve chain liveness with as little impact as possible. If we go the route of slashing everyone with a higher power too, we wander into the area of potentially slashing nodes that are being censored, DOS'd, etc. I consider that to be more contentious and I wanted to steer clear from it the initial wit\2 integration.

@aesedepece
Copy link
Member Author

If we go the route of slashing everyone with a higher power too

Then your suggestion is to apply slashing to everyone in the rf commitee only in the scenario where there is no block candidates?

@drcpu-github
Copy link
Collaborator

If we go the route of slashing everyone with a higher power too

Then your suggestion is to apply slashing to everyone in the rf commitee only in the scenario where there is no block candidates?

That is what I have currently implemented, yes, but solely for the sake of (game-theoretic) simplicity. I'm not opposed to the other option, I just wanted to keep my patch as little contentious as possible.

The one thing I'm still not sure about is if I like the slash proportional to the rank option because slashing a high-power node by, e.g., 1/3 of his power feels a bit futile (at least on my artificial testnets).

@guidiaz
Copy link
Contributor

guidiaz commented Jun 26, 2024

we wander into the area of potentially slashing nodes that are being censored, DOS'd, etc.

I had this same concern, and that's why the article about the Witnet P2P Bucketing System was linked above. After solving multiple questions and possible flaws on current bucketing system, we came to agree that we should consider it to be strong enough to not auto-limit ourselves when thinking on possible slashing solutions.

not sure about is if I like the slash proportional to the rank option

Slashing in different proportions wipes out any attempt of an attacker feeding validators with exactly the same staked amount (the most naive way to take over the RF top ranking arena), and also prevents reluctant top stakers having accrued similar power end up entering back into the top RF rank on a periodical base.

e.g., 1/3 of his power feels a bit futile (at least on my artificial testnets).

I would need to assess the tests or simulations being done. A priori, I don't believe that reducing the power of a rank-3 validator by a third would be futile. What matters most is not how much power is reduced in absolute terms, though, but how much power is reduced in relation to higher ranked validators.

@guidiaz
Copy link
Contributor

guidiaz commented Jun 26, 2024

What about increasing RF if no block was produced on previous epoch?

No matter the slashing approach we ultimately decide upon, there can always be the chance of an attacker taking over the RF top ranking list. For the current value of RF = 4, I think the chances are too high, and therefore we should either consider

(a) settle a higher value for the RF constant,
(b) dynamically increase RF in some proportion (maybe not double the previous value, but perhaps summing up RF instead, for instance) if no block was produced in previous epoch (and reset to RF otherwise),
(c) or both.

@guidiaz
Copy link
Contributor

guidiaz commented Jun 26, 2024

apply slashing to everyone in the rf commitee only in the scenario where there is no block candidates?

Because there can always be the chance of an attacker taking over the "rf committee", slashing everyone in such committee if no block was consolidated on previous epoch should be a MUST. The ideal thing would be to power-slash all members of previous rf committee at the beginning of the new epoch, so a new "rf commitee" gets selected.

@drcpu-github
Copy link
Collaborator

I had this same concern, and that's why the article about the Witnet P2P Bucketing System was linked above.

I'm inclined to agree with the article, I just wanted the current patch to be non-contentious. If no one objects to slashing stakers 1 to k-1 on consolidating a block from staker k, I'm fully onboard with implementing this.

Slashing in different proportions wipes out any attempt of an attacker feeding validators with exactly the same staked amount (the most naive way to take over the RF top ranking arena), and also prevents reluctant top stakers having accrued similar power end up entering back into the top RF rank on a periodical base.

It does, but at the cost of having more epochs where one or more validators can refuse a block. I'm not really against it, but the consequence over fully slashing all validators is significant and I'm mainly wondering about the actual slashing ratios.

A priori, I don't believe that reducing the power of a rank-3 validator to a third would be futile.

Note that you are not reducing it to a third, but rather reducing it by a third (otherwise a rank 3 validator would be punished harsher than a rank 2 validator).

What about increasing RF if no block was produced on previous epoch?

Certainly not against it as that was part of my initial proposal, I'm just not sure how to implement it because that changes the rf from a constant to a variable thing meaning it probably needs to be save in some chain state.

@guidiaz
Copy link
Contributor

guidiaz commented Jun 26, 2024

Note that you are not reducing it to a third, but rather reducing it by a third (otherwise a rank 3 validator would be punished harsher than a rank 2 validator).

Agreed, I actually meant "by a third" too, and just fixed it above.

It does, but at the cost of having more epochs where one or more validators can refuse a block. I'm not really against it, but the consequence over fully slashing all validators is significant and I'm mainly wondering about the actual slashing ratios.

I'd be more concerned about the number of epochs where all validators are prone to refuse a block. As a way to minimize periodical situations where all validators refuse a block, sequential prime numbers (p ) could be used to settle the slashing ratios (e.g. (p-1)/p).

it probably needs to be save in some chain state.

Not really. Block proposers in epoch N should know the last epoch M on which a block was consolidated. So the rf value in epoch N could be calculated as (N-M)*RF, or RF*2^(N-M-1), for example.

@aesedepece
Copy link
Member Author

Not really. Block proposers in epoch N should know the last epoch M on which a block was consolidated. So the rf value in epoch N could be calculated as (N-M)*RF, or RF*2^(N-M-1), for example.

From what I can tell, this is true, if we're saying N is the epoch of a block candidate (block.block_header.beacon.checkpoint ) and Mis the epoch of the last consolidated block (self.chain_state.unwrap().highest_block_checkpoint).

@aesedepece
Copy link
Member Author

Under that perspective, there would be a base replication factor constant, and a separate effective replication factor that grows progressively as epochs are completed without a consolidated block, and goes back to the value of the base constant as soon as a block is consolidated.

Is this what you are suggesting @guidiaz ?

@drcpu-github
Copy link
Collaborator

drcpu-github commented Jun 26, 2024

self.chain_state.unwrap().highest_block_checkpoint

This may be interesting (and workable) as an approach. I was not sure how we could increment the rf for nodes that were synchronizing (either from start or from recovering from a shallow fork) since I think they do not go through the consolidate block flow.

Under that perspective, there would be a base replication factor constant, and a separate effective replication factor that grows progressively as epochs are completed without a consolidated block, and goes back to the value of the base constant as soon as a block is consolidated.

Yes, that is what we discussed before on Telegram as a way to tackle the issue where there are more than the base rf attackers.

@aesedepece
Copy link
Member Author

This may be interesting (and workable) as an approach. I was not sure how we could increment the rf for nodes that were synchronizing (either from start or from recovering from a shallow fork) since I think they do not go through the consolidate block flow.

Nodes that are synchronizing do not go into validating anything related to eligibility, as they can't compare block candidates, etc.

@guidiaz
Copy link
Contributor

guidiaz commented Jun 28, 2024

About witnessing power-slashing

Because block proposers are sovereign to decide what dr-commit transactions to include, if any at all, there's no actual possible way to power-slash reluctant witnesses.

However, we should definitely care to reset the coin age of all different "witnessing identities" for whom at least on valid dr-commit transaction gets included in a block (a "witnessing identity" being any the unique validator-withdrawer pair in the Stake Tracker).

@guidiaz
Copy link
Contributor

guidiaz commented Jul 2, 2024

About validation of dr-commit transactions

From a block validator point of view, the following rules should apply in order to consider whether the dr-commit transactions contained within a block proposal are valid:

a) they have to refer to a not-yet-committed and not-yet-expired DR.
b) they have to refer an existing "witnessing identity" in the Stake Tracker.
c) referred "witnessing identities" should be within the resulting range described in witnessing eligibility condition (2) below.
d) their VRFs should be equal or greater than the threshold described in witnessing eligibility condition (3) below.
e) the current coins field of the corresponding "witnessing identity" needs to be equal or greater as the DR's collateral.
f) every time a dr-commit transaction gets verified, the coins field of the corresponding "witnessing identity" should be decreased in the same amount as the referred DR's collateral.

Should any "witnessing identity" get its coins value below zero during the block validation, the whole block proposal should then considered to be invalid. On the contrary, if all dr-commit transactions within a block proposal get successfully verified:

  • The coin_age MUST be set to 1 on all different "witnessing identities" referred by the dr-commit transactions included in the block.
  • The altered coins values MUST be consolidated as the new status when processing block candidates on following epochs.

@guidiaz
Copy link
Contributor

guidiaz commented Jul 2, 2024

About validation of dr-tally transactions

I partially concur with the idea proposed in #2446 about:

...letting a block proposer to include dr-tally transactions embedding a specific error (to-be-named) if a DR getting included within the same block requires a number of witnesses greater than the number of entries in the Stake Tracker...

but adding this extra condition:
...with at least as much stake (i.e. coins) as the DR's collateral, divided by a replication factor (ie. see rf below).

On another note, instead of naming this specific tally error as "too many witnesses", I'd rather suggest to name it as InsufficientWitnesses, because of two reasons:

(a) coherence with the InsufficientReveals and InsufficientCommits proposed in #2430;

(b) "too many witnesses" could give the wrong idea that the data requester is trying to require an "illegal" number of witnesses, whereas the fact is that the scarcity of witnesses may just be something temporary and eventually self-amended in the short-term.

Finally, I think we should decide on whether the block proposer should earn double or single fee: one mining fee for including the DR tx and another mining fee for including the DR Tally tx as well, or just one mining fee for including both (as if including the former without the later would invalidate the whole block being proposed). What do you think guys @aesedepece @drcpu-github @Tommytrg ?

@drcpu-github
Copy link
Collaborator

Because block proposers are sovereign to decide what dr-commit transactions to include, if any at all, there's no actual possible way to power-slash reluctant witnesses.

I remember there was a reason for the inclusion of commit transactions to be essentially random, but I cannot remember what it was and I don't know if this still holds up. I wonder if we can require the included commits to be ranked by power (and then we can introduce slashing). Of course, that only works under the assumption that no one is censoring nodes (but we are assuming that anyway).

Let block proposers include dr-tally transactions referring "insufficient witnesses" if a not-yet-committed DR requires a number of witnesses greater than the number of entries in the Stake Tracker with at least as much stake (i.e. coins) as the DR's collateral. In this case, the block proposer would earn the DR's "mining fee"... wip...

I'm not quite sure, but this sounds like you are (partially) referring to this PR? Note that this simply takes into account the number of stakers, not their coins. I don't think taking into account the number of coins is relevant though since there is a minimum stakeable amount of 10k coins and it seems unlikely we'll see DR's requesting that kind of collateral as long as they have to pay 1/125 of the requested collateral as reward to each witness.

@guidiaz
Copy link
Contributor

guidiaz commented Jul 2, 2024

I'm not quite sure, but this sounds like you are (partially) referring to this PR? Note that this simply takes into account the number of stakers, not their coins. I don't think taking into account the number of coins is relevant though since there is a minimum stakeable amount of 10k coins and it seems unlikely we'll see DR's requesting that kind of collateral as long as they have to pay 1/125 of the requested collateral as reward to each witness.

I wasn't directly referring to that PR, but yeah, stating a similar idea I guess. In fact, the one proposed in the PR is even better, because the tally transaction would be included together with the DR transaction itself, which is even more efficient. However, I'd strongly suggest the condition to be "not enough entries in the Stake Tracker with at least as much stake (i.e. coins) as the DR's collateral". The reason being "market freedom". Why should we limit the amount of reward, ergo collateral, that a data requester may be willing to pay for a DR getting solved?

@guidiaz
Copy link
Contributor

guidiaz commented Jul 2, 2024

About witnessing eligibility

(Summarizing a few ideas and conclusions after in-depth chatting with @aesedepece)

Based on what's currently stated in the Wit/2 WIP, some variants are proposed below for your consideration, pretending to:

  • let most powerful witnessing identities (i.e. unique validator-withdrawer pair in the Stake Tracker) have more chances to become potentially eligible for solving DRs;
  • minimize the chances of the same wintessing identities monopolizing multiple DRs within the same block.
  • let creation of DR witnessing committees to be random enough as to avoid witnessing preemptiveness and collusion.
  • reduce max_rounds to 3 while preserving QoS (i.e. DR successful resolution ratio).

() For a commitment transaction to be considered for inclusion in a block, it MUST refer to a (a) not-yet-committed data request, (b) the referred DR's round is 3 or less, (c) the committer (i.e. validator-withdrawer pair) holds an stake (i.e. coins) greater than the DR's collateral, (d) the committer holds certain amount of witnessing
power, and (e) the committer provides a valid VRF proof that MUST satisfy all the following requirements, depending on the current DR's round:

  • (1) The VRF input is the concatenation of the previous block hash, the data request hash, and the current epoch, all of them in big-endian format.
  • (2) The committer is within the i-th quartile of most powerful witnessing identities having at least as much stake as the DR's collateral (ie. Q1, Q2 or Q3).
  • (3) The big-endian value of the VRF output is less than witnesses * rf / Ri.
  • (4) The value of Ri is greater or equal than witnesses * rf.

Where:

  • rf is the replication factor (same on all rounds),
  • i is the DR's round number calculated as the difference between current epoch and the epoch on which the referred DR was included on a block,
  • witnesses is the DR's witnesses value,
  • Qi is the i-quartile of the Stake Tracker (e.g. Q1 would be the witnessing power threshold that at least 25% of the Stake Tracker entries staking at least the DR's collateral can be proven to have),
  • Ri is the number of witnessing identities having a stake equal or greater to the DR's collateral, and a witnessing power of at least the Qi.

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

No branches or pull requests

5 participants