"8×8 seems big compared to 3×3 or 4×4 matrixes. The values are as random as you might expect a cryptographic hash to be, and range from 0-255:"
"Lets see it in use:"
]
},
{
@ -112,9 +109,6 @@
"execution_count": 3,
"id": "65aa7c7a-25d5-4971-8780-661f367e45ab",
"metadata": {
"jupyter": {
"source_hidden": true
},
"slideshow": {
"slide_type": "skip"
},
@ -146,12 +140,24 @@
}
],
"source": [
"#collapse-hide\n",
"print(hash_m(b\"Hello A\"))\n",
"print()\n",
"print(hash_m(b\"Hello B\"))"
]
},
{
"cell_type": "markdown",
"id": "04132091-21b1-4fbb-99df-711ae5e0c819",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"tags": []
},
"source": [
"8×8 seems big compared to 3×3 or 4×4 matrixes, but otherwise everything looks normal. The values are as random as you might expect a cryptographic hash to be, and range from 0-255."
"Merklist hash of the list [b'A', b'Hello', b'World'] :\n",
"[[178 188 57 157 60 136 190 127]\n",
" [ 40 234 254 224 38 46 250 52]\n",
" [156 72 193 136 219 98 28 4]\n",
" [197 2 43 132 132 232 254 198]\n",
" [ 93 64 113 215 2 246 130 192]\n",
" [ 91 107 85 13 149 60 19 173]\n",
" [ 84 77 244 98 0 239 123 17]\n",
" [ 58 112 98 250 163 20 27 6]]\n"
" [ 58 112 98 250 163 20 27 6]] \n",
"\n"
]
}
],
"source": [
"#collapse-hide\n",
"#collapse-output\n",
"print(\"List of elements:\")\n",
"print(elements)\n",
"print()\n",
"print(\"Hash of each element:\")\n",
"print(element_hashes)\n",
"print()\n",
"print(\"Hash of full list:\")\n",
"print(list_hash1)\n",
"# Expand the section below to see the output"
"print(\"List of elements:\\n\", elements, \"\\n\")\n",
"print(\"List of element hashes:\\n\", element_hashes, \"\\n\")\n",
"print(\"Merklist hash of the list\", elements, \":\\n\", list_hash1, \"\\n\")"
]
},
{
@ -301,17 +288,7 @@
"\n",
"Upon consideration, these are the exact properties that one would want in order to define the hash of a list of items. Non-commutativity enables the order of elements in the list to be well defined, since swapping different elements produces a different hash. Associativity enables calculating the hash of the list by performing the reduction operations in any order, and you still get the same hash.\n",
"\n",
"Lets sanity-check that these properties can hold for the construction described above."
]
},
{
"cell_type": "markdown",
"id": "c6c8ef5e-99d2-4a7e-887f-54b93a7baf4a",
"metadata": {},
"source": [
"### Associativity\n",
"\n",
"If it's associative, we should get the same hash if we rearrange the parenthesis to indicate reduction in a different operation order. That is: $((e1 × e2) × e3) = (e1 × (e2 × e3))$"
"Lets sanity-check that these properties can hold for the construction described above. For setup, lets consider the hashes of three elements, $he_1$, $he_2$, and $he_3$:"
]
},
{
@ -323,9 +300,19 @@
},
"outputs": [],
"source": [
"e1 = hash_m(b\"Hello A\")\n",
"e2 = hash_m(b\"Hello B\")\n",
"e3 = hash_m(b\"Hello C\")"
"he1 = hash_m(b\"A\")\n",
"he2 = hash_m(b\"B\")\n",
"he3 = hash_m(b\"C\")"
]
},
{
"cell_type": "markdown",
"id": "c6c8ef5e-99d2-4a7e-887f-54b93a7baf4a",
"metadata": {},
"source": [
"### Associativity\n",
"\n",
"If it's associative, we should get the same hash if we rearrange the parenthesis to indicate reduction in a different operation order. $((he_1 × he_2) × he_3) = (he_1 × (he_2 × he_3))$"
]
},
{
@ -337,33 +324,18 @@
},
"outputs": [],
"source": [
"x = np.matmul(np.matmul(e1, e2), e3)\n",
"y = np.matmul(e1, np.matmul(e2, e3))\n",
"x = np.matmul(np.matmul(he1, he2), he3)\n",
"y = np.matmul(he1, np.matmul(he2, he3))\n",
"\n",
"# observe that they produce the same summary\n",
"assert_equal(x, y)"
]
},
{
"cell_type": "markdown",
"id": "bda2bacf-daf7-4f42-93cf-c422704dc067",
"metadata": {
"tags": []
},
"source": [
"> Expand the sections below to see a comparison"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "b7a1906d-524c-4339-920a-978a0385d6cc",
"metadata": {
"collapsed": true,
"jupyter": {
"outputs_hidden": true,
"source_hidden": true
},
"tags": []
},
"outputs": [
@ -371,32 +343,29 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 58 12 144 134 100 158 159 51]\n",
" [ 73 206 202 190 87 79 223 2]\n",
" [210 122 142 117 37 148 106 45]\n",
" [175 146 187 223 235 171 64 226]\n",
" [149 85 203 87 92 251 243 206]\n",
" [ 18 252 160 103 125 251 181 133]\n",
" [191 132 220 104 213 154 34 154]\n",
" [127 197 95 87 166 3 22 3]]\n",
"[[236 186 154 122 127 118 202 95]\n",
" [132 196 196 78 80 160 68 166]\n",
" [208 62 184 219 85 118 143 111]\n",
" [ 7 176 219 162 243 25 29 54]\n",
" [233 49 39 237 233 209 201 221]\n",
" [187 196 20 155 17 241 207 101]\n",
" [132 186 67 153 231 160 68 62]\n",
" [ 8 184 160 149 100 160 189 56]] \n",
"\n",
"[[ 58 12 144 134 100 158 159 51]\n",
" [ 73 206 202 190 87 79 223 2]\n",
" [210 122 142 117 37 148 106 45]\n",
" [175 146 187 223 235 171 64 226]\n",
" [149 85 203 87 92 251 243 206]\n",
" [ 18 252 160 103 125 251 181 133]\n",
" [191 132 220 104 213 154 34 154]\n",
" [127 197 95 87 166 3 22 3]]\n"
" [[236 186 154 122 127 118 202 95]\n",
" [132 196 196 78 80 160 68 166]\n",
" [208 62 184 219 85 118 143 111]\n",
" [ 7 176 219 162 243 25 29 54]\n",
" [233 49 39 237 233 209 201 221]\n",
" [187 196 20 155 17 241 207 101]\n",
" [132 186 67 153 231 160 68 62]\n",
" [ 8 184 160 149 100 160 189 56]]\n"
]
}
],
"source": [
"#collapse-hide\n",
"#collapse-output\n",
"print(x)\n",
"print()\n",
"print(y)"
"print(x, \"\\n\\n\", y)"
]
},
{
@ -406,7 +375,7 @@
"source": [
"### Non-Commutativity\n",
"\n",
"If it's not commutative, then swapping different elements should produce a different hash. That is, $e1 × e2 \\ne e2 × e1$:"
"If it's not commutative, then swapping different elements should produce a different hash. That is, $he_1 × he_2 \\ne he_2 × he_1$:"
]
},
{
@ -418,33 +387,18 @@
},
"outputs": [],
"source": [
"x = np.matmul(e1, e2)\n",
"y = np.matmul(e2, e1)\n",
"x = np.matmul(he1, he2)\n",
"y = np.matmul(he2, he1)\n",
"\n",
"# observe that they produce different summaries\n",