hypersign-protocol / whitepaper

2 stars 0 forks source link

Research on verifiable snapshots/checkpoints #4

Closed Vishwas1 closed 2 years ago

Vishwas1 commented 2 years ago

Note: polygon

How L2 gets linked to L1 or L3 gets linked with L2? Or in other word, how can subchchains obtains security from main chain? Check out how polygon are doing There is this concept of Checkpointing “for every few blocks on the block layer (subchain) of the Matic Network, a proposer will be chosen among the stakeholders to propose a checkpoint on the main chain.” These checkpoints are created by the proposer after validating all the blocks on the block layer of the Matic Network and creating the Merkle tree of the block hashes since the last checkpoint. The Merkle root is then broadcasted to the Staker network for their signatures. The other stakeholders also verify the proof. They will approve the proposed block, if it is valid, by providing their signatures.

https://github.com/maticnetwork/whitepaper#consensus-con

Vishwas1 commented 2 years ago

What is checkpoints?

Checkpoint is noting about Merkle root hash of Merkle tree of the block hashes since the last checkpoint.

Why Checkpoints?

To gain security from Ethereum main net.

How checkpointing works in polygon?

  1. Users send transactions on BOR
  2. Blocks are formed on BOR by one of the nodes
  3. Heimdall queries a smart contract deployed at BOR to get few blocks
  4. A proposer at Heimdall then generates the checkpoint
    Checkpoints data st.

    {
    start_block,
    end_block,
    timestamp,
    proposserAddr,
    rootHash // Merkel root of merkle tree of blocks   
    }
  5. And sends it to the Ethereum main net via a [smart contract] (https://etherscan.io/address/0x536c55cFe4892E581806e10b38dFE8083551bd03#code) method call submitCheckpoint()

      function submitCheckpoint(bytes calldata data, uint[3][] calldata sigs) external {
        (address proposer, uint256 start, uint256 end, bytes32 rootHash, bytes32 accountHash, uint256 _borChainID) = abi
            .decode(data, (address, uint256, uint256, bytes32, bytes32, uint256));
        require(CHAINID == _borChainID, "Invalid bor chain id");
    
        require(_buildHeaderBlock(proposer, start, end, rootHash), "INCORRECT_HEADER_DATA");
    
        // check if it is better to keep it in local storage instead
        IStakeManager stakeManager = IStakeManager(registry.getStakeManagerAddress());
        uint256 _reward = stakeManager.checkSignatures(
            end.sub(start).add(1),
            /**  
                prefix 01 to data 
                01 represents positive vote on data and 00 is negative vote
                malicious validator can try to send 2/3 on negative vote so 01 is appended
             */
            keccak256(abi.encodePacked(bytes(hex"01"), data)),
            accountHash,
            proposer,
            sigs
        );
    
        require(_reward != 0, "Invalid checkpoint");
        emit NewHeaderBlock(proposer, _nextHeaderBlock, _reward, start, end, rootHash);
        _nextHeaderBlock = _nextHeaderBlock.add(MAX_DEPOSITS);
        _blockDepositId = 1;
    }
  6. The submitCheckpoint() forms block and assigns block number to the checkpoint data st.
  7. The submitCheckpoint() emits an event NewHeaderBlock about the successful block creation
      emit NewHeaderBlock(proposer, _nextHeaderBlock, _reward, start, end, rootHash);
  8. Heimdall nodes keeps listening to this event. code
       ....
      case "NewHeaderBlock":
                    if isCurrentValidator, delay := util.CalculateTaskDelay(rl.cliCtx); isCurrentValidator {
                        rl.sendTaskWithDelay("sendCheckpointAckToHeimdall", selectedEvent.Name, logBytes, delay)
                    }
       ...
  9. And forms the ACK message. code

     // create msg checkpoint ack message
        msg := checkpointTypes.NewMsgCheckpointAck(
            helper.GetFromAddress(cp.cliCtx),
            checkpointNumber.Uint64(),
            hmTypes.BytesToHeimdallAddress(event.Proposer.Bytes()),
            event.Start.Uint64(),
            event.End.Uint64(),
            event.Root,
            hmTypes.BytesToHeimdallHash(log.TxHash.Bytes()),
            uint64(log.Index),
        )
  10. And finally broadcasts to all Heimdall nodes about this ACK. code

     // return broadcast to heimdall
        if err := cp.txBroadcaster.BroadcastToHeimdall(msg); err != nil {
            cp.Logger.Error("Error while broadcasting checkpoint-ack to heimdall", "error", err)
            return err
        }

Problems

Next Step

arnabghose997 commented 2 years ago

Smart Contracts in focus

Heimdall Mainnet REST API: