Merkle 树

Merkle Tree

  1. 叶子节点为奇数时,复制最后一个;然后由所有叶子节点构造一个满二叉树
  2. List 第 0 个存放空,root 放在第 1 个。则第 i 个叶子节点在 list 中的下标为 k = i + list.size() / 2; 由叶子节点往上需要获取的节点为 k % 2 == 0 ? k+1 : k-1,然后 k=k/2 往上递归直到 root,即 1。
public class MT {

	private static final Logger logger = LoggerFactory.getLogger(MT.class);

	List<HashNode> leaves;

	List<HashNode> list = new ArrayList<>();

	HashNode root;

	public MT(List<HashNode> leaves) {
		this.leaves = leaves;
		list.add(new HashNode("", null, null));
	}

	public static void main(String[] args) {
		List<HashNode> leaves = new ArrayList<>();
		for (String h : Arrays.asList("a", "b", "c", "d", "e", "f", "g")) {
			leaves.add(new HashNode(h, null, null));
		}
		MT mt = new MT(leaves);
		mt.buildFromLeaves();
		logger.info("root:{}, hashNodes:{}", mt.root, mt.list.subList(1, mt.list.size()));

		for (int i = 0; i < leaves.size(); i++) {
			logger.info("hashes:{}", mt.getHashes(i));
		}

		List<HashNode> hashes = mt.getHashes(0);

		int k = 0;
		String calRootHash = leaves.get(k).hash;
		for (HashNode h : hashes) {
			if (k % 2 == 0) calRootHash = hash(calRootHash, h.hash);
			else calRootHash = hash(h.hash, calRootHash);
		}
		logger.info("calRootHash:{}, rootHash:{}", calRootHash, mt.root.hash);
	}

	private static String hash(String l, String r) {
		return l + "-" + r;
	}

	private static List<HashNode> fromSubLayer(List<HashNode> subLayer) {
		List<HashNode> currentLayer = new ArrayList<>();
		for (int i = 0; i < subLayer.size(); i += 2) {
			HashNode left = subLayer.get(i);
			HashNode right = subLayer.get(i + 1);
			currentLayer.add(new HashNode(hash(left.hash, right.hash), left, right));
		}
		return currentLayer;
	}

	private List<HashNode> getHashes(int i) {
		int k = i + list.size() / 2;
		List<HashNode> result = new ArrayList<>();
		while (k / 2 >= 1) {
			if (k % 2 == 0) result.add(list.get(k + 1));
			else result.add(list.get(k - 1));
			k = k / 2;
		}
		return result;
	}

	private void buildFromLeaves() {
		if (leaves.size() % 2 == 1) leaves.add(leaves.get(leaves.size() - 1));
		List<HashNode> temp = leaves;
		do {
			list.addAll(1, temp);
			temp = fromSubLayer(temp);
		} while (temp.size() > 1);
		list.addAll(1, temp);
		root = list.get(1);
	}

	private static class HashNode {
		String hash;

		HashNode l, r;

		public HashNode(String hash, HashNode l, HashNode r) {
			this.hash = hash;
			this.l = l;
			this.r = r;
		}

		@Override
		public String toString() {
			return hash;
		}
	}

}

posted on 2018-06-12 20:43  ppcoin  阅读(168)  评论(0)    收藏  举报