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

Incentives: Suspend "absentee" accounts that don't propose. #5757

Merged
merged 123 commits into from
Apr 23, 2024

Conversation

jannotti
Copy link
Contributor

@jannotti jannotti commented Sep 26, 2023

Building on #5740, this PR "suspends" accounts that claim to be online but don't appear to be participating. With the addition of block incentives comes the concern that participants, eager to earn incentives, will begin participating without being as careful as we'd like. They might run a node without paying enough attention to uptime. Two of the biggest concerns:

  1. An entity with a lot of stake (say an exchange) runs their node to earn incentives, but doesn't worry (enough) about uptime. A 5% node can go down without harming the protocol, but it would be scary. And in a decentralized network, one might wonder who they are and when they will get around to fixing it.
  2. Many entities, each with a little stake, decide to participate. Over time, they might get bored or distracted, and not notice that the proverbial "node in their basement" has failed.

This PR proposes that the network suspend nodes if they go too long without participating, as determined by their lack of proposals. A proposer can suspend accounts that have not proposed in a "long" time, currently 10x the interval over which one would have expected them to propose. A node with 1% stake should propose once every 100 rounds. If they have not proposed for 1,000 rounds, they can be suspended. Large stakeholders with failed nodes would be noticed relatively quickly (on the scale of an hour). Small stakeholders with broken nodes would be noticed more slowly, but would also slowly be removed, presumably before too many accumulate.

keyreg can be somewhat arduous for large stake holders who use multisig, Ledgers, cold storage wallets, and so on. Therefore, we would not want false positive suspensions which would require a new keyreg to go back online. So, a follow-on will add a "heartbeat" mechanism (#5799). If a node notices that it it has been unlucky, and is perhaps approaching 8 or 9 times their expected proposal interval, they can issue a special kind of keyreg that simply renews their existing voting keys. Since it's hard to get transactions signed by secure, high-stake accounts, this special keyreg can be signed by the participation keys of the account, not the spending key. For accounts that separate the job of node running and (spending) key management, we want the node runner to be able to issue these keep-alives. However, care must be taken to ensure that participation keys can only sign these keep-alive transactions, and that they can not be "spammed", wasting fees, by a node runner gone rogue.

While "suspension" removes the account's balance from online stake, it it does not remove voting key material from the node's account record. Therefore, in the case of a long lasting network partition that cause an account to be suspended, the node can return to service when the network heals by sending a keep-alive (again, no laborious keyreg is required).

Many things remain to do:

  • Add new account fields to REST API and AVM
  • Update an account's LastProposed field during the mining payout
  • And bring them back online if they were suspended
  • Mark a newly online account with LastHeartbeat = current round.
  • Note suspendible accounts, verify them, and suspend them
    • Account for pending rewards in calculation
    • Get acct and total stake from the same round
    • Use a grace period so that accounts don't have to predict their suspension

@jannotti jannotti changed the title Absenteeism - Suspend accounts that don't propose. Incentives: Suspend "absentee" accounts that don't propose. Sep 26, 2023
@jannotti jannotti self-assigned this Sep 26, 2023
@joe-p
Copy link
Contributor

joe-p commented Sep 26, 2023

this special keyreg can be signed by the participation keys of the account, not the spending key.

This is very interesting to me. I wonder if a similar mechanism can be used for online registration in-general. For example, Alice wants to participate for X rounds, but only wants to generate the keys for some number of rounds less than X right now. Alice signs the initial keyreg with her signing key, but the node will automate the key generation and future keyregs at some interval up until round X.

ledger/eval/eval.go Outdated Show resolved Hide resolved
@jannotti jannotti force-pushed the absenteeism branch 2 times, most recently from 1b5f162 to 797bac9 Compare September 27, 2023 12:54
@jannotti jannotti force-pushed the absenteeism branch 3 times, most recently from 1f5baaa to 0f7bb79 Compare September 28, 2023 13:18
@jannotti
Copy link
Contributor Author

this special keyreg can be signed by the participation keys of the account, not the spending key.

This is very interesting to me. I wonder if a similar mechanism can be used for online registration in-general. For example, Alice wants to participate for X rounds, but only wants to generate the keys for some number of rounds less than X right now. Alice signs the initial keyreg with her signing key, but the node will automate the key generation and future keyregs at some interval up until round X.

That's is approximately how it works today. Alice generates a "root" participation key pair. That's the one she supplies at keyreg time. Before doing so, she generates a bunch, say 1,000, "batch keys", which she signs with the root key. Then she throws away the root private key, so that no more batch keys can ever be signed. Finally, as needed, she takes one of the batch keys, generates and signs another 1,000 or so keys that are intended for use in specific rounds of the protocol, throws away that batch key. Those are true "participation keys" and are used for only one round, then deleted.

In this way, Alice "virtually" has a million keys, but never actually has more than 2,000 in existence. Agreement performs three signatures check when checking an agreement signature. The signature of the message, and then two signatures to work up the chain and ensure that the root key is the root of trust. Only that root key was signed by the spending key (to prepare the keyreg)

That's for normal agreement keys. Some of this is different for state proof keys, I don't know that system as well.

In this proposal, I'm advocating for the derived key that is usable for agreement in round X to also be usable to construct and sign a heartbeat transaction with firstvalid=X.

@jannotti jannotti force-pushed the absenteeism branch 5 times, most recently from be12955 to 7476f7e Compare October 3, 2023 20:26
@codecov
Copy link

codecov bot commented Oct 10, 2023

Codecov Report

Attention: Patch coverage is 61.18068% with 217 lines in your changes are missing coverage. Please review.

Project coverage is 55.88%. Comparing base (0e7087b) to head (3d2fbc4).
Report is 2 commits behind head on master.

Files Patch % Lines
ledger/eval/eval.go 68.89% 35 Missing and 30 partials ⚠️
node/node.go 14.70% 27 Missing and 2 partials ⚠️
ledger/ledgercore/validatedBlock.go 0.00% 19 Missing ⚠️
agreement/proposal.go 68.51% 12 Missing and 5 partials ⚠️
data/basics/fraction.go 21.05% 14 Missing and 1 partial ⚠️
data/bookkeeping/block.go 58.82% 14 Missing ⚠️
ledger/ledgercore/accountdata.go 42.10% 11 Missing ⚠️
ledger/testing/testGenesis.go 0.00% 10 Missing ⚠️
data/pools/transactionPool.go 62.50% 5 Missing and 1 partial ⚠️
daemon/algod/api/server/v2/handlers.go 0.00% 5 Missing ⚠️
... and 9 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5757      +/-   ##
==========================================
+ Coverage   55.78%   55.88%   +0.10%     
==========================================
  Files         490      491       +1     
  Lines       68125    68473     +348     
==========================================
+ Hits        38004    38269     +265     
- Misses      27562    27613      +51     
- Partials     2559     2591      +32     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jannotti jannotti force-pushed the absenteeism branch 2 times, most recently from f71bd0f to 6dd7d1c Compare October 24, 2023 13:27
@joe-p joe-p mentioned this pull request Oct 27, 2023
@jannotti jannotti force-pushed the absenteeism branch 2 times, most recently from 5c32652 to 985bd5c Compare December 21, 2023 18:04
@jannotti jannotti force-pushed the absenteeism branch 4 times, most recently from c8dd389 to eebb4e2 Compare January 10, 2024 21:14
crypto/onetimesig.go Outdated Show resolved Hide resolved
@jannotti jannotti dismissed stale reviews from gmalouf and jasonpaulos via 87a20c5 April 22, 2024 18:47
gmalouf
gmalouf previously approved these changes Apr 22, 2024
jasonpaulos
jasonpaulos previously approved these changes Apr 22, 2024
ledger/eval/eval_test.go Outdated Show resolved Hide resolved
Co-authored-by: cce <[email protected]>
@jannotti jannotti dismissed stale reviews from jasonpaulos and gmalouf via 480f0f9 April 23, 2024 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.