源代码如下:
*&---------------------------------------------------------------------*
*& Report ZBLOCKTREE
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zblocktree.
PARAMETERS: leafnode TYPE i.
TYPES: BEGIN OF ty_merkletree,
leafvalue TYPE string,
leafhash TYPE string,
level TYPE int4,
leftleafhash TYPE string,
rightleafhash TYPE string,
END OF ty_merkletree.
DATA: treeheight TYPE int4,
count TYPE int4,
merkeldata1 TYPE TABLE OF ty_merkletree,
merkeldata2 TYPE TABLE OF ty_merkletree,
merkeldata TYPE TABLE OF ty_merkletree.
START-OF-SELECTION.
IF leafnode MOD 2 <> 0.
leafnode = leafnode + 1.
ENDIF.
" Calculate tree height
treeheight = leafnode / 2.
count = 0.
DATA: lv_tabix TYPE string,
merkelline TYPE ty_merkletree,
merkelline1 TYPE ty_merkletree,
merkelline2 TYPE ty_merkletree.
DO leafnode TIMES.
lv_tabix = sy-index.
CONCATENATE 'Leaf' lv_tabix INTO merkelline-leafvalue .
PERFORM dohash USING merkelline-leafvalue CHANGING merkelline-leafhash.
merkelline-level = treeheight.
merkelline-leftleafhash = ''.
merkelline-rightleafhash = ''.
APPEND merkelline TO merkeldata.
ENDDO.
merkeldata1 = merkeldata.
PERFORM recursivehashing.
BREAK-POINT.
FORM recursivehashing.
""Check number of nodes to be hashed if odd add the last node again.
DESCRIBE TABLE merkeldata1 LINES DATA(leafcount).
IF leafcount MOD 2 <> 0.
READ TABLE merkeldata1 INTO merkelline1 INDEX leafcount.
APPEND merkelline1 TO merkeldata1.
ENDIF.
DESCRIBE TABLE merkeldata1 LINES leafcount.
DATA(iteration) = leafcount / 2.
" Combine the number of nodes based on iteration count.
DO iteration TIMES.
DATA(count) = sy-index * 2.
DATA(count2) = count - 1.
READ TABLE merkeldata INTO merkelline1 INDEX count.
READ TABLE merkeldata INTO merkelline2 INDEX count2.
CONCATENATE merkelline1-leafvalue merkelline2-leafvalue INTO merkelline-leafvalue.
CONCATENATE merkelline1-leafhash merkelline2-leafhash INTO merkelline-leafhash.
PERFORM dohash USING merkelline-leafhash CHANGING merkelline-leafhash.
merkelline-leftleafhash = merkelline1-leafhash.
CONCATENATE merkelline1-leafhash merkelline2-leafhash INTO merkelline-leafhash .
merkelline-rightleafhash = merkelline2-leafhash.
merkelline-level = treeheight - count.
APPEND merkelline TO merkeldata2.
ENDDO.
" Add the processed nodes to master table and call the subroutine again with processed node data
"CLEAR adddummy.
INSERT LINES OF merkeldata2 INTO merkeldata INDEX 1.
CLEAR merkeldata1.
merkeldata1 = merkeldata2.
CLEAR merkeldata2.
DESCRIBE TABLE merkeldata1 LINES leafcount.
IF leafcount <> 1.
PERFORM recursivehashing.
ENDIF.
ENDFORM.
FORM dohash USING inputvalue TYPE string CHANGING hashvalue TYPE string.
CALL METHOD cl_abap_message_digest=>calculate_hash_for_char
EXPORTING
if_algorithm = 'SHA1'
if_data = inputvalue
IMPORTING
ef_hashstring = hashvalue.
ENDFORM.
这段 ABAP 代码实现的是一个简单的 Merkel 树(Merkle Tree)算法。Merkle 树是一种哈希树,在密码学和计算机科学中广泛使用,特别是在分布式系统和区块链技术中。
我们来逐步了解这段代码。
首先,定义了一个名为 ty_merkletree
的类型,该类型包含了树节点需要的各种信息,如叶子值,叶子哈希,层级,左叶子哈希,右叶子哈希。
之后,定义了一些用于构建 Merkle 树的变量,如 treeheight
,count
,merkeldata1
,merkeldata2
,merkeldata
等。
在 START-OF-SELECTION
中,首先检查输入的叶节点数量 leafnode
是否为偶数,如果不是则加1使其变为偶数。然后计算树的高度和初始化计数器。
在接下来的循环中,生成了 Merkle 树的叶节点。使用 dohash
这个 FORM 对叶节点的值进行哈希运算,生成叶节点的哈希值,并把这些叶节点添加到 merkeldata
这个表中。
接下来,调用了 recursivehashing
这个 FORM 来递归地生成 Merkle 树的其余部分。在这个 FORM 中,首先检查待处理节点的数量,如果是奇数则复制最后一个节点使其变为偶数。然后在循环中,每次取两个节点,计算它们的哈希值,然后生成一个新的父节点,这个父节点的哈希值是两个子节点哈希值的哈希,左右子节点的哈希值也被记录下来。这些新生成的父节点被添加到 merkeldata2
这个表中。
当所有的叶节点都处理完后,把 merkeldata2
中的节点添加到 merkeldata
中,然后清空 merkeldata1
和 merkeldata2
,然后把 merkeldata2
的值设置为 merkeldata1
,然后再次调用 recursivehashing
这个 FORM,直到只剩下一个节点,也就是 Merkle 树的根节点。
dohash
这个 FORM 是用来对输入的字符串进行哈希运算的,它使用了 cl_abap_message_digest
类的 calculate_hash_for_char
方法,该方法使用 SHA1 算法进行哈希运算。