RFC: Another proposal for collaborative mining

I’ve been following the orphaning/mev issue the last few days (albeit a bit late to the party…) and had some thoughts I thought I’d share, just in-case any of it might spark some additional ideas or innovation in those currently working on the project.

The following proposal builds a bit on Aaron’s proposal (terms, producer sets, eliminating microblocks, etc.) and is admittedly a bit rough around the edges and not all of the details are completely thought out, but I hope people can understand the overall gist of things :slightly_smiling_face:

Introduction

This proposal stems from thinking of stacks as a distributed atomic state machine, taking rough concepts from multi-master distributed databases, Lightning network, Radix DLT and more. The general thinking behind this is to define an open and fair protocol which emphasizes collaboration and inclusion over competition and exclusion by re-focusing rewards (“payments”) to actual network contributions.

The proposal also aims to present a long-term solution, with the performance and scalability of the network over time in mind.

How this proposal differs from today’s solution

  • Block reward incentive is more-or-less removed and replaced with transaction processing incentive.
  • The concept of microblocks (as blocks) is removed, in favor of the processing of individual transactions. Note that blocks are still produced as the “true finality marker”.
  • The mempool adds a distributed op-log (i.e. “write-ahead log” (WAL) or “commit log”) of transactions which have been confirmed by active miners but not yet written to a block.
  • All miners process transactions and no two miners process the same transaction.
  • All miners have a fair chance of being included and thus receive rewards.
  • Mining rewards are distributed across all participating miners in relation to their contributions.
  • BTC commitments of miners, instead of being “spent upon commitment”, are used as a deposit which in turn is used to purchase the right to process a transaction.

Pros

  • Miner rewards are directly related to the miner’s contributions to the network. Miners are only rewarded for their contributions, and don’t risk losing more than they contribute. Or rather the miner is guaranteed a return in STX - risk is still implicit in the BTC/STX exchange rate.
  • By spreading transaction processing over a group of miner nodes, instead of all miners processing the same transactions, the theoretical network throughput is increased.
  • Even small miners can participate and receive rewards with a good chance of inclusion, and it’s impossible for large miners to crowd-out smaller miners due to semi-random miner selection.
  • The introduction of a miner Reputation during selection prioritizes good behavior and availability (more likely to be included in Cohorts) over financial muscle.
  • Incentive for crowding-out, orphaning, MEV disappears.
  • Miners cannot free-load, they must purchase transaction processing rights and process transactions to receive rewards.
  • Miners may not pick-and-choose which transactions they want to process - transactions are delegated to them, removing any possibility to use MEV.
  • As there is no direct incentive for the act of producing a block, there is no longer any incentive for orphaning blocks/forking.
  • Nodes can with reasonable confidence consider a transaction as “confirmed” as soon as it lands in the distributed op-log, which should be in near-real-time, as orphaning/forking is not incentivized.
  • Miners which are not participating in the current cohort do not need to use additional compute resources for transaction processing, creating a potential optimization point for nodes in the cloud using burstable instances.

Cons

  • The consensus protocol becomes markedly more complex.
  • The p2p network becomes chattier, though this can be minimized by keeping as much as possible only between the currently selected mining nodes (“producer set”), possibly even using a separate cohort-only channel.
  • Not entirely sure how this plays with PoX/Stacking.
  • The implementation of something like this proposal is likely much larger than other currently proposed solutions.

Definitions

Term – A pre-defined period of N Stacks blocks, Bitcoin blocks, or some volume-based rule. A pre-defined period of time in one way or another.

Cohort – (a’la “producer set”) A group of miners which have been selected via a Cohort Selection to contribute to transaction processing and block production during a Term.

Cohort Selection – The process of the network selecting the members which will be included in a Cohort.

Reputation – Some sort of score assigned to individual mining nodes indicating their reliability and contributions to the network. What this score is based on could be a combination of parameters such as the number of terms the node has participated in, number of transactions they have processed, availability for transaction processing, transaction processing speed, etc. The selected parameters should all be weighed over time.

Miner Balance – The current remaining balance of the miner’s BTC.

Transaction Processing Rights – The right for a mining node in a Cohort to process a transaction, purchased from the network using funds from the miner’s BTC balance.

Transaction Processing – The processing of mutations by a mining node via Clarity smart contracts on the Stacks network.

Passive Miner – A mining node which has not been selected to participate in the current Cohort.

Active Miner – A mining node which is active in the current Cohort and processing transactions.

Inactive Miner – A mining node which was selected to participate in the current Cohort and has processed at least one transaction, but for one reason or another is unable to continue to fulfill its duties.

Failed Miner – A mining node which was selected to participate in the current Cohort and has failed to process any transactions.

Transaction – A request to perform a mutation to the current state of the Stacks network (i.e. a contract call).

General

  • Miners fund their nodes using BTC. Unlike today, this BTC is not an absolute commitment and is instead used as a balance from which Transaction Processing Rights are purchased.
    • This is a little bit like how Lightning channels must be funded prior to being used, and the movement of liquidity from one end of the channel to the other somewhat like movement between Miners and Stackers.
    • A reasonable minimum-amount could be imposed to be eligible for inclusion in a Cohort, but this should be small enough that your average enthusiast could participate.
    • What to do with unspent BTC after the end of a Term? It could be returned to the miner, or perhaps it should be considered a “commitment” and the only way to redeem funds is via participation and STX rewards?
  • The amount of BTC spent by a miner on purchasing Transaction Processing Rights during a Term directly correlates to their STX reward.
  • The number of members in a Cohort must be at a minimum N. If N nodes are not available, then all available nodes must be used. N may be adjusted upwards by the network to increase throughput at times of contention.
  • All nodes in the network are aware at all times of the current and upcoming Cohort members.
  • If a Passive Miner receives a transaction from a client, the node forwards the transaction to the appropriate Active Miner (using its local lookup-table).
  • If the Miner Balance of a node in the active Cohort reaches (near?) zero, it may be evicted from the Cohort and become an Inactive Miner. A new Passive Miner could be selected to replace the Inactive Miner, becoming an Active Miner for the remainder of the Term (or until evicted or failed).
  • A miner which has become an Inactive Miner (has processed transactions but had to drop-out) will still receive STX for the work performed.
  • A Failed Miner may be ineligible for Cohort selection during a period of time.

Description

Cohort Selection

  1. Prior to the beginning of a term N (N-2 has been suggested), the network determines the number of required Cohort members and selects eligible nodes to participate. This would ideally be semi-random, for example it could be a requirement that e.g. 60% of miners have a reputation over X and the rest be randomly selected from the remaining candidates. If 60% of miners do not have a reputation greater than X then the 60% is filled using nodes’ reputations in descending order from best to worst. The motivation behind this kind of rule would be to ensure that a majority of a Cohort consists of considered-reliable nodes, while still giving newer nodes a fair chance of being included.
    THOUGHT: Perhaps a number of runner-up nodes should also be selected, based on the size of the Cohort, to increase predictability in the event of a failure/eviction of an Active Miner.

  2. Based on the number of nodes in the Cohort, ranges of a 32-bit integer are evenly and uniquely assigned to each node (e.g… node 1 = 0-10, node 2 = 11-20, etc.). This will be used to fairly distribute transaction requests across the Cohort using e.g. CRC32 hashing of requests.
    NOTE: Using CRC32 as an example as it’s very fast and results in a 32-bit integer. Could be swapped out for any appropriate algorithm.
    NOTE: This could also be weighted ranges factoring in the available Miner Balance, but care should be taken to not allow a miner to crowd-out others with large balances.

  3. This information is broadcast to the network. All nodes maintain an updated list of Cohort members and their assigned hash range.

Transaction Processing

This is where things get a little bit more complicated and less thought-out in detail, so I’m keeping this on a high-level. There is a lot of research and varying implementations in this area which could be looked into by people smarter than me :slight_smile:

  1. When a mutation has been received by a node (any miner node), the request is CRC32’d. This value is looked-up in the local Cohort mapping and (if not self) forwarded to the correct Cohort member for processing.

  2. The responsible node processes the transaction as done today.
    THOUGHT: This could even be two or three nodes which should process the transaction and compare results?

  3. Upon successful processing, the miner broadcasts the result of the mutation to the Cohort as a PRE_COMMIT message.

  4. [Insert some fancy distributed multi-phase commit consensus algorithm here]
    Some interesting work has been done in this area by Radix DLT , particularly with their “Cerberus” consensus model. See their whitepaper.

  5. Conflict resolution: Attempt to re-run transaction using latest state and goto #3?

  6. When a miner in the Cohort agrees that the transaction result is valid, they send an ACK back to the responsible miner including a signature of the result signed by their Stacks private key.
    THOUGHT: The Cohort probably needs to agree on a sequence number for each commit, so that commits can’t be applied out-of-order by nodes.

  7. Once the responsible miner receives ACKs from a majority of the Cohort, it then broadcasts a COMMIT message to the network with the transaction including the corresponding ACK signatures, allowing the network (which knows which nodes are in the current Cohort) to verify that the commit is valid.

  8. All nodes update their mempool oplogs.

  9. The responsible node’s balance is debited X satoshis (some function of the transaction cost?). This would be debited in BTC but the transaction processing cost would be calculated in STX. How could this be solved?

Block Production

  1. Periodically throughout a Term, blocks will be produced by members of the Cohort. As there is no practical reward for producing a block, a random Active Miner with sufficient balance to submit the Stacks block to the burnchain is selected and given the responsibility.

  2. If the miner responsible for submitting the block fails to do so, another miner is selected.

  3. The BTC fees incurred by the miner will be reimbursed in STX (how to handle exchange rate?).
    THOUGHT: The BTC fee could also be reimbursed to the Miner’s Balance, in which case the Cohort would need to come to a consensus on the fee to be used to avoid a miner specifying ridiculously-high fees and getting reimbursed.

Reward Payout

  1. Rewards are paid out in the last block of each Term to the participating members of the Cohort.

  2. Coinbase rewards are used:

    1. first, to reimburse burnchain network costs to Cohort members and any other potential fees that might be incurred by participants (if not reimbursed in BTC to the Miner Balance),
    2. second, to pay rewards in proportion to paid BTC,
    3. and the remainder is distributed proportionately to Cohort members based on their contributions. Or, maybe some could go back to stackers?

Additional Thoughts

  • When the Stacks network grows large enough, sharding could be implemented to increase throughput and decrease node size.
    • In this case the Cohort Selection would need to ensure that all shards are accounted for in the Cohort (probably with redundancy as well).
    • The determination of the Responsible Miner would need to be altered to include randomization across shard owners.
    • This would likely need to be accompanied by “archive nodes” (or “full nodes” as Ethereum calls them).
  • Another way to do the distribution of transactions across Cohort members would be to base the hashing on the destination contract, but then it’s almost guaranteed that there will be hot-spots in the Cohort.
  • What kinds of attack vectors could exist in this model? (D)DoS? A mechanism to eject suspected malicious nodes should exist.
    • A miner could theoretically maliciously target requests to their node, forcing transactions to be processed by them (once they find a request that matches their assigned hash prefix)… but I don’t think they could do that with profit?
  • After some thought I’m leaning towards that the BTC deposit shouldn’t be refundable, and the only way to reclaim it is via STX rewards…
  • After some thought, I think that removing block rewards completely and to use Term rewards instead would be better:
    • This would allow for as many blocks as needed to be produced within a Term while keeping the block size reasonably-sized and not capping the number of transactions which could potentially occur within a Term.
    • If Terms were fixed at a specific number of burnchain blocks then the existing coinbase amounts could be used, since one Stacks block is produced for each burnchain block. The coinbase would then be the last block of each Term (or the first block of the next Term), and be equivalent to [(burnchain blocks in Term) * (block reward)].