Merkle Tree

什么是 Merkle Tree

  1. Merkle(默克尔)树通常又被叫做 Hash 树,该树的名字来源于他的专利作者Ralph Merkle。
  2. 它是一个非线性的二叉树。
  3. 该树可用于对大量数据中的内容进行有效且安全的一致性验证,而无需访问整个数据集。

如何构建树

叶子节点:

该叶子节点对应数据的 Hash值。没有固定的hash算法,例如 SHA-256 或者 Keccak 以及 SHA3-256。

非叶子节点:

该节点的所有子节点的 Hash。例如 C 有 A,B两个子节点,那么 C = hash(AB)。

在这里插入图片描述

如果某一回合计算出现了奇数个节点,那么将最后一个节点复制一份并与它自己做 Hash.

在这里插入图片描述

示例

下面是一个简单的计算 默克尔树根的示例。

package main

import (
	"encoding/hex"
	"fmt"
	"golang.org/x/crypto/sha3"
	"math"
)

// HashLength is expected length of hash.
const HashLength = 32

// Hash represents 32 byte SHA3-256 hash of arbitrary data.
type Hash [HashLength]byte

// Bytes gets the byte representation of h.
func (h Hash) Bytes() []byte {
	return h[:]
}

// Hex returns the hex representation of h, prefixed with '0x'.
func (h Hash) Hex() string {
	enc := make([]byte, len(h)*2+2)
	copy(enc, "0x")
	hex.Encode(enc[2:], h[:])
	return string(enc)
}

// SetBytes sets the h to the value of b.
// if b is larger than len(h), b will be cropped from the left.
func (h *Hash) SetBytes(b []byte) {
	if len(b) > len(h) {
		b = b[len(b)-HashLength:]
	}
	copy(h[HashLength-len(b):], b)
}

// sha3-256
func sha3256(h1 Hash, h2 *Hash) (h Hash) {
	fn := sha3.New256()
	fn.Write(h1[:])
	if h2 == nil {
		fn.Write(h1[:])
	} else {
		fn.Write(h2[:])
	}
	h.SetBytes(fn.Sum(nil))
	return
}

// ComputeMerkleRoot computes merkle root of given hashes.
// This will modify the input array, the result at index 0.
func ComputeMerkleRoot(hashes []Hash) {
	var i, j, z, l = 0, 0, 0, len(hashes)
	arr := hashes
	for l > 1 {
		for ; i < l; i++ {
			var right *Hash
			z = i + 1
			if z < l {
				right = &(arr[z])
			}
			arr[j] = sha3256(arr[i], right)
			fmt.Println(arr[j].Hex())
			j++
			i = z
		}
		fmt.Println("---------------------------------------------------------------")
		l = int(math.Ceil(float64(l)/2))
		i, j = 0, 0
	}
}

// newSha3256Hash creates a Hash object with sha3-256(str)
func newSha3256Hash(str string) Hash {
	var h Hash
	b := sha3.Sum256([]byte(str))
	h.SetBytes(b[:])
	return h
}

func main() {
	hashes := make([]Hash, 5)
	hashes[0] = newSha3256Hash("Hello")
	hashes[1] = newSha3256Hash("World")
	hashes[2] = newSha3256Hash("Merkle")
	hashes[3] = newSha3256Hash("Tree")
	hashes[4] = newSha3256Hash("Joel")
	ComputeMerkleRoot(hashes)
	fmt.Println(hashes[0].Hex())
}

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值