spacemeshos / SMIPS

Spacemesh Improvement Proposals
https://spacemesh.io
Creative Commons Zero v1.0 Universal
7 stars 1 forks source link

Rewards and incentives #38

Open lrettig opened 3 years ago

lrettig commented 3 years ago

Overview

The Spacemesh system needs to reward nodes that perform objectively valuable actions for the network such as mining new transactions into blocks, executing and validating the transactions in those blocks, and participating in Hare consensus.

For background see these forum threads:

Goals and motivation

See https://community.spacemesh.io/t/preliminary-proposal-for-incentives-rewards/121/1

High-level design

This design is based on EIP-1559, modified to work for a mesh rather than a chain. We introduce a base_fee in each layer, which all transactions in blocks in that layer must pay. Rewards collected in a layer and distributed to miners are smoothed over all blocks and transactions in a configurable number of layers. We also add reward maturation, so that a reward earned by a miner in a given layer isn't spendable until a configurable number of layers later.

Proposed implementation

  1. Config variables. We add several new config variables, including:
    • smoothing_distance: the number of layers over which rewards are smoothed (0 = no smoothing, 1 = layer-wide smoothing, etc.). Note that this must be hardcoded in genesis for a given net/mesh and cannot change later.
    • maturation_distance: the number of layers that must pass before a reward earned by a miner is spendable
    • max_adjust: the maximum ratio by which we allow the base_fee to change from layer to layer
    • min_gas: the minimum total fee that a miner accepts to mine a transaction into a block. This is not in consensus and will differ from miner to miner. It should represent something close to a miner's actual variable cost of including an additional transaction in a block.
  2. Transaction fees and gas
    • Update Transaction data structure to include GasLimit (already present), MaxFeePerGas (max base fee tx is willing to pay) and MaxTipPerGas
    • Update gas arithmetic in tx processing/STF, and in state projection
  3. Miner transaction selection algorithm and add per-layer base_fee
    • Miners should keep their txpool sorted by fee
    • They should determine the base_fee for the current layer (based on votes in the previous layer), determine which transactions in the txpool pay at least this fee, and select transactions randomly from the set that are above this threshold
    • They should calculate a base_fee (based on layer capacity, to take effect in the following layer) and include their explicit vote for base_fee in blocks they publish in this layer
    • They should consider as contextually invalid, and vote against, any block that includes transactions below the base_fee for a given layer
  4. Reward smoothing and maturation
    • Modify reward smoothing to make it work over a variable number of layers. Make sure it includes all collected tips and fees, as well as the block subsidy.
    • Add maturation so that "paid" rewards don't appear in the recipient's account, and aren't spendable, until maturation_distance has passed
  5. API changes: this will require rethinking the way the API returns info on rewards and account state (balances). We already split account state into current/projected in the API. We could include upcoming (immature) rewards in projected but not current account info. We may need to split rewards endpoint to do something similar. Rewards will now have three states: upcoming/projected (due to smoothing), paid (but not matured/spendable), final (matured/spendable).

Implementation plan

  1. Refactor existing rewards code to standardize type (https://github.com/spacemeshos/go-spacemesh/issues/2069)
  2. Update types
    • Transaction (as described above)
    • Block (add fee voting: this is just a uint)
  3. Gas arithmetic
    • Implement EIP-1559 logic in STF/tx processor
    • Update state projection logic as well
  4. Mempool management, tx selection & block building logic
    • Rewrite mempool to sort by fee. Will require changing data structures, something like a priority queue/heap but also indexed by account.
    • Add logic to calculate base_fee for new layer based on blocks in DB for previous layer: cutoff top N transactions then pick randomly among them; include vote for base_fee in new block
  5. Smoothing
    • Add smoothing_distance param
    • Rewrite rewards logic using smoothing
    • Evaluate how expensive it would be to reread rewards from previous smoothing_distance layers in each new layer, and whether we need to cache these values in memory. Build a cache if necessary.
  6. Maturation
    • Does not require major changes to rewards logic. Just apply rewards maturation_distance layers behind the latest confirmed layer, whenever a new layer is confirmed (same as now).
  7. Update API methods related to rewards, fees, and account state/balance, as described above.

Questions

Ongoing work

This proposal only includes the barebones design and implementation required for a functional reward system for genesis. In particular, only mining is rewarded. Other useful behaviors such as transaction validation and participation in Hare are not covered by this design and are left for follow-on designs.

Dependencies and interactions

Stakeholders and reviewers

These changes touch several core go-spacemesh components. Reviews will be requested from the folks most familiar with the components that are changed.

Testing and performance

Tests will be added for all new and changed code.

Performance considerations:

lrettig commented 3 years ago

Thank you everyone for your helpful feedback on today's R&D call. Here are some followup items:

lrettig commented 3 years ago

Moving this over here from #50, need to find a place for it in this SMIP or another:

Initially no change to incentives is necessary. Dishonest miners may submit empty content blocks, no content blocks, or duplicate content blocks but this will have little or no impact on the superblock produced for each layer. In any case, the degree of harm that dishonest miners can cause under this proposal is no greater than in Spacemesh 0.1, where they could engage in the same behavior. (In fact, there's less harm, since they cannot cause bloat in the mesh due to many duplicate transactions in a layer.)

If we're concerned about high fee paying transactions not being included in layers due to Byzantine behavior by a dishonest minority of miners in scenarios where the mempool contains many pending transactions, we could increase redundancy of these transactions by having multiple miners include such transactions in their proposed content blocks (at the cost of total throughput). See Coupon collector's problem for one probabilistic approach to solving this problem.

We should continue to research ways to better align incentives, such as by punishing miners (or withholding incentives from miners) who submit content blocks that are less than full, or contain many duplicate transactions.