update spec for Merkle RFC 6962 (#3175)

* spec: specify when MerkleRoot is on hashes

* remove unnecessary hash methods

* update changelog

* fix test
This commit is contained in:
Ethan Buchman
2019-01-21 10:02:57 -05:00
committed by GitHub
parent de5a6010f0
commit 7a8aeff4b0
7 changed files with 40 additions and 34 deletions

View File

@@ -51,7 +51,7 @@ type Header struct {
// hashes of block data
LastCommitHash []byte // commit from validators from the last block
DataHash []byte // MerkleRoot of transactions
DataHash []byte // MerkleRoot of transaction hashes
// hashes from the app output from the prev block
ValidatorsHash []byte // validators for the current block
@@ -303,7 +303,7 @@ The first block has `block.Header.LastBlockID == BlockID{}`.
### LastCommitHash
```go
block.Header.LastCommitHash == MerkleRoot(block.LastCommit)
block.Header.LastCommitHash == MerkleRoot(block.LastCommit.Precommits)
```
MerkleRoot of the votes included in the block.
@@ -314,10 +314,15 @@ The first block has `block.Header.LastCommitHash == []byte{}`
### DataHash
```go
block.Header.DataHash == MerkleRoot(block.Txs.Txs)
block.Header.DataHash == MerkleRoot(Hashes(block.Txs.Txs))
```
MerkleRoot of the transactions included in the block.
MerkleRoot of the hashes of transactions included in the block.
Note the transactions are hashed before being included in the Merkle tree,
so the leaves of the Merkle tree are the hashes, not the transactions
themselves. This is because transaction hashes are regularly used as identifiers for
transactions.
### ValidatorsHash

View File

@@ -213,7 +213,7 @@ func innerHash(left []byte, right []byte) []byte {
// largest power of 2 less than k
func getSplitPoint(k int) { ... }
func MerkleRoot(leafs [][]byte) []byte{
func MerkleRoot(items [][]byte) []byte{
switch len(items) {
case 0:
return nil
@@ -228,10 +228,20 @@ func MerkleRoot(leafs [][]byte) []byte{
}
```
Note: `MerkleRoot` operates on items which are arbitrary byte arrays, not
necessarily hashes. For items which need to be hashed first, we introduce the
`Hashes` function:
```
func Hashes(items [][]byte) [][]byte {
return SHA256 of each item
}
```
Note: we will abuse notion and invoke `MerkleRoot` with arguments of type `struct` or type `[]struct`.
For `struct` arguments, we compute a `[][]byte` containing the hash of each
For `struct` arguments, we compute a `[][]byte` containing the amino encoding of each
field in the struct, in the same order the fields appear in the struct.
For `[]struct` arguments, we compute a `[][]byte` by hashing the individual `struct` elements.
For `[]struct` arguments, we compute a `[][]byte` by amino encoding the individual `struct` elements.
### Simple Merkle Proof

View File

@@ -60,7 +60,7 @@ When hashing the Validator struct, the address is not included,
because it is redundant with the pubkey.
The `state.Validators`, `state.LastValidators`, and `state.NextValidators`, must always by sorted by validator address,
so that there is a canonical order for computing the SimpleMerkleRoot.
so that there is a canonical order for computing the MerkleRoot.
We also define a `TotalVotingPower` function, to return the total voting power: