一文了解Merkle Patricia Trie这种数据结构

基础概念

1. Trie(字典树)

Trie 是一种树形数据结构,用于存储键值对。键通常是字符串,树的每一层代表键的一个字符。例如:

  • 插入键值对 ("apple", 10),路径是 a -> p -> p -> l -> e
  • 插入键值对 ("app", 20),路径是 a -> p -> p

2. Patricia Trie(压缩前缀树)

Patricia Trie 是对 Trie 的优化,通过合并只有一个子节点的路径来压缩树。例如:

  • 如果路径 a -> p -> p 只有一个子节点,可以压缩为一个节点 app

3. Merkle Tree

Merkle Tree 是一种树结构,每个节点存储其子节点的哈希值。根节点的哈希值可以用于验证整个树的数据完整性。

4. Merkle Patricia Trie

Merkle Patricia Trie 结合了 Patricia Trie 和 Merkle Tree:

  • 使用 Patricia Trie 存储键值对。
  • 每个节点存储其内容的哈希值,形成 Merkle Tree。

示例

假设我们有以下键值对:

  • ("dog", 10)
  • ("doge", 20)
  • ("cat", 30)

Trie 结构

  1. 插入 ("dog", 10)

    rust 复制代码
    root -> d -> o -> g (value=10)
  2. 插入 ("doge", 20)

    ini 复制代码
    root -> d -> o -> g (value=10)
                       -> e (value=20)
  3. 插入 ("cat", 30)

    rust 复制代码
    root -> c -> a -> t (value=30)
          -> d -> o -> g (value=10)
                       -> e (value=20)

Patricia Trie 结构

压缩路径:

ini 复制代码
root -> c -> at (value=30)
      -> d -> og (value=10)
            -> e (value=20)

Merkle Patricia Trie

为每个节点计算哈希值,形成 Merkle Tree。


Go 实现

以下是一个简化版的 MPT 实现:

go 复制代码
package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
)

type Node struct {
	Value    int
	Children map[byte]*Node
}

type MerklePatriciaTrie struct {
	Root *Node
}

func NewMerklePatriciaTrie() *MerklePatriciaTrie {
	return &MerklePatriciaTrie{Root: &Node{Children: make(map[byte]*Node)}}
}

func (mpt *MerklePatriciaTrie) Insert(key string, value int) {
	current := mpt.Root
	for i := 0; i < len(key); i++ {
		char := key[i]
		if current.Children[char] == nil {
			current.Children[char] = &Node{Children: make(map[byte]*Node)}
		}
		current = current.Children[char]
	}
	current.Value = value
}

func (mpt *MerklePatriciaTrie) Get(key string) (int, bool) {
	current := mpt.Root
	for i := 0; i < len(key); i++ {
		char := key[i]
		if current.Children[char] == nil {
			return 0, false
		}
		current = current.Children[char]
	}
	return current.Value, true
}

func (mpt *MerklePatriciaTrie) Hash() string {
	return calculateHash(mpt.Root)
}

func calculateHash(node *Node) string {
	if node == nil {
		return ""
	}
	hash := sha256.New()
	for char, child := range node.Children {
		hash.Write([]byte{char})
		hash.Write([]byte(calculateHash(child)))
	}
	hash.Write([]byte(fmt.Sprintf("%d", node.Value)))
	return hex.EncodeToString(hash.Sum(nil))
}

func main() {
	mpt := NewMerklePatriciaTrie()
	mpt.Insert("dog", 10)
	mpt.Insert("doge", 20)
	mpt.Insert("cat", 30)

	value, exists := mpt.Get("dog")
	fmt.Println("Get dog:", value, exists) // Output: 10 true

	fmt.Println("Root Hash:", mpt.Hash())
}

Node.js 实现

以下是一个简化版的 MPT 实现:

javascript 复制代码
const crypto = require('crypto');

class Node {
    constructor() {
        this.value = null;
        this.children = new Map();
    }
}

class MerklePatriciaTrie {
    constructor() {
        this.root = new Node();
    }

    insert(key, value) {
        let current = this.root;
        for (let char of key) {
            if (!current.children.has(char)) {
                current.children.set(char, new Node());
            }
            current = current.children.get(char);
        }
        current.value = value;
    }

    get(key) {
        let current = this.root;
        for (let char of key) {
            if (!current.children.has(char)) {
                return null;
            }
            current = current.children.get(char);
        }
        return current.value;
    }

    hash() {
        return this.calculateHash(this.root);
    }

    calculateHash(node) {
        const hash = crypto.createHash('sha256');
        if (node) {
            for (let [char, child] of node.children) {
                hash.update(char);
                hash.update(this.calculateHash(child));
            }
            hash.update(node.value !== null ? node.value.toString() : '');
        }
        return hash.digest('hex');
    }
}

const mpt = new MerklePatriciaTrie();
mpt.insert("dog", 10);
mpt.insert("doge", 20);
mpt.insert("cat", 30);

console.log("Get dog:", mpt.get("dog")); // Output: 10
console.log("Root Hash:", mpt.hash());

总结

  • Merkle Patricia Trie 是一种高效的数据结构,结合了 Patricia Trie 的压缩特性和 Merkle Tree 的哈希验证特性。
  • 通过 Go 和 Node.js 的示例,你可以看到如何实现一个简化版的 MPT。
  • 实际应用中(如以太坊),MPT 的实现会更复杂,涉及更多的优化和细节处理。
相关推荐
_GR39 分钟前
2025年蓝桥杯第十六届C&C++大学B组真题及代码
c语言·数据结构·c++·算法·贪心算法·蓝桥杯·动态规划
shinelord明2 小时前
【软件系统架构】事件驱动架构
数据结构·设计模式·架构·系统架构·软件工程
照海19Gin2 小时前
数据结构中的宝藏秘籍之广义表
c语言·数据结构·算法
大炮筒2 小时前
CPPlist初识
数据结构·c++·list
浅浅2803 小时前
numpy、pandas内存优化操作整理
数据结构·经验分享·python·学习·性能优化·numpy·pandas
bloxd yzh3 小时前
筛选法(埃氏筛法)C++
数据结构·算法
那就摆吧3 小时前
数据结构-栈
android·java·c语言·数据结构
L_09073 小时前
【C】初阶数据结构10 -- 希尔排序
c语言·数据结构·排序算法
刘 大 望3 小时前
Java写数据结构:栈
java·开发语言·数据结构
暖阳冷月海无涯3 小时前
数据结构-C语言版本(四)队列
c语言·数据结构