I've seen many broad overviews of proof-of-stake mining, and descriptions, but I have not seen any good description of what goes into actually mining and verifying a proof-of-stake block, and how it accomplishes what people say. What are the technical details of this?
Proof-of-stake mining is similar to Proof-of-work at a technical level. It involves a sort of lottery, similar to proof-of-work, but the difficult of this lottery is weighted depending on how many coins you are staking. The overall process for "attempting" to mine a PoS block is like so:
- Add a coinbase transaction, and a staking transaction (in most coins, must be hardcoded as the second transaction)
- Prepare block normally, with transactions from network etc
- Compute the PoS "kernel"
- Compute the "staking difficulty", which is the base difficulty, reduced by a ratio of how many coins you are staking (or in PoS version 1.0's case, the coinage of your coins)
- Compare the kernel's hash against the staking difficulty
- If the hash meets the difficulty then continue, otherwise go back to step 1 trying other UTXOs in your wallet that are suitable for staking
- Now you have a valid PoS block. The final step is to sign the block header, proving that you own the staking transaction from step 1.
Now I'll try to go into a bit more depth.
First, the staking transaction is a special transaction that is not possible on the normal Bitcoin blockchain. It includes the concept of negative fees. Because all stakers know the reward, they add this reward to this transaction, meaning that there are more output coins than input coins. This kind of transaction is only valid in a staking context.
Next, the PoS kernel. This is a bit complicated, but the important part is that nothing in it can be easily changed in the context of this block. In the case of blackcoin, the kernel consists of "stake modifier"(I'll explain that in a bit), current block's timestamp, and data from the "txPrev". The txPrev is the transaction of the output which is spent by the staking transaction(ie, the input to the staking transaction). The data pulled from the txPrev includes blocktime, transaction time, hash, and output number (vout 'n').
Because the txPrev data has already been confirmed in the blockchain, it is immutable. The only piece of data that is mutable is the current blocktime. The current blocktime in PoS coins is actually masked though (ie, the bottom bits are set to 0), so that there is very little entropy that can be had by making minor modifications to it. And the blocktime can not be beyond certain network drift limits, or not all nodes will accept the block. Finally the stake modifier is a value generated by taking some entropy bits from the previous (iirc) 64 blocks and hashing it together to form a relatively random number. It's primary purpose is to make computing future block's (beyond the next block) kernel difficult.
Finally, all the data for the kernel is hashed together. The staking difficulty is computed simply. It takes the standard difficulty from Bitcoin, but makes it so that this difficulty is for 1 coin. If you stake 2 coins, then it's only half the difficulty. For 4 coins only a quarter of the difficulty, etc. There are some restrictions to this. In order to prevent someone from being able to control the network for a chain of blocks with a large number of coins, there is a limit to the amount of staking coins, and thus there is a limit on how much the base difficulty can be reduced by.
Finally, a signature is made, proving that the staking transaction actually belongs to the person creating this block. The signature itself goes into the blockheader so that the signature is part of the blockhash.
All of this put together causes the following effects:
- PoS block "mining" does involve hashing and difficulty like PoW, but there are very few mechanisms to change the hash that is given, and so no matter how much computing power you have, it won't help any
- The stake modifier prevents predicting which block you will be able to successfully stake, because it adds a lot of uncontrollable entropy to the kernel hash
- The more coins you stake, the better chance you have at successfully creating a block, because of the weighted difficulty
- In case the network gets stuck due to a sudden drop in the number of people staking, the low-entropy version of the blocktime will eventually allow new kernel hashes to be generated given enough time, giving stakers left on the network a chance to have a successful PoS block
I published this in a blog post, but figured it would fit the QA format of here well and help more people when searching for this answer
Here are some closely related observations on the topic that might help other newbies like me to understand PoS. I spend a couple of hours trying to put things together and to be honest coming from the PoW background it was quite difficult to really grasp why PoS works the way it does. Especially difficult to understand was how does PoS prevent gaining benefits from having more available CPU power. The answer to this question is quite simple: PoS does NOT benefit from having more hash power since the inputs to the hash functions are quite "static" and therefore the output of the hash function within a given time frame is always the same. To clarify, in PoW the input to the hash function includes a nonce and also the tx's data. These inputs are constantly changing and therefore having more CPU power allows trying more combinations that will hopefully lead to generating a valid block hash. With PoS since all inputs remain the same (only the timestamp changes at regular intervals), having more CPU power does not help the miner because the result of running the hash function with the same inputs will generate the same output hash. The only thing that can be done to increase the impact of CPU is to increase the number of UTXO's that a wallet owns by splitting larger UTXO denominations into smaller ones. However, this will lead to a higher difficulty to generate a valid hash. Here are two diagrams that I drew that represent the correlation between the number of UTXO's per wallet, the individual balance of each UTXO, the number of "mining" iterations and consequently the CPU cycles.
Diagram 1 (Increasing the number of UTXO's leads to slower probability for generating a valid block hash):
Diagram 2 (Keeping the number of UTXO's small but with higher denominations per single UTXO increases the probability for generating a valid block hash):
Both diagrams represent the same correlation between the number of UTXO's per wallet and the probability to calculate a valid hash. In Proof-of-Stake the idea is to use the wallet balance as a variable in the calculation of the block difficulty. An example formula for making this calculation could be the one below:
Using that formula, the correlations presented in Diagrams 1 and 2 could be interpreted as follows:
If the validator (miner) tries to split his UTXO's into smaller denominations and thus increasing the number of UTXO's that the wallet has, the difficulty of calculating a new hash increases. The reason for this is that the balance of each individual UTXO(i) will be smaller, thus balance(UTXO(i)) / difficulty will be a really small number and it will be harder to generate a valid hash.