type CheckpointBlockHeader struct { // Proposer is selected based on stake Proposer types.HeimdallAddress `json:"proposer"`
// StartBlock: The block number on Bor from which this checkpoint starts StartBlock uint64`json:"startBlock"`
// EndBlock: The block number on Bor from which this checkpoint ends EndBlock uint64`json:"endBlock"`
// RootHash is the Merkle root of all the leaves containing the block // headers starting from start to the end block RootHash types.HeimdallHash `json:"rootHash"`
// Account root hash for each validator // Hash of data that needs to be passed from Heimdall to Ethereum chain like slashing, withdraw topup etc. AccountRootHash types.HeimdallHash `json:"accountRootHash"`
// Timestamp when checkpoint was created on Heimdall TimeStamp uint64`json:"timestamp"` }
注意:这里 checkpoint 的提交是基于 bor 的StartBlock到EndBlock之间的区块,这点很重要。 bor是基于Ethereum协议实现的底层链。官方定义
blockHash
1
blockHash = keccak256([number, time, tx hash, receipt hash])
rootHash
1 2 3 4 5 6 7 8 9
B(1) := keccak256([number, time, tx hash, receipt hash]) B(2) := keccak256([number, time, tx hash, receipt hash]) . . . B(n) := keccak256([number, time, tx hash, receipt hash])
// checkpoint is Merkle root of all block hash checkpoint's root hash = Merkel[B(1), B(2), ....., B(n)]
// Golang representation of block data used in checkpoint blockData := crypto.Keccak256(appendBytes32( blockHeader.Number.Bytes(), new(big.Int).SetUint64(blockHeader.Time).Bytes(), blockHeader.TxHash.Bytes(), blockHeader.ReceiptHash.Bytes(), ))
// array of block hashes of Bor blocks headers := [blockData1, blockData2, ..., blockDataN]
// merkel tre tree := merkle.NewTreeWithOpts(merkle.TreeOptions{EnableHashSorting: false, DisableHashLeaves: true}) tree.Generate(convert(headers), sha3.NewLegacyKeccak256())