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;
        }
    }

}
相關文章
相關標籤/搜索