|
1 | | -from .encoding.hash import double_sha256 |
2 | | -from .encoding.hexbytes import h2b_rev |
3 | | - |
4 | | - |
5 | | -def merkle(hashes, hash_f=double_sha256): |
6 | | - """Take a list of hashes, and return the root merkle hash.""" |
7 | | - while len(hashes) > 1: |
8 | | - hashes = merkle_pair(hashes, hash_f) |
9 | | - return hashes[0] |
10 | | - |
11 | | - |
12 | | -def merkle_pair(hashes, hash_f): |
13 | | - """Take a list of hashes, and return the parent row in the tree of merkle hashes.""" |
14 | | - if len(hashes) % 2 == 1: |
15 | | - hashes = list(hashes) |
16 | | - hashes.append(hashes[-1]) |
17 | | - items = [] |
18 | | - for i in range(0, len(hashes), 2): |
19 | | - items.append(hash_f(hashes[i] + hashes[i+1])) |
20 | | - return items |
21 | | - |
22 | | - |
23 | | -def test_merkle(): |
24 | | - s1 = h2b_rev("56dee62283a06e85e182e2d0b421aceb0eadec3d5f86cdadf9688fc095b72510") |
25 | | - assert merkle([s1], double_sha256) == s1 |
26 | | - # from block 71043 |
27 | | - mr = h2b_rev("30325a06daadcefb0a3d1fe0b6112bb6dfef794316751afc63f567aef94bd5c8") |
28 | | - s1 = h2b_rev("67ffe41e53534805fb6883b4708fd3744358f99e99bc52111e7a17248effebee") |
29 | | - s2 = h2b_rev("c8b336acfc22d66edf6634ce095b888fe6d16810d9c85aff4d6641982c2499d1") |
30 | | - assert merkle([s1, s2], double_sha256) == mr |
31 | | - |
32 | | - # from block 71038 |
33 | | - mr = h2b_rev("4f4c8c201e85a64a410cc7272c77f443d8b8df3289c67af9dab1e87d9e61985e") |
34 | | - s1 = h2b_rev("f484b014c55a43b409a59de3177d49a88149b4473f9a7b81ea9e3535d4b7a301") |
35 | | - s2 = h2b_rev("7b5636e9bc6ec910157e88702699bc7892675e8b489632c9166764341a4d4cfe") |
36 | | - s3 = h2b_rev("f8b02b8bf25cb6008e38eb5453a22c502f37e76375a86a0f0cfaa3c301aa1209") |
37 | | - assert merkle([s1, s2, s3], double_sha256) == mr |
38 | | - |
39 | | - |
40 | | -if __name__ == "__main__": |
41 | | - test_merkle() |
42 | | - |
43 | | - |
44 | | -""" |
45 | | -Implement Merkle hashing. See http://en.wikipedia.org/wiki/Merkle_tree |
46 | | -
|
47 | | -
|
48 | | -The MIT License (MIT) |
49 | | -
|
50 | | -Copyright (c) 2013 by Richard Kiss |
51 | | -
|
52 | | -Permission is hereby granted, free of charge, to any person obtaining a copy |
53 | | -of this software and associated documentation files (the "Software"), to deal |
54 | | -in the Software without restriction, including without limitation the rights |
55 | | -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
56 | | -copies of the Software, and to permit persons to whom the Software is |
57 | | -furnished to do so, subject to the following conditions: |
58 | | -
|
59 | | -The above copyright notice and this permission notice shall be included in |
60 | | -all copies or substantial portions of the Software. |
61 | | -
|
62 | | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
63 | | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
64 | | -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
65 | | -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
66 | | -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
67 | | -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
68 | | -THE SOFTWARE. |
69 | | -""" |
| 1 | +# Annotated pycoin/merkle.py |
| 2 | + |
| 3 | +from typing import List, Optional |
| 4 | + |
| 5 | +class MerkleNode: |
| 6 | + def __init__(self, left: Optional['MerkleNode'], right: Optional['MerkleNode'], value: bytes): |
| 7 | + self.left = left |
| 8 | + self.right = right |
| 9 | + self.value = value |
| 10 | + |
| 11 | +def create_merkle_tree(leaves: List[bytes]) -> MerkleNode: |
| 12 | + nodes = [MerkleNode(None, None, leaf) for leaf in leaves] |
| 13 | + while len(nodes) > 1: |
| 14 | + nodes = [MerkleNode(nodes[i], nodes[i + 1], nodes[i].value + nodes[i + 1].value) |
| 15 | + for i in range(0, len(nodes), 2)] |
| 16 | + return nodes[0] if nodes else None |
0 commit comments