/ lib / _ak_zblock
_ak_zblock
  1  #!/usr/bin/env bash
  2  ###
  3  ### arching-kaos-tools
  4  ### Tools to interact and build an Arching Kaos Infochain
  5  ### Copyright (C) 2021 - 2026  kaotisk
  6  ###
  7  ### This program is free software: you can redistribute it and/or modify
  8  ### it under the terms of the GNU General Public License as published by
  9  ### the Free Software Foundation, either version 3 of the License, or
 10  ### (at your option) any later version.
 11  ###
 12  ### This program is distributed in the hope that it will be useful,
 13  ### but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  ### GNU General Public License for more details.
 16  ###
 17  ### You should have received a copy of the GNU General Public License
 18  ### along with this program.  If not, see <http://www.gnu.org/licenses/>.
 19  ###
 20  #set -x
 21  source $AK_LIBDIR/_ak_lib_load
 22  _ak_lib_load _ak_log
 23  _ak_lib_load _ak_script
 24  _ak_lib_load _ak_datetime
 25  _ak_lib_load _ak_gpg
 26  _ak_lib_load _ak_html
 27  _ak_lib_load _ak_ipfs
 28  _ak_lib_load _ak_fs
 29  
 30  if [ ! -d $AK_WORKDIR/ipfs ]
 31  then
 32      mkdir $AK_WORKDIR/ipfs
 33  fi
 34  
 35  function _ak_data_expand(){
 36      if [ ! -z $1 ] && [ ! -z $2 ] && [ -n "$1" ] && [ -n "$2" ]
 37      then
 38          TEMP="$(_ak_make_temp_directory)"
 39          cd $TEMP
 40          _ak_ipfs_cid_v0_check $1
 41          _ak_ipfs_cat $1 > /dev/null
 42          if [ $? -ne 0 ]
 43          then
 44              _ak_log_error "Error while reading $1"
 45              exit 1
 46          fi
 47          _ak_ipfs_cat $1 | jq -M > /dev/null
 48          if [ $? -ne 0 ]
 49          then
 50              _ak_log_error "Error while parsing JSON for $1"
 51              exit 1
 52          fi
 53          _ak_ipfs_cat $1 | jq | grep ipfs > /dev/null
 54          if [ $? -ne 0 ]
 55          then
 56              _ak_log_error "_ak_data_expand: No 'ipfs' field in $1"
 57              _ak_log_debug "Looking for akfsmap"
 58              _ak_ipfs_cat $1 | jq | grep akfsmap > /dev/null
 59              if [ $? -ne 0 ]
 60              then
 61                  _ak_log_error "_ak_data_expand: No 'akfsmap' field in $1"
 62                  exit 1
 63              fi
 64              is_data_akfs="yes"
 65          else
 66              is_data_akfs="no"
 67          fi
 68          if [ "${is_data_akfs}" == "yes" ]
 69          then
 70              DATA=$(_ak_ipfs_cat $1 | jq -r '.akfsmap')
 71              if [ $? -ne 0 ]
 72              then
 73                  _ak_log_error "Error while extracting data (akfsmap) from JSON for $1"
 74                  exit 1
 75              fi
 76          else
 77              DATA="$(_ak_ipfs_cat $1 | jq -r '.ipfs')" #| grep ipfs | sed -e 's/"ipfs": "//g; s/[",]//g; s/ //g')"
 78              if [ $? -ne 0 ]
 79              then
 80                  _ak_log_error "Error while extracting data (ipfs) from JSON for $1"
 81                  exit 1
 82              fi
 83              # _ak_log_debug "DATA of $1 is: [$DATA]"
 84          fi
 85          _ak_ipfs_cat $1 | jq | grep detach > /dev/null
 86          if [ $? -ne 0 ]
 87          then
 88              _ak_log_error "_ak_data_expand: No 'detach' field in $1"
 89              exit 1
 90          fi
 91          DETACH="$(_ak_ipfs_cat $1 | jq -r '.detach')" #| grep detach | sed -e 's/"detach": "//g; s/[",]//g; s/ //g')"
 92          if [ $? -ne 0 ]
 93          then
 94              _ak_log_error "Error while extracting data from JSON for $1"
 95              exit 1
 96          fi
 97          _ak_ipfs_cid_v0_check $2
 98          gpg="$2"
 99          _ak_ipfs_get $gpg > /dev/null 2>&1
100          if [ $? -ne 0 ]
101          then
102              _ak_log_error "Could not get GPG key: $gpg"
103          exit 1
104          fi
105          _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1
106          if [ $? -ne 0 ]
107          then
108              _ak_log_error "Could not import GPG key: $gpg"
109              exit 1
110          fi
111          _ak_log_debug "GPG key from $gpg was imported!"
112          if [ "${is_data_akfs}" == "yes" ]
113          then
114              _ak_log_info "DATA is on AKFS"
115              _ak_fs_net_get_from_map_hash $DETACH
116              if [ $? -ne 0 ]
117              then
118                  _ak_log_error "Failed to download $DETACH"
119                  exit 1
120              fi
121              detach_filename="$(_ak_fs_from_map_net_get_original_filename $DETACH)"
122              _ak_log_info "$DETACH downloaded @ $detach_filename (we are in: $(pwd))"
123              if [ ! -f $TEMP/$detach_filename ]
124              then
125                  _ak_log_error "File downloaded from akfs wasn't found: $DETACH $detach_filename"
126                  exit 1
127              fi
128              _ak_log_debug "detach filename is $detach_filename"
129              mv $TEMP/$detach_filename $TEMP/$DETACH
130              if [ ! -f $TEMP/$DETACH ]
131              then
132                  _ak_log_error "$DETACH was downloaded but not found"
133                  exit 1
134              fi
135              mv $TEMP/$DETACH $TEMP/$DATA.asc
136          else
137              _ak_ipfs_get $DETACH > /dev/null 2>&1
138              if [ $? -ne 0 ]
139              then
140                  _ak_log_error "Error while getting signature: $DETACH for data: $DATA"
141                  exit 1
142              fi
143              _ak_log_debug "$DETACH was downloaded"
144              if [ ! -f $AK_IPFS_ARTIFACTS/$DETACH ]
145              then
146                  _ak_log_error "$DETACH was downloaded but not found"
147                  exit 1
148              fi
149              ln -s $AK_IPFS_ARTIFACTS/$DETACH $TEMP/$DATA.asc
150          fi
151          _ak_log_debug "DATA_SIGNATURE $DETACH downloaded"
152          _ak_log_info "Gonna get $DATA..."
153          if [ "${is_data_akfs}" == "yes" ]
154          then
155              _ak_fs_net_cat_from_map_hash $DATA > $TEMP/$DATA
156              if [ $? -ne 0 ]
157              then
158                  _ak_log_error "Failed to download $DATA"
159                  exit 1
160              fi
161              if [ ! -f $TEMP/$DATA ]
162              then
163                  _ak_log_error "$DATA was downloaded but not found"
164                  exit 1
165              fi
166          else
167              _ak_ipfs_get $DATA > /dev/null 2>&1
168              if [ $? -ne 0 ]
169              then
170                  _ak_log_error "Error while getting data: $DATA"
171                  exit 1
172              fi
173              ln -s $AK_IPFS_ARTIFACTS/$DATA $TEMP/$DATA
174          fi
175          _ak_log_debug "DATA $DATA downloaded"
176          _ak_gpg_verify_signature $TEMP/$DATA.asc $TEMP/$DATA # > /dev/null 2>&1
177          if [ $? -ne 0 ]
178          then
179              _ak_log_error "Error while verifying signature for $DATA [ $TEMP/$DATA ] against $DETACH [ $TEMP/$DATA.asc ]"
180              exit 1
181          fi
182          # ln -s $AK_IPFS_ARTIFACTS/$DATA $AK_WORKDIR/ipfs
183          _ak_log_info "DATA_SIGNATURE $DETACH verified"
184          echo -n '"data":"'$1'","'$1'":'$(_ak_ipfs_cat $1|jq -M -c)','
185          cd
186          rm -rf $TEMP
187      else
188          _ak_log_error "_ak_data_expand HASH GPG"
189          exit 1
190      fi
191  }
192  
193  # _ak_zblock_show
194  # ak-zblock [IPFS CID]
195  #
196  # Returns a JSON array representing the chain retrieved.
197  function _ak_zblock_show(){
198      verify=1
199      if [ ! -z $1 ] && [ -n "$1" ]
200      then
201          _ak_ipfs_cid_v0_check $1
202          entrance="$1"
203      else
204          entrance="$(cat $AK_ZLATEST)"
205      fi
206      TEMP=$(_ak_make_temp_directory)
207      cd $TEMP
208      zblock=$entrance
209      # Check if $zblock exists as variable
210      if [ ! -v $zblock ]
211      then
212          # Check if it is not our seed cause if it is we skip this part
213          if [ "$zblock" != "$seed" ]
214          then
215              # Reset timestamp since it's introduced later
216              timestamp=''
217              # Announce to logs which ZBLOCK is being read at the moment
218              _ak_log_info "Examining $zblock"
219              _ak_ipfs_cid_v0_check "$zblock"
220              # We check if any $zblock at all...
221              # TODO: Eliminate outputing to file since we store all cat/get'ed
222              #       ipfs hashes on local fs.
223              _ak_ipfs_cat $zblock > /dev/null 2>&1
224              if [ $? -ne 0 ]
225              then
226                  _ak_log_error "ZBLOCK $zblock unreachable"
227                  exit 1
228              fi
229              _ak_log_debug "ZBLOCK $zblock within reach"
230              # ...and if it's JSON formated
231              cat $AK_IPFS_ARTIFACTS/$zblock | jq > /dev/null 2>&1
232              if [ $? -ne 0 ]
233              then
234                  _ak_log_error "ZBLOCK $zblock is not JSON"
235                  cat /dev/null > $AK_IPFS_ARTIFACTS/$zblock > /dev/null 2>&1
236                  exit 1
237              fi
238              _ak_log_debug "ZBLOCK $zblock is JSON"
239              echo -n '{'
240  #            echo -n '"id":"'$counter'",'
241              echo -n '"zblock":"'$zblock'",'
242              # Be sure that there are the expected values
243              # We need 'block' and 'block_signature' inside a 'zblock'
244              # Exit if any is missing
245              block="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block)"
246              if [ "$block" == "null" ]
247              then
248                  _ak_log_error "ZBLOCK $zblock has no BLOCK"
249                  exit 1
250              fi
251              _ak_ipfs_cid_v0_check "$block"
252              _ak_log_debug "ZBLOCK $zblock has block $block"
253              block_signature="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block_signature)"
254              if [ "$block_signature" == "null" ]
255              then
256                  _ak_log_error "ZBLOCK $zblock has no BLOCK_SIGNATURE"
257                  exit 1
258              fi
259              _ak_ipfs_cid_v0_check "$block_signature"
260              _ak_log_debug "ZBLOCK $zblock contains a BLOCK_SIGNATURE $block_signature"
261              # Same as above applies to BLOCK and DATA subparts of each ZBLOCK
262              # BLOCKS
263              echo -n '"block":"'$block'",'
264              echo -n '"block_signature":"'$block_signature'",'
265              _ak_ipfs_cat $block | jq -c -M > /dev/null 2>&1
266              cat $AK_IPFS_ARTIFACTS/$block | jq -M > /dev/null 2>&1
267              if [ $? -ne 0 ]
268              then
269                  _ak_log_error "BLOCK $block READ failed"
270                  exit 1
271              fi
272              grep -e 'timestamp' -e 'gpg' -e 'data' -e 'action' -e 'detach' -e 'previous' $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1
273              if [ $? -ne 0 ]
274              then
275                  _ak_log_error "BLOCK $block is NOT a valid block"
276                  exit 1
277              fi
278              _ak_log_debug "BLOCK $block is a block"
279              action="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .action)"
280              module="$(echo $action | sed -e 's/\// /g' | awk '{ print $1 }')"
281              _ak_log_debug "DATA is $module module."
282              command="$(echo $action | sed -e 's/\// /g' | awk '{ print $2 }')"
283              _ak_log_debug "COMMAND is $command"
284              timestamp="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .timestamp)"
285              if [ "$timestamp" != "null" ]
286              then
287                  echo -n '"timestamp":"'$timestamp'",'
288              fi
289              detach="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .detach)"
290              echo -n '"detach":"'$detach'",'
291              echo -n '"module":"'$module'",'
292              echo -n '"action":"'$command'",'
293              gpg="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .gpg)"
294              echo -n '"gpg":"'$gpg'",'
295              if [ $verify -eq 1 ]
296              then
297                  _ak_ipfs_get $gpg > /dev/null 2>&1
298                  if [ $? -ne 0 ]
299                  then
300                      _ak_log_error "Could not get GPG key: $gpg ."
301                      exit 1
302                  fi
303                  _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1
304                  if [ $? -ne 0 ]
305                  then
306                      _ak_log_error "Could not import GPG key: $gpg ."
307                      exit 1
308                  fi
309                  _ak_ipfs_get $block_signature > /dev/null 2>&1
310                  if [ $? -ne 0 ]
311                  then
312                      _ak_log_error "Error while getting BLOCK_SIGNATURE $block_signature for BLOCK $block"
313                      exit 1
314                  fi
315                  ln -s $AK_IPFS_ARTIFACTS/$block_signature $TEMP/$block.asc
316                  _ak_log_info "BLOCK_SIGNATURE $block_signature downloaded"
317                  _ak_ipfs_get $block > /dev/null 2>&1
318                  if [ $? -ne 0 ]
319                  then
320                      _ak_log_error "Could not get $block block"
321                      exit 1
322                  fi
323                  _ak_log_info "BLOCK $block downloaded"
324                  _ak_gpg_verify_signature $TEMP/$block.asc $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1
325                  if [ $? -ne 0 ]
326                  then
327                      _ak_log_error "Could not verify $block with GPG key $gpg."
328                      exit 1
329                  fi
330                  _ak_log_info "$gpg signature of $block is verified."
331              fi
332              data="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .data)"
333              _ak_ipfs_cid_v0_check "$data"
334              _ak_data_expand $data $gpg
335              if [ $? -ne 0 ]
336              then
337                  _ak_log_error "Failed on data signature verification [data: $data, gpg: $gpg, zblock: $zblock]"
338                  exit 1
339              fi
340              # DATA
341              # Only print to stdout
342              # _ak_ipfs_cat $data
343              # touch $AK_DATADIR/$data
344              # ^ unreasonable?
345              # Now, since we sourced the BLOCK to our terminal, we can search
346              # for $previous variable. In case we don't find one, we append one
347              # and we exit.
348              previous="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .previous)"
349              if [ -v $previous ]
350              then
351                  _ak_log_warning "Block $block has no previous zblock, appending pseudo genesis to exit with 2."
352                  echo -n '"previous":"'$seed'"},{"genesis":"genesis"}]'
353                  _ak_log_info "Reached pseudo-genesis, counted $counter zblocks."
354                  exit 2
355              # Otherwise, we inform of the sequence
356              else
357                  #echo "$zblock after $previous"
358                  _ak_log_info "Found a previous block for $zblock: $previous"
359                  echo -n '"previous":"'$previous'"}'
360                  zblock=$previous
361              fi
362          # Now check if it is equal to the seed
363          # which apparently means we reached the seed.
364          elif [ "$zblock" == "$seed" ]
365          then
366              echo -n '{"genesis":"genesis"}]'
367              _ak_log_info "Reached $seed, counted $counter zblocks."
368              exit 0
369          fi
370      # And finally, if nothing is there exit with error
371      else
372          echo "Check not passed... No previous IPFS CID"
373          exit 1
374      fi
375  }
376  
377  # _ak_zblock_manipulator(){
378  # # This file describe the structure of the ArchingKaos messages in their basis.
379  # #
380  # # As previously thought, we exchange one IPFS hash through whatever means we can.
381  # #
382  # # GPG is mentioned as a signing algorithm for encryption, decryption and signing.
383  # # Let's say we have a file named as `example`
384  # #
385  # # We can extend this with calling the encoder and further send the transaction
386  # #
387  #
388  # #FINGERPRINT="CHANGE THIS TO YOUR DEFAULT FINGERPRINT"
389  # # We acquire the GPG fingerprint by email address
390  # # The following example finds kaos@kaos.kaos' GPG fingerprint like this
391  # # FINGERPRINT="$(gpg2 --homedir $AK_GPGHOME --list-keys | grep kaos@kaos.kaos -1 | head -n1 | awk '{print $1}')"
392  #
393  # # Below, the usage information
394  # PROGRAM="$(basename $0)"
395  # source $AK_LIBDIR/_ak_log
396  # source $AK_LIBDIR/_ak_ipfs
397  # source $AK_LIBDIR/_ak_gpg
398  #
399  # usage(){
400  #     echo "Usage:"
401  #     echo "$PROGRAM -b block_file | -h block_hash | dunno"
402  #     echo "Creates and publishes a ZBLOCK based on a block and a previous"
403  #     echo "zblock."
404  #     echo ""
405  #     echo "Either -b or -h is needed. If both, -h is used."
406  #     echo ""
407  #     echo "-b block_file        Points to a block file that we want to fix."
408  #     echo "-h block_hash        If we don't have the block as a file, we can"
409  #     echo "                use it's hash to retrieve it and edit it."
410  #     echo "-p previous_hash        We refering to a previous hash for a ZBLOCK."
411  #     echo ""
412  #     echo "#TODO:"
413  #     echo "-t timestamp        Unix UTC timestamp in seconds."
414  #     echo "-a \"module/action\"    Change the action tag. Format: object/verb."
415  #     echo "                In sense, \"Add news -> news/add\"."
416  #     echo "-d data            In case you want to change the data, you 'll"
417  #     echo "                be changing potentially the key of the block"
418  #     echo "                and the data signature, otherwise your block"
419  #     echo "                will be unverified."
420  #     echo ""
421  # }
422  #
423  # main(){
424  #
425  #     _ak_log_info "We are doing" $BLOCK_TO_ADD "with content" $PREVIOUS
426  #     # We add it to IPFS
427  #     MESSAGE_HASH=$(_ak_ipfs_add $MESSAGE)
428  #
429  #     # We create a detached and armor signature of it
430  #     MESSAGE_SIGN_FILE=$MESSAGE".asc"
431  #     _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $MESSAGE
432  #
433  #     # We add the signature to IPFS
434  #     MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
435  #
436  #     # We will be using our public key also to put it in the block later
437  #     KEY="gpg.pub"
438  #     _ak_gpg_key_self_export $KEY
439  #     GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
440  #
441  #     # Acquire last block of information, to chain this one with previous posted
442  #     PREVIOUS=$(_ak_ipfs_files_stat /zlatest | head -n 1)
443  #
444  #     # We create a block of json like this:
445  #     cat > block <<EOF
446  # {
447  #     "timestamp":"$(date -u +%s)",
448  #     "action":"$ACTION",
449  #     "data":"$MESSAGE_HASH",
450  #     "detach":"$MESSAGE_SIGNATURE",
451  #     "gpg":"$GPG_PUB_KEY",
452  #     "previous":"$PREVIOUS"
453  # }
454  # EOF
455  # }
456  # makeZBlock(){
457  #     BLOCK="block"
458  #     BLOCK_SIG=$BLOCK".asc"
459  #     # We have a block now, so we sign it
460  #     _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
461  #
462  #     # We now add the signature to IPFS
463  #     BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
464  #
465  #     # We also add the block!
466  #     BLOCK=$(_ak_ipfs_add $BLOCK)
467  #
468  #     # So we now do the think almost again
469  #     cat > zblock << EOF
470  # {
471  #     "block":"$BLOCK",
472  #     "block_signature":"$BLOCK_SIGNATURE"
473  # }
474  # EOF
475  #     ZBL="zblock"
476  #     # and we add it on IPFS
477  #     ZBLOCK=$(_ak_ipfs_add $ZBL)
478  #     echo $ZBLOCK
479  # }
480  #
481  # if [ ! -z $2 ];
482  # then
483  #     PWD="$(pwd)"
484  #
485  #     # We ask which BLOCK is goind to be edited
486  #     BLOCK_TO_ADD="$1"
487  #     # We ask for a ZBLOCK or GENESIS to put in the BLOCK
488  #     PREVIOUS="$2"
489  #
490  #     _ak_ipfs_cat "$BLOCK_TO_ADD"
491  #     if [ $? == 0 ];
492  #     then
493  #         echo "Nice! We found the block"
494  #         _ak_ipfs_get "$BLOCK_TO_ADD"
495  #
496  #         sed -i.bak -e 's/^.*previous.*$/\"previous\":\"'$PREVIOUS'\"/' $BLOCK_TO_ADD
497  #         cat $BLOCK_TO_ADD | jq -M
498  #
499  #         exit 2
500  #     else
501  #         echo "Too bad, it seems the block is not there"
502  #         exit 1
503  #     fi
504  #
505  #     # cat $PWD/zblock | jq -M
506  #     # Optional or extending with
507  #     # python send_as_ak_tx $ZBLOCK
508  #     # or for "offline" use
509  #     echo $ZBLOCK > $ZLATEST
510  #     _ak_ipfs_name_publish --key=zchain $ZBLOCK > /dev/null 2>&1
511  #     _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
512  #     _ak_ipfs_files_cp /zlatest /zarchive/$(date -u +%s)-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
513  #     _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
514  #     _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
515  # else
516  #     usage
517  #     exit 0
518  # fi
519  #
520  # }
521  
522  function _ak_zblock_gen_html(){
523      time_started=$(_ak_datetime_unix_nanosecs)
524      ss=$(echo $time_started | cut -d '.' -f 1)
525      nss=$(echo $time_started | cut -d '.' -f 2)
526      # Check if there are enough arguments
527      if [ $# -lt 1 ]
528      then
529          _ak_log_error "Not enough arguments provided"
530          _ak_help
531          exit 1
532      fi
533      if [ -n "$1" ]
534      then
535          TEST="$(echo -n "$1" | grep -v '^Qm[A-Za-z0-9]\{44\}$')"
536          if [ -n "$TEST" ]
537          then
538              echo not ok
539              exit 1
540          fi
541      fi
542      arg="$(_ak_make_temp_file)"
543      _ak_zblock_show "$1" | jq > $arg
544      _ak_generate_html_header > zblock-$1.html
545      _ak_generate_html_zblock $arg >> zblock-$1.html
546      time_ended=$(_ak_datetime_unix_nanosecs)
547      se=$(echo $time_ended | cut -d '.' -f 1)
548      nse=$(echo $time_ended | cut -d '.' -f 2)
549      printf '    <hr>\n' >> zblock-$1.html
550      printf '    <footer>Generated by %s on %s in %s.' "$PROGRAM" "$(_ak_datetime_human)" "$(( $se - $ss ))">> zblock-$1.html
551      if [ $nse -lt $nss ]
552      then
553          printf '%s seconds</footer>\n' "$(( 1$nse - $nss ))" >> zblock-$1.html
554      else
555          printf '%s seconds</footer>' "$(( $nse - $(echo -n $nss|sed 's/^0*//') ))" >> zblock-$1.html
556      fi
557      printf '</body>' >> zblock-$1.html
558      printf '</html>' >> zblock-$1.html
559      rm $arg
560  }
561  
562  function _ak_zblock_cache(){
563      if [ ! -d "$AK_CACHEDIR/fzblocks" ]
564      then
565          mkdir $AK_CACHEDIR/fzblocks
566      fi
567      FZBLOCKSDIR="$AK_CACHEDIR/fzblocks"
568      if [ ! -z "$1" ] && [ -n "$1" ]
569      then
570          if [ -f "$AK_ZBLOCKDIR/$1" ] && [ "$( (du -b $AK_ZBLOCKDIR/$1 || du -A $AK_ZBLOCKDIR/$1)2>/dev/null | awk '{ print $1 }')" != "0" ]
571          then
572              # if [ "$(sha512sum $AK_ZBLOCKDIR/$1 | awk '{ print $1 }')" == "$(_ak_zblock_show $1 | sha512sum | awk '{ print $1 }')" ]
573              if [ ! -f $FZBLOCKSDIR/$1 ]
574              then
575                  _ak_log_info "No cache found. Caching..."
576                  _ak_zblock_show "$1" > $FZBLOCKSDIR/$1
577              fi
578              if [ ! -f $FZBLOCKSDIR/$1 ]
579              then
580                  _ak_log_info "Caching failed..."
581                  exit 1
582              fi
583              cat $FZBLOCKSDIR/$1
584          else
585              _ak_zblock_show "$1" > $FZBLOCKSDIR/$1
586              if [ $? -ne "0" ]
587              then
588                  _ak_log_error "_ak_zblock_show failed..."
589                  exit 2
590              fi
591              _ak_log_error "Could not find zblock $1..."
592              exit 1
593          fi
594          exit 0
595      else
596          _ak_log_error "No arguments..."
597          exit 1
598      fi
599  }
600  
601  function _ak_zblock_repack(){
602      if [ -z $1 ] || [ ! -n "$1" ]
603      then
604          _ak_log_error "No zblock hash provided"
605          exit 1
606      fi
607      _ak_ipfs_cid_v0_check $1
608      if [ $? -ne 0 ]
609      then
610          _ak_log_error "Not valid zblock hash provided"
611          exit 1
612      fi
613      zblock_to_repack="$1"
614      if [ -z $2 ] || [ ! -n "$2" ]
615      then
616          _ak_log_error "No zblock hash provided"
617          exit 1
618      fi
619      _ak_ipfs_cid_v0_check $2
620      if [ $? -ne 0 ]
621      then
622          _ak_log_error "Not valid zblock hash provided"
623          exit 1
624      fi
625      zblock_to_repack_at="$2"
626      MESSAGE="$zblock_to_repack"
627      ACTION="$(_ak_zblock_show $zblock_to_repack  | jq -r '.module,.action' | tr $'\n' '/' | sed -e 's/\/$//g')"
628      if [ ! -n "$ACTION" ]
629      then
630          _ak_log_error "Empty action"
631          exit 1
632      fi
633      if [ ! -f "$AK_IPFS_ARTIFACTS/$MESSAGE" ]
634      then
635          _ak_log_error "File does not exist. Aborting..."
636          exit 1
637      fi
638      data="$(_ak_zblock_show $zblock_to_repack | jq -r '.data')"
639      if [ ! -f $AK_IPFS_ARTIFACTS/$data ]
640      then
641          _ak_log_error "$data file doesn't exist"
642          exit 1
643      fi
644      _ak_log_info "We are repacking $ACTION with content $MESSAGE at $zblock_to_repack_at"
645      MESSAGE_HASH="$data"
646      # We create a detached and armor signature of it
647      MESSAGE_SIGN_FILE="$data.asc"
648      _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $AK_IPFS_ARTIFACTS/$data
649      _ak_log_debug "Signature made for $data"
650      # We add the signature to IPFS
651      MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
652      _ak_log_debug "Hash made for $data: $MESSAGE_SIGNATURE"
653      # We will be using our public key also to put it in the block later
654      KEY="self.pub"
655      _ak_gpg_key_self_export $KEY
656      GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
657      _ak_log_debug "Key: $GPG_PUB_KEY"
658      # Acquire last block of information, to chain this one with previous posted
659      PREVIOUS="$zblock_to_repack_at"
660      _ak_log_debug "Previous: $PREVIOUS"
661      # We create a block of json like this:
662      printf '{"timestamp":"%s","action":"%s","data":"%s","detach":"%s","gpg":"%s","previous":"%s"}' $(_ak_datetime_unix) $ACTION $MESSAGE_HASH $MESSAGE_SIGNATURE $GPG_PUB_KEY $PREVIOUS > block
663      BLOCK="block"
664      BLOCK_SIG=$BLOCK".asc"
665      # We have a block now, so we sign it
666      _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
667      _ak_log_debug "Signature made for block"
668      # We now add the signature to IPFS
669      BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
670      _ak_log_debug "Block signature hash: $BLOCK_SIGNATURE"
671      # We also add the block!
672      BLOCK=$(_ak_ipfs_add $BLOCK)
673      _ak_log_debug "Block hash: $BLOCK"
674      # So we now do the think almost again
675      printf '{"block":"%s","block_signature":"%s"}' $BLOCK $BLOCK_SIGNATURE > zblock
676      ZBL="zblock"
677      # and we add it on IPFS
678      ZBLOCK=$(_ak_ipfs_add $ZBL)
679      echo $ZBLOCK
680      _ak_log_debug "Zblock hash: $ZBLOCK"
681      # cat $PWD/zblock | jq -M
682      # Optional or extending with
683      # python send_as_ak_tx $ZBLOCK
684      # or for "offline" use
685      archivaltime="$(_ak_datetime_unix)"
686      echo "${archivaltime} $(cat $AK_ZLATEST)" >> $AK_ZLATEST_HISTORY
687      echo $ZBLOCK > $AK_ZLATEST
688      _ak_ipfs_name_publish zchain /ipfs/$ZBLOCK #> /dev/null 2>&1
689      if [ $? -ne 0 ]
690      then
691          _ak_log_error "Failed publishing ZBLOCK: $ZBLOCK"
692          exit 1
693      fi
694      _ak_ipfs_files_ls /zarchive > /dev/null 2>&1
695      if [ $? -ne 0 ]
696      then
697          _ak_log_warning "/zarchive does not exist"
698          _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
699          if [ $? -ne 0 ]
700          then
701              _ak_log_error "Could not create /zarchive directory. Aborting."
702              exit 1
703          fi
704      fi
705      _ak_ipfs_files_cp /zlatest /zarchive/${archivaltime}-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
706      if [ $? -ne 0 ]
707      then
708          _ak_log_error "Could not back up previous /zlatest"
709          exit 1
710      fi
711      _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
712      if [ $? -ne 0 ]
713      then
714          _ak_log_error "Could not remove previous /zlatest"
715          exit 1
716      fi
717      _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
718      if [ $? -ne 0 ]
719      then
720          _ak_log_error "Could not copy $ZBLOCK to /zlatest"
721          exit 1
722      fi
723      _ak_config_publish
724      if [ $? -ne 0 ]
725      then
726          _ak_log_error "Could not publish new configuration"
727          exit 1
728      fi
729  }
730  
731  function _ak_zblock_pack(){
732      if [ ! -z $2 ]
733      then
734          MESSAGE="$2"
735          ACTION="$1"
736          if [ -f "$MESSAGE" ]; then
737              # We check firstly if the encapsulated value of the "ipfs" key has already
738              # appeared in the zchain.
739              TO_CHECK="$(cat $MESSAGE | jq | grep ipfs | awk '{print $2}' | sed -e 's/"//g;s/,//g')"
740              ak-zchain --crawl | jq | grep ipfs | awk '{print $2}' | sed -e 's/"//g;s/,//g' | sort | uniq > tempisalreadythere
741              while IFS="" read -r p || [ -n "$p" ]
742              do
743                  if [ "$p" == "$TO_CHECK" ]
744                  then
745                      _ak_log_error "Value $TO_CHECK already mentioned on the zchain"
746                      exit 1
747                  fi
748              done < tempisalreadythere
749              rm tempisalreadythere
750              _ak_log_info "We are doing $ACTION with content $MESSAGE"
751              # We add it to IPFS
752              MESSAGE_HASH=$(_ak_ipfs_add $MESSAGE)
753              # We create a detached and armor signature of it
754              MESSAGE_SIGN_FILE=$MESSAGE".asc"
755              _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $MESSAGE
756              # We add the signature to IPFS
757              MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
758              # We will be using our public key also to put it in the block later
759              KEY="gpg.pub"
760              _ak_gpg_key_self_export $KEY
761              GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
762              # Acquire last block of information, to chain this one with previous posted
763              PREVIOUS="$(cat $AK_ZLATEST)"
764              # We create a block of json like this:
765              printf '{"timestamp":"%s","action":"%s","data":"%s","detach":"%s","gpg":"%s","previous":"%s"}' "$(_ak_datetime_unix)" "$ACTION" "$MESSAGE_HASH" "$MESSAGE_SIGNATURE" "$GPG_PUB_KEY" "$PREVIOUS" > block
766              BLOCK="block"
767              BLOCK_SIG="${BLOCK}.asc"
768              # We have a block now, so we sign it
769              _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
770              # We now add the signature to IPFS
771              BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
772              # We also add the block!
773              BLOCK=$(_ak_ipfs_add $BLOCK)
774              # So we now do the think almost again
775              printf '{"block":"%s","block_signature":"%s"}' $BLOCK $BLOCK_SIGNATURE > zblock
776              ZBL="zblock"
777              # and we add it on IPFS
778              ZBLOCK=$(_ak_ipfs_add $ZBL)
779              echo $ZBLOCK
780          else
781              _ak_log_error "File does not exist. Aborting..."
782              exit 1
783          fi
784          # cat $PWD/zblock | jq -M
785          # Optional or extending with
786          # python send_as_ak_tx $ZBLOCK
787          # or for "offline" use
788          archivaltime="$(_ak_datetime_unix)"
789          echo "${archivaltime} $(cat $AK_ZLATEST)" >> $AK_ZLATEST_HISTORY
790          echo $ZBLOCK > $AK_ZLATEST
791          _ak_ipfs_name_publish zchain /ipfs/$ZBLOCK > /dev/null 2>&1
792          if [ $? -ne 0 ]
793          then
794              _ak_log_error "Failed publishing ZBLOCK: $ZBLOCK"
795              exit 1
796          fi
797          _ak_ipfs_files_ls /zarchive > /dev/null 2>&1
798          if [ $? -ne 0 ]
799          then
800              _ak_log_warning "/zarchive does not exist"
801              _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
802              if [ $? -ne 0 ]
803              then
804                  _ak_log_error "Could not create /zarchive directory. Aborting."
805                  exit 1
806              fi
807          fi
808          _ak_ipfs_files_cp /zlatest /zarchive/${archivaltime}-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
809          if [ $? -ne 0 ]
810          then
811              _ak_log_error "Could not back up previous /zlatest"
812              exit 1
813          fi
814          _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
815          if [ $? -ne 0 ]
816          then
817              _ak_log_error "Could not remove previous /zlatest"
818              exit 1
819          fi
820          _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
821          if [ $? -ne 0 ]
822          then
823              _ak_log_error "Could not copy $ZBLOCK to /zlatest"
824              exit 1
825          fi
826          _ak_config_publish
827          if [ $? -ne 0 ]
828          then
829              _ak_log_error "Could not publish new configuration"
830              exit 1
831          fi
832      else
833          _ak_log_error "Not enough arguments"
834          exit 1
835      fi
836  }
837  
838  function _ak_zblock_announce(){
839      if [ ! -z "$1" ] && [ -n "$1" ]
840      then
841          curl \
842              --connect-timeout 3 \
843              --header 'Content-Type: application/json' \
844              --data-raw '{"zblock":"'$1'"}' \
845              "http://[$(_ak_settings_get api.bindToIP)]:8610/v0/announce/zblock" \
846              2>/dev/null | jq -M -c > /dev/null
847          if [ $? -ne 0 ]
848          then
849              _ak_log_error "zblock $zblock announcement failed"
850          else
851              _ak_log_info "zblock $zblock announced"
852          fi
853      else
854          curl \
855              --connect-timeout 3 \
856              --header 'Content-Type: application/json' \
857              --data-raw '{"zblock":"'$(ak-zchain --get-latest)'"}' \
858              "http://127.0.0.1:8610/v0/announce/zblock" \
859              2>/dev/null | jq -M -c > /dev/null
860          if [ $? -ne 0 ]
861          then
862              _ak_log_error "zblock $zblock announcement failed"
863          else
864              _ak_log_info "zblock $zblock announced"
865          fi
866      fi
867  }
868  
869  _ak_log_debug "_ak_zblock loaded $(caller)"