使用 ABAP 代码生成区块链

发布时间 2023-11-16 21:50:12作者: JerryWang_汪子熙

源代码如下:

*&---------------------------------------------------------------------*
*& Report ZBLOCKCHAIN
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zblockchain.

PARAMETERS: diffle  TYPE char5 default '00000',
            noblock TYPE i DEFAULT 2.

DATA:blockdata TYPE zcl_abap_blockchain_tool=>tt_block .

DATA:blockdataline LIKE LINE OF blockdata,
     timestamp     TYPE timestampl,
     combineddata  TYPE string,
     prevblockdata LIKE LINE OF blockdata,
     nonce         TYPE i VALUE 1,
     noncestring   TYPE string,
     flag          TYPE c,
     difflength    TYPE i,
     gethash       TYPE REF TO cl_abap_message_digest.

blockdataline-index = 0.
blockdataline-data = 'Jerry first Genesis block'.
blockdataline-phash = '000000'.
GET TIME STAMP FIELD timestamp.
blockdataline-timestamp = timestamp.
blockdataline-nonce  = 0.
CONCATENATE blockdataline-index blockdataline-data blockdataline-phash blockdataline-timestamp blockdataline-nonce INTO combineddata.
CALL METHOD cl_abap_message_digest=>calculate_hash_for_char
  EXPORTING
    if_algorithm  = 'SHA1'
    if_data       = combineddata
  IMPORTING
    ef_hashstring = blockdataline-chash.
APPEND blockdataline TO blockdata.

noblock = noblock - 1.
difflength = strlen( diffle ).

DO noblock TIMES.
  blockdataline-index = sy-tabix.
  CONCATENATE `Jerry's Block ` blockdataline-index INTO blockdataline-data SEPARATED BY '-'.
  READ TABLE blockdata INTO prevblockdata INDEX blockdataline-index.
  IF sy-subrc EQ 0.
    blockdataline-phash = prevblockdata-chash.
  ENDIF.
  GET TIME STAMP FIELD timestamp.
  blockdataline-timestamp = timestamp.

  WHILE flag EQ abap_false.
    noncestring = nonce.
    CONCATENATE blockdataline-index blockdataline-data blockdataline-phash blockdataline-timestamp noncestring INTO combineddata.
    CALL METHOD cl_abap_message_digest=>calculate_hash_for_char
      EXPORTING
        if_algorithm  = 'SHA1'
        if_data       = combineddata
      IMPORTING
        ef_hashstring = blockdataline-chash.

    IF blockdataline-chash(difflength) = diffle.
      flag = 'X'.
      blockdataline-nonce  = nonce.
      APPEND blockdataline TO blockdata.
      nonce = 1.
      CLEAR:blockdataline.
    ENDIF.
    nonce = nonce + 1.
  ENDWHILE.
  CLEAR flag.
ENDDO.

DATA: g_alv_tree TYPE REF TO cl_gui_alv_tree,
      gt_data    TYPE STANDARD TABLE OF zcl_abap_blockchain_tool=>ty_displayed_node,
      ok_code    LIKE sy-ucomm,
      save_ok    LIKE sy-ucomm,
      ls_data    LIKE LINE OF gt_data.
  FIELD-SYMBOLS: <field> TYPE LINE OF LVC_T_FCAT.

  DATA(lo_tool) = NEW zcl_abap_blockchain_tool( blockdata ).
  DATA(lt_fieldcat) = lo_tool->get_fieldcat_by_data( ls_data ).
  PERFORM change_label.
  CALL SCREEN 100.

DEFINE define_label.

  READ TABLE lt_fieldcat ASSIGNING <field> INDEX &1.
  <field>-seltext = <field>-reptext = <field>-scrtext_m = <field>-scrtext_s = <field>-scrtext_l = &2.
  <field>-outputlen = &3.

END-OF-DEFINITION.

FORM change_label.
  define_label 1 'Block Data' 20.
  define_label 2 'Hash' 40.
  define_label 3 'Nonce' 10.
  define_label 4 'Timestamp' 20.

ENDFORM.
FORM init_tree.
  g_alv_tree = lo_tool->get_tree( ).
  DATA l_hierarchy_header TYPE treev_hhdr.
  PERFORM build_hierarchy_header CHANGING l_hierarchy_header.
  CALL METHOD g_alv_tree->set_table_for_first_display
    EXPORTING
      is_hierarchy_header = l_hierarchy_header
    CHANGING
      it_fieldcatalog     = lt_fieldcat
      it_outtab           = gt_data.
  PERFORM create_tree.
  g_alv_tree->frontend_update( ).
  lo_tool->expand( ).
ENDFORM.
FORM create_tree.
  lo_tool->render_tree( ).
ENDFORM.
FORM build_hierarchy_header CHANGING p_hierarchy_header TYPE treev_hhdr.
  p_hierarchy_header-heading = 'BlockChain list'.
  p_hierarchy_header-width = 30.
  p_hierarchy_header-width_pix = ' '.
ENDFORM.

FORM exit_program.
  LEAVE PROGRAM.
ENDFORM.

MODULE pbo OUTPUT.
  SET PF-STATUS 'MAIN100'.
  SET TITLEBAR 'MAINTITLE'.
  IF g_alv_tree IS INITIAL.
    PERFORM init_tree.
    CALL METHOD cl_gui_cfw=>flush
      EXCEPTIONS
        cntl_system_error = 1
        cntl_error        = 2.
    ASSERT sy-subrc = 0.
  ENDIF.
ENDMODULE.

MODULE pai INPUT.
  save_ok = ok_code.
  CLEAR ok_code.
  CASE save_ok.
    WHEN 'EXIT' OR 'BACK' OR 'CANC'.
      PERFORM exit_program.
    WHEN OTHERS.
      CALL METHOD cl_gui_cfw=>dispatch.
  ENDCASE.
  CALL METHOD cl_gui_cfw=>flush.
ENDMODULE.

代码解释如下:

首先,它定义了一个报告 ZBLOCKCHAIN,该报告有两个参数 difflenoblockdiffle 是一个五个字符的字符串,用于定义区块链的难度,而 noblock 是一个整数,用于定义区块链中区块的数量。

然后,它定义了一些数据对象,包括 blockdata,它是一个表,用于存储区块链中的区块; blockdataline,它代表一个区块,包含了区块的索引、数据、前一个区块的哈希值、时间戳和随机数; timestamp 是一个时间戳; combineddata 是一个字符串,用于存储区块的信息,并用于生成哈希值; prevblockdata 用于存储前一个区块的信息; nonce 是一个随机数,用于生成哈希值; noncestringnonce 的字符串表示; flag 是一个标志,用于控制循环; difflengthdiffle 的长度; gethash 是一个对象引用,用于生成哈希值。

接下来,它创建了创世区块,也就是区块链的第一个区块。创世区块的索引为 0,数据为 Jerry first Genesis block,前一个区块的哈希值为 000000,时间戳为当前时间,随机数为 0。然后,它将这些信息连接成一个字符串,然后调用 cl_abap_message_digest=>calculate_hash_for_char 方法生成哈希值,并将哈希值存储在 blockdataline-chash 中。最后,它将 blockdataline 添加到 blockdata 中。

接着,它创建了其余的区块。这是通过一个循环实现的,循环的次数是 noblock - 1。在每次循环中,它首先设置区块的索引和数据,然后读取前一个区块的信息,将其哈希值设置为当前区块的 phash,设置当前区块的时间戳,然后在一个内部循环中,生成随机数,连接区块的信息,生成哈希值,如果哈希值的前 difflength 个字符和 diffle 相等,那么就退出内部循环,将当前区块添加到 blockdata 中,否则,增加随机数,然后继续内部循环。