编写一段 ABAP 代码构造 merklet 树

发布时间 2023-11-16 21:55:23作者: 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代码是用于创建一个Merkle树(Merkle Tree)的程序。Merkle树是一种数据结构,通常用于验证大型数据集的完整性,特别是在分布式系统和加密领域中。它的核心思想是通过逐层哈希计算来构建一个树结构,最终生成一个根哈希值,以验证数据的一致性。这个Merkle树程序首先生成叶节点的哈希值,然后逐层组合这些叶节点,最终生成根哈希值。

以下是代码中不同部分的详细解释:

  1. 程序说明和数据定义部分:

    • REPORT zblocktree:报告的名称。
    • PARAMETERS: leafnode TYPE i:定义了一个输入参数,用于指定叶子节点的数量。
    • TYPES:定义了一个自定义数据类型ty_merkletree,用于表示Merkle树的节点。
    • DATA:声明了一些变量用于存储Merkle树的信息和数据。
  2. START-OF-SELECTION 部分:

    • 这是程序执行的起始点。
  3. 叶子节点的生成:

    • 通过循环生成叶子节点。DO leafnode TIMES 循环,其中 leafnode 是叶子节点的数量。
    • 对每个叶子节点,将其值存储在 merkelline-leafvalue 中,然后通过 dohash 函数计算叶子节点的哈希值,将其存储在 merkelline-leafhash 中。
    • 设置 merkelline-level 为树的高度,并将左右子叶哈希值设置为空。
    • 最后,将节点添加到 merkeldata 表中。
  4. recursivehashing 子例程:

    • 这是一个递归子例程,用于逐层组合叶子节点以构建Merkle树。
    • 首先检查节点数是否为奇数,如果是,添加最后一个节点再进行哈希计算。
    • 然后,计算迭代次数,并在每次迭代中,组合两个节点的值和哈希,计算其父节点的哈希值。
    • 将父节点添加到 merkeldata2 表中,并清空 merkeldata1 表。
    • 递归调用 recursivehashing 直到只剩下一个节点。
  5. dohash 子例程:

    • 这个子例程用于计算给定输入值的哈希值,使用了 cl_abap_message_digest 类中的 calculate_hash_for_char 方法,采用SHA-1算法。

现在,让我们来看一个示例来说明这个ABAP程序是如何工作的。假设 leafnode 参数的值为 4,这意味着有4个叶子节点。程序将如下工作:

  1. 创建四个叶子节点,每个节点都包含一个值和相应的哈希值。
  2. 递归地组合这些叶子节点,生成中间节点,然后继续递归,直到生成根节点。
  3. 最终,Merkle树将包含根节点,该节点的哈希值可用于验证整个数据集的完整性。

Merkle树的结构如下:

Root Hash
|
|--- Intermediate Hash 1
|   |
|   |--- Leaf Hash 1
|   |
|   |--- Leaf Hash 2
|
|--- Intermediate Hash 2
|   |
|   |--- Leaf Hash 3
|   |
|   |--- Leaf Hash 4

根哈希值将被用于验证整个数据集是否与原始数据相匹配。这是一种常见的数据完整性验证方法,特别适用于分布式系统和加密领域。