libplanet icon indicating copy to clipboard operation
libplanet copied to clipboard

🛑 Remove `PreEvaluationBlock`

Open riemannulus opened this issue 1 year ago • 3 comments

Context

PreEvaluationBlock played an important role in the days when Libplanet ran on PoW. The idea of ​​HashRandom, which determines the Hash before executing a transaction and uses it as a Random Seed, has always been a core concept of Libplanet.

However, now that the PBFT consensus algorithm has been adopted, there is less reason to use this method. Rather, the problem is that Hash is easy to manipulate, making it easy to use the transaction results as desired.

We attempted to introduce VRF to solve this problem, but it is difficult to introduce VRF in its current form as the StateRootHash of the nth block contains the execution result of the nth block.

Therefore, we would like to proceed with a more flexible and reliable chain consensus by deleting PreEvaluationBlock and making StateRootHash look at the execution results of the previous block.

Rationale

We must check the point below.

  • Meaning of genesis block.
  • How to store the nth block's state root hash.
  • Side effect of changes.

riemannulus avatar Apr 16 '24 07:04 riemannulus

Meaning of genesis block

For now, Block.StateRootHash is a root hash of the state after state transition, which is triggered by Block.Transactions. So, Block proves the result of the Block.Transaction, so if someone finds state whose root hash is equal to Block.StateRootHash, he can believe that state is result state of Block.

After above change applied, there's no way to prove some state is a result state of Block, without computing state transition, so meaning of Block has been changed slightly.

Now Block means a set of previous state and transactions, which was a set of transactions and result state (a, s') => (s, a), which means almost same as current PreEvaluationBlock.

For the genesis block, it meant "world setter transactions" and "state after world setter transactions" previously, but this have to be redefined.

IMO, What we have to decide is, whether define genesis block as

  • Empty state + World setter transactions or
  • State after world setter transactions + Empty transactions -> (I think it doesn't have to be empty though)

From a different point of view, we can remove genesis block, starting 1st block with consensus.

OnedgeLee avatar Apr 16 '24 08:04 OnedgeLee

How to store the nth block's state root hash

Below methods will be added to IStore interface.

  • void PutNextStateRootHash(BlockHash hash, HashDigest<SHA256> stateRootHash)
  • HashDigest<SHA256> GetNextStateRootHash(BlockHash hash)

BlockChain.Append() will check below additionally.

  • GetNextStateRootHash(block.PreviousHash).Equals(block.StateRootHash)

BlockChain will hold additional event handler.

  • event EventHandler<(Block block, HashDigest<SHA256> stateRootHash)> NextStateRootHashEvaluated
  • Above event will be triggered in the BlockChain.Append(), after IStateStore.PutNextStateRootHash() called

Context.IsValid(Block block) will be suspended until BlockChain.NextStateRootHashEvaluated triggered.

OnedgeLee avatar Apr 17 '24 01:04 OnedgeLee

Redefine StateRootHash

  • [x] Update IStore
  • [x] Update BlockChain.Append()
  • [x] Update BlockChain.ValidateBlock()
  • [x] Update BlockChain.Propose()
  • [x] Update tests for blockchain
  • [ ] Update Consensus.IsValid()
  • [ ] Update tests for consensus
  • [ ] Update queries for IWorldState

Introduce Proof

Generate random seed from Proof

Remove PreEvaluationBlock

OnedgeLee avatar Apr 18 '24 05:04 OnedgeLee