使用 ABAP 代码构造 Merkle树(Merkle Tree)

发布时间 2023-11-17 12:53:41作者: JerryWang_汪子熙

源代码如下:

*&---------------------------------------------------------------------*
*& 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 树的变量,如 treeheightcountmerkeldata1merkeldata2merkeldata 等。

START-OF-SELECTION 中,首先检查输入的叶节点数量 leafnode 是否为偶数,如果不是则加1使其变为偶数。然后计算树的高度和初始化计数器。

在接下来的循环中,生成了 Merkle 树的叶节点。使用 dohash 这个 FORM 对叶节点的值进行哈希运算,生成叶节点的哈希值,并把这些叶节点添加到 merkeldata 这个表中。

接下来,调用了 recursivehashing 这个 FORM 来递归地生成 Merkle 树的其余部分。在这个 FORM 中,首先检查待处理节点的数量,如果是奇数则复制最后一个节点使其变为偶数。然后在循环中,每次取两个节点,计算它们的哈希值,然后生成一个新的父节点,这个父节点的哈希值是两个子节点哈希值的哈希,左右子节点的哈希值也被记录下来。这些新生成的父节点被添加到 merkeldata2 这个表中。

当所有的叶节点都处理完后,把 merkeldata2 中的节点添加到 merkeldata 中,然后清空 merkeldata1merkeldata2,然后把 merkeldata2 的值设置为 merkeldata1,然后再次调用 recursivehashing 这个 FORM,直到只剩下一个节点,也就是 Merkle 树的根节点。

dohash 这个 FORM 是用来对输入的字符串进行哈希运算的,它使用了 cl_abap_message_digest 类的 calculate_hash_for_char 方法,该方法使用 SHA1 算法进行哈希运算。