稀疏默克尔树实现
稀疏默克尔树实现
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