Rebol3 Code Examplex
SHA-256 Merkle tree
Build a Merkle tree using SHA-256 hashes.
Rebol [
title: "Rosetta code: SHA-256 Merkle tree"
file: %SHA-256_Merkle_tree.r3
url: https://rosettacode.org/wiki/SHA-256_Merkle_tree
]
markle-tree: function/with [
"Compute a Merkle Tree (hash tree) SHA-256 checksum"
data [string! binary!] "source data"
block-size [integer!] "size of each leaf block in bytes"
][
hashes: copy #{} ;; Binary buffer to store concatenated leaf hashes
;; Ensure data is binary for hashing
unless binary? data [data: to binary! data]
;; Process data in block-size chunks
while [not tail? data][
;; Append SHA hash of current chunk into 'hashes' binary
;; checksum/part <data> 'method <length> computes hash of segment
append hashes checksum/part data 'sha256 block-size
;; Advance input cursor by one block
data: skip data block-size
]
;; Build the Merkle root from the concatenated leaf hashes
compute-tree-hash hashes
][
;; Helper function: Recursively reduce a binary containing concatenated hashes
;; until a single hash remains (the Merkle root).
compute-tree-hash: func [
hashes [binary!] ;; Current level's concatenated hashes
/local next-level
][
;; If only one hash remains (32 bytes for SHA-256), we are done
either 32 == length? hashes [
hashes
][
next-level: copy #{} ;; Binary accumulator for next level
;; Process the current level in pairs of hashes (2 × 32 bytes = 64 bytes)
while [not tail? hashes] [
append next-level either 64 > length? hashes [
;; Odd-last hash is promoted unchanged when no pair to combine
hashes
][
;; Otherwise, concatenate two 32-byte hashes (already together
;; in the first 64 bytes) and hash them to form parent node
checksum/part hashes 'sha256 64
]
;; Move to the next hash or next pair
hashes: skip hashes 64
]
;; Recurse to continue building tree until one root hash remains
compute-tree-hash next-level
]
]
]
;; Display the Merkle root hash (as binary) for "abcdef" using 2-byte leafs
assert [
#{ECE0D575751F0CE6D4829D1EE93916B993CC9D5F41D4F59AC6BB5340F5F6F903}
== probe markle-tree "abcdef" 2
]
;; Using the image from the task specification:
image-url: https://rosettacode.org/wiki/File:RosettaCodeTitle.png
assert [
not error? bin: try [read image-url]
#{A4F902CF9D51FE51EDA156A6792E1445DFF65EDF3A217A1F3334CC9CF1495C2C}
== probe markle-tree :bin 1024
]