#!/usr/bin/env bash
###
### arching-kaos-tools
### Tools to interact and build an Arching Kaos Infochain
### Copyright (C) 2021 - 2025  kaotisk
###
### This program is free software: you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation, either version 3 of the License, or
### (at your option) any later version.
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with this program.  If not, see <http://www.gnu.org/licenses/>.
###
#set -x
source $AK_LIBDIR/_ak_log
source $AK_LIBDIR/_ak_script
source $AK_LIBDIR/_ak_gpg
source $AK_LIBDIR/_ak_html
source $AK_LIBDIR/_ak_ipfs

if [ ! -d $AK_WORKDIR/ipfs ]
then
    mkdir $AK_WORKDIR/ipfs
fi

function _ak_data_expand(){
    if [ ! -z $1 ] && [ ! -z $2 ] && [ -n "$1" ] && [ -n "$2" ]
    then
        TEMP="$(_ak_make_temp_directory)"
        cd $TEMP
        _ak_ipfs_cid_v0_check $1
        _ak_ipfs_cat $1 > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while reading $1"
            exit 1
        fi
        _ak_ipfs_cat $1 | jq -M > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while parsing JSON for $1"
            exit 1
        fi
        _ak_ipfs_cat $1 | jq | grep ipfs > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "_ak_data_expand: No 'ipfs' field in $1"
            exit 1
        fi
        DATA="$(_ak_ipfs_cat $1 | jq -r '.ipfs')" #| grep ipfs | sed -e 's/"ipfs": "//g; s/[",]//g; s/ //g')"
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while extracting data from JSON for $1"
            exit 1
        fi
        _ak_ipfs_cat $1 | jq | grep detach > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "_ak_data_expand: No 'detach' field in $1"
            exit 1
        fi
        DETACH="$(_ak_ipfs_cat $1 | jq -r '.detach')" #| grep detach | sed -e 's/"detach": "//g; s/[",]//g; s/ //g')"
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while extracting data from JSON for $1"
            exit 1
        fi
        _ak_ipfs_cid_v0_check $2
        gpg="$2"
        _ak_ipfs_get $gpg > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not get GPG key: $gpg"
        exit 1
        fi
        _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not import GPG key: $gpg"
            exit 1
        fi
        _ak_ipfs_get $DETACH > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while getting signature: $DETACH for data: $DATA"
            exit 1
        fi
        if [ ! -f $AK_IPFS_ARTIFACTS/$DETACH ]
        then
            _ak_log_error "$DETACH was downloaded but not found"
            exit 1
        fi
        ln -s $AK_IPFS_ARTIFACTS/$DETACH $TEMP/$DATA.asc
        _ak_log_debug "DATA_SIGNATURE $DETACH downloaded"
        _ak_ipfs_get $DATA > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while getting data: $DATA"
            exit 1
        fi
        _ak_log_debug "DATA $DATA downloaded"
        _ak_gpg_verify_signature $TEMP/$DATA.asc $AK_IPFS_ARTIFACTS/$DATA # > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Error while verifying signature for $DATA"
            exit 1
        fi
        # ln -s $AK_IPFS_ARTIFACTS/$DATA $AK_WORKDIR/ipfs
        _ak_log_info "DATA_SIGNATURE $DATA_SIGNATURE verified"
        echo -n '"data":"'$1'","'$1'":'$(_ak_ipfs_cat $1|jq -M -c)','
        cd
        # rm -rf $TEMP
    else
        _ak_log_error "_ak_data_expand HASH GPG"
        exit 1
    fi
}

# _ak_zblock_show
# ak-zblock [IPFS CID]
#
# Returns a JSON array representing the chain retrieved.
# Logs messages to $LOGSFILE.
function _ak_zblock_show(){
    verify=1
    if [ ! -z $1 ] && [ -n "$1" ]
    then
        _ak_ipfs_cid_v0_check $1
        entrance="$1"
    else
        entrance="$(cat $AK_ZLATEST)"
    fi
    TEMP=$(_ak_make_temp_directory)
    cd $TEMP
    zblock=$entrance
    # Check if $zblock exists as variable
    if [ ! -v $zblock ]
    then
        # Check if it is not our seed cause if it is we skip this part
        if [ "$zblock" != "$seed" ]
        then
            # Reset timestamp since it's introduced later
            timestamp=''
            # Announce to logs which ZBLOCK is being read at the moment
            _ak_log_info "Examining $zblock"
            _ak_ipfs_cid_v0_check "$zblock"
            # We check if any $zblock at all...
            # TODO: Eliminate outputing to file since we store all cat/get'ed
            #       ipfs hashes on local fs.
            _ak_ipfs_cat $zblock > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "ZBLOCK $zblock unreachable"
                exit 1
            fi
            _ak_log_debug "ZBLOCK $zblock within reach"
            # ...and if it's JSON formated
            cat $AK_IPFS_ARTIFACTS/$zblock | jq > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "ZBLOCK $zblock is not JSON"
                cat /dev/null > $AK_IPFS_ARTIFACTS/$zblock > /dev/null 2>&1
                exit 1
            fi
            _ak_log_debug "ZBLOCK $zblock is JSON"
            echo -n '{'
#            echo -n '"id":"'$counter'",'
            echo -n '"zblock":"'$zblock'",'
            # Be sure that there are the expected values
            # We need 'block' and 'block_signature' inside a 'zblock'
            # Exit if any is missing
            block="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block)"
            if [ "$block" == "null" ]
            then
                _ak_log_error "ZBLOCK $zblock has no BLOCK"
                exit 1
            fi
            _ak_ipfs_cid_v0_check "$block"
            _ak_log_debug "ZBLOCK $zblock has block $block"
            block_signature="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block_signature)"
            if [ "$block_signature" == "null" ]
            then
                _ak_log_error "ZBLOCK $zblock has no BLOCK_SIGNATURE"
                exit 1
            fi
            _ak_ipfs_cid_v0_check "$block_signature"
            _ak_log_debug "ZBLOCK $zblock contains a BLOCK_SIGNATURE $block_signature"
            # Same as above applies to BLOCK and DATA subparts of each ZBLOCK
            # BLOCKS
            echo -n '"block":"'$block'",'
            echo -n '"block_signature":"'$block_signature'",'
            _ak_ipfs_cat $block | jq -c -M > /dev/null 2>&1
            cat $AK_IPFS_ARTIFACTS/$block | jq -M > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "BLOCK $block READ failed"
                exit 1
            fi
            grep -e 'timestamp' -e 'gpg' -e 'data' -e 'action' -e 'detach' -e 'previous' $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "BLOCK $block is NOT a valid block"
                exit 1
            fi
            _ak_log_debug "BLOCK $block is a block"
            action="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .action)"
            module="$(echo $action | sed -e 's/\// /g' | awk '{ print $1 }')"
            _ak_log_debug "DATA is $module module."
            command="$(echo $action | sed -e 's/\// /g' | awk '{ print $2 }')"
            _ak_log_debug "COMMAND is $command"
            timestamp="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .timestamp)"
            if [ "$timestamp" != "null" ]
            then
                echo -n '"timestamp":"'$timestamp'",'
            fi
            detach="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .detach)"
            echo -n '"detach":"'$detach'",'
            echo -n '"module":"'$module'",'
            echo -n '"action":"'$command'",'
            gpg="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .gpg)"
            echo -n '"gpg":"'$gpg'",'
            if [ $verify -eq 1 ]
            then
                _ak_ipfs_get $gpg > /dev/null 2>&1
                if [ $? -ne 0 ]
                then
                    _ak_log_error "Could not get GPG key: $gpg ."
                    exit 1
                fi
                _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1
                if [ $? -ne 0 ]
                then
                    _ak_log_error "Could not import GPG key: $gpg ."
                    exit 1
                fi
                _ak_ipfs_get $block_signature > /dev/null 2>&1
                if [ $? -ne 0 ]
                then
                    _ak_log_error "Error while getting BLOCK_SIGNATURE $block_signature for BLOCK $block"
                    exit 1
                fi
                ln -s $AK_IPFS_ARTIFACTS/$block_signature $TEMP/$block.asc
                _ak_log_info "BLOCK_SIGNATURE $block_signature downloaded"
                _ak_ipfs_get $block > /dev/null 2>&1
                if [ $? -ne 0 ]
                then
                    _ak_log_error "Could not get $block block"
                    exit 1
                fi
                _ak_log_info "BLOCK $block downloaded"
                _ak_gpg_verify_signature $TEMP/$block.asc $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1
                if [ $? -ne 0 ]
                then
                    _ak_log_error "Could not verify $block with GPG key $gpg."
                    exit 1
                fi
                _ak_log_info "$gpg signature of $block is verified."
            fi
            data="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .data)"
            _ak_ipfs_cid_v0_check "$data"
            _ak_data_expand $data $gpg
            if [ $? -ne 0 ]
            then
                _ak_log_error "Failed on data signature verification [data: $data, gpg: $gpg, zblock: $zblock]"
                exit 1
            fi
            # DATA
            # Only print to stdout
            # _ak_ipfs_cat $data
            # touch $AK_DATADIR/$data
            # ^ unreasonable?
            # Now, since we sourced the BLOCK to our terminal, we can search
            # for $previous variable. In case we don't find one, we append one
            # and we exit.
            previous="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .previous)"
            if [ -v $previous ]
            then
                _ak_log_warning "Block $block has no previous zblock, appending pseudo genesis to exit with 2."
                echo -n '"previous":"'$seed'"},{"genesis":"genesis"}]'
                _ak_log_info "Reached pseudo-genesis, counted $counter zblocks."
                exit 2
            # Otherwise, we inform of the sequence
            else
                #echo "$zblock after $previous"
                _ak_log_info "Found a previous block for $zblock: $previous"
                echo -n '"previous":"'$previous'"}'
                zblock=$previous
            fi
        # Now check if it is equal to the seed
        # which apparently means we reached the seed.
        elif [ "$zblock" == "$seed" ]
        then
            echo -n '{"genesis":"genesis"}]'
            _ak_log_info "Reached $seed, counted $counter zblocks."
            exit 0
        fi
    # And finally, if nothing is there exit with error
    else
        echo "Check not passed... No previous IPFS CID"
        exit 1
    fi
}

# _ak_zblock_manipulator(){
# # This file describe the structure of the ArchingKaos messages in their basis.
# #
# # As previously thought, we exchange one IPFS hash through whatever means we can.
# #
# # GPG is mentioned as a signing algorithm for encryption, decryption and signing.
# # Let's say we have a file named as `example`
# #
# # We can extend this with calling the encoder and further send the transaction
# #
#
# #FINGERPRINT="CHANGE THIS TO YOUR DEFAULT FINGERPRINT"
# # We acquire the GPG fingerprint by email address
# # The following example finds kaos@kaos.kaos' GPG fingerprint like this
# # FINGERPRINT="$(gpg2 --homedir $AK_GPGHOME --list-keys | grep kaos@kaos.kaos -1 | head -n1 | awk '{print $1}')"
#
# # Below, the usage information
# PROGRAM="$(basename $0)"
# source $AK_LIBDIR/_ak_log
# source $AK_LIBDIR/_ak_ipfs
# source $AK_LIBDIR/_ak_gpg
#
# usage(){
#     echo "Usage:"
#     echo "$PROGRAM -b block_file | -h block_hash | dunno"
#     echo "Creates and publishes a ZBLOCK based on a block and a previous"
#     echo "zblock."
#     echo ""
#     echo "Either -b or -h is needed. If both, -h is used."
#     echo ""
#     echo "-b block_file        Points to a block file that we want to fix."
#     echo "-h block_hash        If we don't have the block as a file, we can"
#     echo "                use it's hash to retrieve it and edit it."
#     echo "-p previous_hash        We refering to a previous hash for a ZBLOCK."
#     echo ""
#     echo "#TODO:"
#     echo "-t timestamp        Unix UTC timestamp in seconds."
#     echo "-a \"module/action\"    Change the action tag. Format: object/verb."
#     echo "                In sense, \"Add news -> news/add\"."
#     echo "-d data            In case you want to change the data, you 'll"
#     echo "                be changing potentially the key of the block"
#     echo "                and the data signature, otherwise your block"
#     echo "                will be unverified."
#     echo ""
# }
#
# main(){
#
#     _ak_log_info "We are doing" $BLOCK_TO_ADD "with content" $PREVIOUS
#     # We add it to IPFS
#     MESSAGE_HASH=$(_ak_ipfs_add $MESSAGE)
#
#     # We create a detached and armor signature of it
#     MESSAGE_SIGN_FILE=$MESSAGE".asc"
#     _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $MESSAGE
#
#     # We add the signature to IPFS
#     MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
#
#     # We will be using our public key also to put it in the block later
#     KEY="gpg.pub"
#     _ak_gpg_key_self_export $KEY
#     GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
#
#     # Acquire last block of information, to chain this one with previous posted
#     PREVIOUS=$(_ak_ipfs_files_stat /zlatest | head -n 1)
#
#     # We create a block of json like this:
#     cat > block <<EOF
# {
#     "timestamp":"$(date -u +%s)",
#     "action":"$ACTION",
#     "data":"$MESSAGE_HASH",
#     "detach":"$MESSAGE_SIGNATURE",
#     "gpg":"$GPG_PUB_KEY",
#     "previous":"$PREVIOUS"
# }
# EOF
# }
# makeZBlock(){
#     BLOCK="block"
#     BLOCK_SIG=$BLOCK".asc"
#     # We have a block now, so we sign it
#     _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
#
#     # We now add the signature to IPFS
#     BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
#
#     # We also add the block!
#     BLOCK=$(_ak_ipfs_add $BLOCK)
#
#     # So we now do the think almost again
#     cat > zblock << EOF
# {
#     "block":"$BLOCK",
#     "block_signature":"$BLOCK_SIGNATURE"
# }
# EOF
#     ZBL="zblock"
#     # and we add it on IPFS
#     ZBLOCK=$(_ak_ipfs_add $ZBL)
#     echo $ZBLOCK
# }
#
# if [ ! -z $2 ];
# then
#     PWD="$(pwd)"
#
#     # We ask which BLOCK is goind to be edited
#     BLOCK_TO_ADD="$1"
#     # We ask for a ZBLOCK or GENESIS to put in the BLOCK
#     PREVIOUS="$2"
#
#     _ak_ipfs_cat "$BLOCK_TO_ADD"
#     if [ $? == 0 ];
#     then
#         echo "Nice! We found the block"
#         _ak_ipfs_get "$BLOCK_TO_ADD"
#
#         sed -i.bak -e 's/^.*previous.*$/\"previous\":\"'$PREVIOUS'\"/' $BLOCK_TO_ADD
#         cat $BLOCK_TO_ADD | jq -M
#
#         exit 2
#     else
#         echo "Too bad, it seems the block is not there"
#         exit 1
#     fi
#
#     # cat $PWD/zblock | jq -M
#     # Optional or extending with
#     # python send_as_ak_tx $ZBLOCK
#     # or for "offline" use
#     echo $ZBLOCK > $ZLATEST
#     _ak_ipfs_name_publish --key=zchain $ZBLOCK > /dev/null 2>&1
#     _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
#     _ak_ipfs_files_cp /zlatest /zarchive/$(date -u +%s)-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
#     _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
#     _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
# else
#     usage
#     exit 0
# fi
#
# }

function _ak_zblock_gen_html(){
    time_started=$(date -u +%s.%N)
    ss=$(echo $time_started | cut -d '.' -f 1)
    nss=$(echo $time_started | cut -d '.' -f 2)
    # Check if there are enough arguments
    if [ $# -lt 1 ]
    then
        _ak_log_error "Not enough arguments provided"
        _ak_help
        exit 1
    fi
    if [ -n "$1" ]
    then
        TEST="$(echo -n "$1" | grep -v '^Qm[A-Za-z0-9]\{44\}$')"
        if [ -n "$TEST" ]
        then
            echo not ok
            exit 1
        fi
    fi
    arg="$(_ak_make_temp_file)"
    _ak_zblock_show "$1" | jq > $arg
    _ak_generate_html_header > zblock-$1.html
    _ak_generate_html_zblock $arg >> zblock-$1.html
    time_ended=$(date -u +%s.%N)
    se=$(echo $time_ended | cut -d '.' -f 1)
    nse=$(echo $time_ended | cut -d '.' -f 2)
    printf '    <hr>\n' >> zblock-$1.html
    printf '    <footer>Generated by %s on %s in %s.' "$PROGRAM" "$(datehuman)" "$(( $se - $ss ))">> zblock-$1.html
    if [ $nse -lt $nss ]
    then
        printf '%s seconds</footer>\n' "$(( 1$nse - $nss ))" >> zblock-$1.html
    else
        printf '%s seconds</footer>' "$(( $nse - $(echo -n $nss|sed 's/^0*//') ))" >> zblock-$1.html
    fi
    printf '</body>' >> zblock-$1.html
    printf '</html>' >> zblock-$1.html
    rm $arg
}

function _ak_zblock_cache(){
    if [ ! -d "$AK_CACHEDIR/fzblocks" ]
    then
        mkdir $AK_CACHEDIR/fzblocks
    fi
    FZBLOCKSDIR="$AK_CACHEDIR/fzblocks"
    if [ ! -z "$1" ] && [ -n "$1" ]
    then
        if [ -f "$AK_ZBLOCKDIR/$1" ] && [ "$( (du -b $AK_ZBLOCKDIR/$1 || du -A $AK_ZBLOCKDIR/$1)2>/dev/null | awk '{ print $1 }')" != "0" ]
        then
            # if [ "$(sha512sum $AK_ZBLOCKDIR/$1 | awk '{ print $1 }')" == "$(_ak_zblock_show $1 | sha512sum | awk '{ print $1 }')" ]
            if [ ! -f $FZBLOCKSDIR/$1 ]
            then
                _ak_log_info "No cache found. Caching..."
                _ak_zblock_show "$1" > $FZBLOCKSDIR/$1
            fi
            if [ ! -f $FZBLOCKSDIR/$1 ]
            then
                _ak_log_info "Caching failed..."
                exit 1
            fi
            cat $FZBLOCKSDIR/$1
        else
            _ak_zblock_show "$1" > $FZBLOCKSDIR/$1
            if [ $? -ne "0" ]
            then
                _ak_log_error "_ak_zblock_show failed..."
                exit 2
            fi
            _ak_log_error "Could not find zblock $1..."
            exit 1
        fi
        exit 0
    else
        _ak_log_error "No arguments..."
        exit 1
    fi
}

function _ak_zblock_repack(){
    if [ -z $1 ] || [ ! -n "$1" ]
    then
        _ak_log_error "No zblock hash provided"
        exit 1
    fi
    _ak_ipfs_cid_v0_check $1
    if [ $? -ne 0 ]
    then
        _ak_log_error "Not valid zblock hash provided"
        exit 1
    fi
    zblock_to_repack="$1"
    if [ -z $2 ] || [ ! -n "$2" ]
    then
        _ak_log_error "No zblock hash provided"
        exit 1
    fi
    _ak_ipfs_cid_v0_check $2
    if [ $? -ne 0 ]
    then
        _ak_log_error "Not valid zblock hash provided"
        exit 1
    fi
    zblock_to_repack_at="$2"
    MESSAGE="$zblock_to_repack"
    ACTION="$(_ak_zblock_show $zblock_to_repack  | jq -r '.module,.action' | tr $'\n' '/' | sed -e 's/\/$//g')"
    if [ ! -n "$ACTION" ]
    then
        _ak_log_error "Empty action"
        exit 1
    fi
    if [ ! -f "$AK_IPFS_ARTIFACTS/$MESSAGE" ]
    then
        _ak_log_error "File does not exist. Aborting..."
        exit 1
    fi
    data="$(_ak_zblock_show $zblock_to_repack | jq -r '.data')"
    if [ ! -f $AK_IPFS_ARTIFACTS/$data ]
    then
        _ak_log_error "$data file doesn't exist"
        exit 1
    fi
    _ak_log_info "We are repacking $ACTION with content $MESSAGE at $zblock_to_repack_at"
    MESSAGE_HASH="$data"
    # We create a detached and armor signature of it
    MESSAGE_SIGN_FILE="$data.asc"
    _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $AK_IPFS_ARTIFACTS/$data
    _ak_log_debug "Signature made for $data"
    # We add the signature to IPFS
    MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
    _ak_log_debug "Hash made for $data: $MESSAGE_SIGNATURE"
    # We will be using our public key also to put it in the block later
    KEY="self.pub"
    _ak_gpg_key_self_export $KEY
    GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
    _ak_log_debug "Key: $GPG_PUB_KEY"
    # Acquire last block of information, to chain this one with previous posted
    PREVIOUS="$zblock_to_repack_at"
    _ak_log_debug "Previous: $PREVIOUS"
    # We create a block of json like this:
    printf '{"timestamp":"%s","action":"%s","data":"%s","detach":"%s","gpg":"%s","previous":"%s"}' $(date -u +%s) $ACTION $MESSAGE_HASH $MESSAGE_SIGNATURE $GPG_PUB_KEY $PREVIOUS > block
    BLOCK="block"
    BLOCK_SIG=$BLOCK".asc"
    # We have a block now, so we sign it
    _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
    _ak_log_debug "Signature made for block"
    # We now add the signature to IPFS
    BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
    _ak_log_debug "Block signature hash: $BLOCK_SIGNATURE"
    # We also add the block!
    BLOCK=$(_ak_ipfs_add $BLOCK)
    _ak_log_debug "Block hash: $BLOCK"
    # So we now do the think almost again
    printf '{"block":"%s","block_signature":"%s"}' $BLOCK $BLOCK_SIGNATURE > zblock
    ZBL="zblock"
    # and we add it on IPFS
    ZBLOCK=$(_ak_ipfs_add $ZBL)
    echo $ZBLOCK
    _ak_log_debug "Zblock hash: $ZBLOCK"
    # cat $PWD/zblock | jq -M
    # Optional or extending with
    # python send_as_ak_tx $ZBLOCK
    # or for "offline" use
    echo $ZBLOCK > $AK_ZLATEST
    _ak_ipfs_name_publish zchain /ipfs/$ZBLOCK #> /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        _ak_log_error "Failed publishing ZBLOCK: $ZBLOCK"
        exit 1
    fi
    _ak_ipfs_files_ls /zarchive > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        _ak_log_warning "/zarchive does not exist"
        _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not create /zarchive directory. Aborting."
            exit 1
        fi
    fi
    _ak_ipfs_files_cp /zlatest /zarchive/$(date -u +%s)-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        _ak_log_error "Could not back up previous /zlatest"
        exit 1
    fi
    _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        _ak_log_error "Could not remove previous /zlatest"
        exit 1
    fi
    _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        _ak_log_error "Could not copy $ZBLOCK to /zlatest"
        exit 1
    fi
    _ak_config_publish
    if [ $? -ne 0 ]
    then
        _ak_log_error "Could not publish new configuration"
        exit 1
    fi
}

function _ak_zblock_pack(){
    if [ ! -z $2 ]
    then
        MESSAGE="$2"
        ACTION="$1"
        if [ -f "$MESSAGE" ]; then
            # We check firstly if the encapsulated value of the "ipfs" key has already
            # appeared in the zchain.
            TO_CHECK="$(cat $MESSAGE | jq | grep ipfs | awk '{print $2}' | sed -e 's/"//g;s/,//g')"
            ak-zchain --crawl | jq | grep ipfs | awk '{print $2}' | sed -e 's/"//g;s/,//g' | sort | uniq > tempisalreadythere
            while IFS="" read -r p || [ -n "$p" ]
            do
                if [ "$p" == "$TO_CHECK" ]
                then
                    _ak_log_error "Value $TO_CHECK already mentioned on the zchain"
                    exit 1
                fi
            done < tempisalreadythere
            rm tempisalreadythere
            _ak_log_info "We are doing $ACTION with content $MESSAGE"
            # We add it to IPFS
            MESSAGE_HASH=$(_ak_ipfs_add $MESSAGE)
            # We create a detached and armor signature of it
            MESSAGE_SIGN_FILE=$MESSAGE".asc"
            _ak_gpg_sign_detached $MESSAGE_SIGN_FILE $MESSAGE
            # We add the signature to IPFS
            MESSAGE_SIGNATURE=$(_ak_ipfs_add $MESSAGE_SIGN_FILE)
            # We will be using our public key also to put it in the block later
            KEY="gpg.pub"
            _ak_gpg_key_self_export $KEY
            GPG_PUB_KEY=$(_ak_ipfs_add $KEY)
            # Acquire last block of information, to chain this one with previous posted
            PREVIOUS=$(_ak_ipfs_files_stat /zlatest | head -n 1)
            # We create a block of json like this:
            printf '{"timestamp":"%s","action":"%s","data":"%s","detach":"%s","gpg":"%s","previous":"%s"}' $(date -u +%s) $ACTION $MESSAGE_HASH $MESSAGE_SIGNATURE $GPG_PUB_KEY $PREVIOUS > block
            BLOCK="block"
            BLOCK_SIG=$BLOCK".asc"
            # We have a block now, so we sign it
            _ak_gpg_sign_detached $BLOCK_SIG $BLOCK
            # We now add the signature to IPFS
            BLOCK_SIGNATURE=$(_ak_ipfs_add $BLOCK_SIG)
            # We also add the block!
            BLOCK=$(_ak_ipfs_add $BLOCK)
            # So we now do the think almost again
            printf '{"block":"%s","block_signature":"%s"}' $BLOCK $BLOCK_SIGNATURE > zblock
            ZBL="zblock"
            # and we add it on IPFS
            ZBLOCK=$(_ak_ipfs_add $ZBL)
            echo $ZBLOCK
        else
            _ak_log_error "File does not exist. Aborting..."
            exit 1
        fi
        # cat $PWD/zblock | jq -M
        # Optional or extending with
        # python send_as_ak_tx $ZBLOCK
        # or for "offline" use
        echo $ZBLOCK > $AK_ZLATEST
        _ak_ipfs_name_publish zchain /ipfs/$ZBLOCK > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Failed publishing ZBLOCK: $ZBLOCK"
            exit 1
        fi
        _ak_ipfs_files_ls /zarchive > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_warning "/zarchive does not exist"
            _ak_ipfs_files_mkdir /zarchive > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "Could not create /zarchive directory. Aborting."
                exit 1
            fi
        fi
        _ak_ipfs_files_cp /zlatest /zarchive/$(date -u +%s)-$(_ak_ipfs_files_stat /zlatest | head -n 1) > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not back up previous /zlatest"
            exit 1
        fi
        _ak_ipfs_files_rm /zlatest > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not remove previous /zlatest"
            exit 1
        fi
        _ak_ipfs_files_cp /ipfs/$ZBLOCK /zlatest > /dev/null 2>&1
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not copy $ZBLOCK to /zlatest"
            exit 1
        fi
        _ak_config_publish
        if [ $? -ne 0 ]
        then
            _ak_log_error "Could not publish new configuration"
            exit 1
        fi
    else
        _ak_log_error "Not enough arguments"
        exit 1
    fi
}

function _ak_zblock_announce(){
    if [ ! -z "$1" ] && [ -n "$1" ]
    then
        curl \
            --connect-timeout 3 \
            --header 'Content-Type: application/json' \
            --data-raw '{"zblock":"'$1'"}' \
            "http://[$(_ak_settings_get api.bindToIP)]:8610/v0/announce/zblock" \
            2>/dev/null | jq -M -c > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "zblock $zblock announcement failed"
        else
            _ak_log_info "zblock $zblock announced"
        fi
    else
        curl \
            --connect-timeout 3 \
            --header 'Content-Type: application/json' \
            --data-raw '{"zblock":"'$(ak-zchain --get-latest)'"}' \
            "http://127.0.0.1:8610/v0/announce/zblock" \
            2>/dev/null | jq -M -c > /dev/null
        if [ $? -ne 0 ]
        then
            _ak_log_error "zblock $zblock announcement failed"
        else
            _ak_log_info "zblock $zblock announced"
        fi
    fi
}