当前位置: 首页 > news >正文

稀疏默克尔树实现

稀疏默克尔树实现

package org.example;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;// Node 类
class Node {private final Node left;private final Node right;private final byte[] hash;private final boolean isLeaf;Node(Node left, Node right, byte[] zeroHash) {this.left = left;this.right = right;this.isLeaf = false;this.hash = combineHashes(left, right, zeroHash);}Node(byte[] valueHash) {this.left = null;this.right = null;this.hash = valueHash;this.isLeaf = true;}byte[] getHash() {return hash;}Node getLeft() {return left;}Node getRight() {return right;}boolean isLeaf() {return isLeaf;}private static byte[] combineHashes(Node left, Node right, byte[] zeroHash) {byte[] leftHash = left != null ? left.getHash() : zeroHash;byte[] rightHash = right != null ? right.getHash() : zeroHash;return SparseMerkleTree.hash(leftHash, rightHash);}
}// 证明节点
class ProofNode {private final byte[] hash;private final char direction;ProofNode(byte[] hash, char direction) {this.hash = hash;this.direction = direction;}byte[] getHash() {return hash;}char getDirection() {return direction;}
}// 证明集合
class MerkleProof {private final List<ProofNode> proofNodes = new ArrayList<>();void add(ProofNode node) {proofNodes.add(node);}ProofNode get(int index) {return proofNodes.get(index);}int size() {return proofNodes.size();}
}public class SparseMerkleTree {private static final MessageDigest DIGEST;static {try {DIGEST = MessageDigest.getInstance("SHA-256");} catch (NoSuchAlgorithmException e) {throw new RuntimeException("SHA-256 not available", e);}}private final int height;private final byte[][] zeroHashes;private Node root;public SparseMerkleTree(int height) {this.height = height;this.zeroHashes = new byte[height + 1][];this.zeroHashes[0] = hash(new byte[0]);for (int i = 1; i <= height; i++) {this.zeroHashes[i] = hash(zeroHashes[i - 1], zeroHashes[i - 1]);}this.root = new Node(null, null, zeroHashes[0]);}public void insert(byte[] key, byte[] value) {byte[] keyHash = hash(key);byte[] valueHash = hash(value);byte[] path = getBinaryPath(keyHash, height);root = update(root, path, 0, valueHash, zeroHashes);}private Node update(Node node, byte[] path, int depth, byte[] valueHash, byte[][] zeroHashes) {if (depth == height) {return new Node(valueHash);}// 修复:当 node 为 null 时创建空节点if (node == null) {node = new Node(null, null, zeroHashes[depth + 1]);}boolean isLeft = getPathBit(path, depth);byte[] currentZeroHash = zeroHashes[depth + 1];Node left = node.getLeft();Node right = node.getRight();if (isLeft) {Node newLeft = update(left, path, depth + 1, valueHash, zeroHashes);return new Node(newLeft, right, currentZeroHash);} else {Node newRight = update(right, path, depth + 1, valueHash, zeroHashes);return new Node(left, newRight, currentZeroHash);}}public MerkleProof generateProof(byte[] key) {MerkleProof proof = new MerkleProof();byte[] keyHash = hash(key);byte[] path = getBinaryPath(keyHash, height);Node current = root;for (int depth = 0; depth < height; depth++) {if (current == null || current.isLeaf()) {break;}boolean isLeft = getPathBit(path, depth);Node sibling;char direction;if (isLeft) {sibling = current.getRight();direction = 'R';} else {sibling = current.getLeft();direction = 'L';}byte[] siblingHash = sibling != null ? sibling.getHash() : zeroHashes[depth + 1];proof.add(new ProofNode(siblingHash, direction));current = isLeft ? current.getLeft() : current.getRight();}return proof;}public boolean verifyProof(byte[] key, byte[] value, MerkleProof proof) {byte[] valueHash = hash(value);byte[] currentHash = valueHash;byte[] keyHash = hash(key);byte[] path = getBinaryPath(keyHash, height);for (int i = 0; i < proof.size(); i++) {ProofNode node = proof.get(i);boolean isLeft = getPathBit(path, i);if (node.getDirection() == 'L') {currentHash = hash(currentHash, node.getHash());} else {currentHash = hash(node.getHash(), currentHash);}}return Arrays.equals(currentHash, root.getHash());}// 哈希函数public static byte[] hash(byte[] data) {return DIGEST.digest(data);}public static byte[] hash(byte[] left, byte[] right) {byte[] combined = new byte[left.length + right.length];System.arraycopy(left, 0, combined, 0, left.length);System.arraycopy(right, 0, combined, left.length, right.length);return hash(combined);}// 将字节数组转为二进制路径private byte[] getBinaryPath(byte[] keyHash, int height) {StringBuilder binary = new StringBuilder();for (byte b : keyHash) {for (int i = 7; i >= 0; i--) {binary.append((b >> i) & 1);}}String binaryStr = binary.toString();if (binaryStr.length() < height) {binaryStr = binaryStr.substring(0, Math.min(binaryStr.length(), height));} else {binaryStr = binaryStr.substring(0, height);}byte[] path = new byte[binaryStr.length()];for (int i = 0; i < path.length; i++) {path[i] = (byte) (binaryStr.charAt(i) - '0');}return path;}private boolean getPathBit(byte[] path, int depth) {return path[depth] == 0;}// 示例用法public static void main(String[] args) {SparseMerkleTree tree = new SparseMerkleTree(4);byte[] key1 = "hello".getBytes();byte[] value1 = "world".getBytes();tree.insert(key1, value1);MerkleProof proof = tree.generateProof(key1);boolean verified = tree.verifyProof(key1, value1, proof);System.out.println("Verification: " + verified); // 应输出 true}
}

calcRoot=5be9e3dcaeea831e5c4b1eb6cd67c9f18e12ed5e8918afbc84217e27e39569f6
treeRoot=365d138ad97fdf6c5836d9bd44946daf4c4fdeda5c1b5da0bf1f4445a1ca3ae0
Verification: false

http://www.dtcms.com/a/457897.html

相关文章:

  • jsp基于JavaWeb的原色蛋糕商城的设计与实现(代码+数据库+LW)
  • 松原市住房和城乡建设厅网站wordpress 抓取微信
  • 深入洞察:V模型架构实现业务到IT的服务化设计
  • 从“国庆景区人山人海”看大数据处理中的“数据倾斜”难题
  • 免费自建 响应式 网站作图网站
  • 2025-10-08 Python 标准库 7——内置类型:二进制序列
  • 餐饮业建设网站意义音乐网站的设计
  • ip对网站作用网站开发后台做些什么
  • numpy -- 算术函数 reciprocal() 和 power() 简介
  • 面向中小型制造企业的SaaS版MES解决方案
  • 华为网站建设南通门户网站建设方案
  • Docker安装部署本地对象存储Minio和使用指南
  • 怎么看网站是什么程序营销网站开发选哪家
  • Spring Boot综合项目实战 - 西蒙购物网
  • 西安房产网站大全注册网址在哪里注册
  • 营口网站建设wordpress 添加付款
  • 深度学习和机器学习的区别,联邦学习和隐私计算的区别
  • 98.验证二叉搜索树(二叉树算法题)
  • linux信号(2)——从“暂停咖啡机”看SIGINT:用户与程序的“紧急停止按钮”
  • asp网站安全南京移动网站建设
  • leetcode hot100 中等难度 day05-刷题
  • 企业网站每年的费用wordpress目录魔板
  • 做一个小公司网站多少钱网站备案归属地
  • Access调用Azure翻译:轻松实现系统多语言切换
  • R语言从入门到精通Day5之【数据输入】
  • 网站开发挣不挣钱南通网站建设知识
  • 仿手机底部导航栏制作
  • 二维码生成的技术原理与全场景实践
  • 做网站 嵌入支付wordpress优化攻略
  • Chromium Embedded Framework (CEF)的构建及运行