// Copyright Fuzamei Corp. 2018 All Rights Reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package merkle import ( "bytes" "crypto/sha256" "github.com/33cn/chain33/types" ) /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind that the following merkle tree algorithm has a serious flaw related to duplicate txids, resulting in a vulnerability (CVE-2012-2459). The reason is that if the number of hashes in the list at a given time is odd, the last one is duplicated before computing the next level (which is unusual in Merkle trees). This results in certain sequences of transactions leading to the same merkle root. For example, these two trees: A A / \ / \ B C B C / \ | / \ / \ D E F D E F F / \ / \ / \ / \ / \ / \ / \ 1 2 3 4 5 6 1 2 3 4 5 6 5 6 for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and 6 are repeated) result in the same root hash A (because the hash of both of (F) and (F,F) is C). The vulnerability results from being able to send a block with such a transaction list, with the same merkle root, and the same block hash as the original without duplication, resulting in failed validation. If the receiving node proceeds to mark that block as permanently invalid however, it will fail to accept further unmodified (and thus potentially valid) versions of the same block. We defend against this by detecting the case where we would hash two identical hashes at the end of the list together, and treating that identically to the block having an invalid merkle root. Assuming no double-SHA256 collisions, this will detect all known ways of changing the transactions without affecting the merkle root. */ /*Computation This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */ //flage =1 只计算roothash flage =2 只计算branch flage =3 计算roothash 和 branch func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, mutated bool, pbranch [][]byte) { if len(leaves) == 0 { return nil, false, nil } if flage < 1 || flage > 3 { return nil, false, nil } var count int var branch [][]byte var level uint32 var h []byte inner := make([][]byte, 32) var matchlevel uint32 = 0xff mutated = false var matchh bool for count, h = range leaves { if (uint32(count) == branchpos) && (flage&2) != 0 { matchh = true } else { matchh = false } count++ // 1左移level位 for level = 0; 0 == ((count) & (1 << level)); level++ { //需要计算branch if (flage & 2) != 0 { if matchh { branch = append(branch, inner[level]) } else if matchlevel == level { branch = append(branch, h) matchh = true } } if bytes.Equal(inner[level], h) { mutated = true } //计算inner[level] + h 的hash值 h = GetHashFromTwoHash(inner[level], h) } inner[level] = h if matchh { matchlevel = level } } for level = 0; 0 == (count & (1 << level)); level++ { } h = inner[level] matchh = matchlevel == level for count != (1 << level) { if (flage&2) != 0 && matchh { branch = append(branch, h) } h = GetHashFromTwoHash(h, h) count += (1 << level) level++ // And propagate the result upwards accordingly. for 0 == (count & (1 << level)) { if (flage & 2) != 0 { if matchh { branch = append(branch, inner[level]) } else if matchlevel == level { branch = append(branch, h) matchh = true } } h = GetHashFromTwoHash(inner[level], h) level++ } } return h, mutated, branch } //GetHashFromTwoHash 计算左右节点hash的父hash func GetHashFromTwoHash(left []byte, right []byte) []byte { if left == nil || right == nil { return nil } leftlen := len(left) rightlen := len(right) parent := make([]byte, leftlen+rightlen) copy(parent, left) copy(parent[leftlen:], right) hash := sha256.Sum256(parent) parenthash := sha256.Sum256(hash[:]) return parenthash[:] } //GetMerkleRoot 获取merkle roothash func GetMerkleRoot(leaves [][]byte) (roothash []byte) { if leaves == nil { return nil } proothash, _, _ := Computation(leaves, 1, 0) return proothash } //GetMerkleBranch 获取指定txindex的branch position 从0开始 func GetMerkleBranch(leaves [][]byte, position uint32) [][]byte { _, _, branchs := Computation(leaves, 2, position) return branchs } //GetMerkleRootFromBranch 通过branch 获取对应的roothash 用于指定txhash的proof证明 func GetMerkleRootFromBranch(merkleBranch [][]byte, leaf []byte, Index uint32) []byte { hash := leaf for _, branch := range merkleBranch { if (Index & 1) != 0 { hash = GetHashFromTwoHash(branch, hash) } else { hash = GetHashFromTwoHash(hash, branch) } Index >>= 1 } return hash } //GetMerkleRootAndBranch 获取merkle roothash 以及指定tx index的branch,注释:position从0开始 func GetMerkleRootAndBranch(leaves [][]byte, position uint32) (roothash []byte, branchs [][]byte) { roothash, _, branchs = Computation(leaves, 3, position) return } var zeroHash [32]byte //CalcMerkleRoot 计算merkle树根 func CalcMerkleRoot(txs []*types.Transaction) []byte { var hashes [][]byte for _, tx := range txs { hashes = append(hashes, tx.Hash()) } if hashes == nil { return zeroHash[:] } merkleroot := GetMerkleRoot(hashes) if merkleroot == nil { panic("calc merkle root error") } return merkleroot } //CalcMerkleRootCache 计算merkle树根缓存 func CalcMerkleRootCache(txs []*types.TransactionCache) []byte { var hashes [][]byte for _, tx := range txs { hashes = append(hashes, tx.Hash()) } if hashes == nil { return zeroHash[:] } merkleroot := GetMerkleRoot(hashes) if merkleroot == nil { panic("calc merkle root error") } return merkleroot }