// File: /workspace/github_cpp_makefile_star2_O2/adamjanovsky[P]PA193_test_parser_monero/src/block.cpp
// Function: Block::get_block_hash(std::array<unsigned char, 32ul>&) const
int Block::get_block_hash(hash::hash_t & block_hash) const {
    // Exit if the block is not initialized
    if (this->initialized == false) {
        return ERR_BL_NOT_INITIALIZED;
    }
    
    hash::hash_t miner_tx_hash;

    if(get_miner_tx_hash(miner_tx_hash)) {
        std::cerr << "Block hash: Failed to obtain miner_tx hash." << std::endl;
        return ERR_BL_HASH_MINER_TX_FAIL;
    }

    std::vector<unsigned char> all_hashes_vect;

    // push back the miner_tx hash
    all_hashes_vect.insert(all_hashes_vect.end(), miner_tx_hash.begin(), miner_tx_hash.end());
    // push back the other hashes
    all_hashes_vect.insert(all_hashes_vect.end(), tx_hashes.begin(), tx_hashes.end());

    // get the tree root hash
    hash::hash_t tree_root_hash;
    tools::tree_hash(all_hashes_vect, tree_root_hash);

    // blob that will be hashed to get the block hash
    std::vector<unsigned char>hashing_blob;
    // push back the block header
    hashing_blob.insert(hashing_blob.end(), block_header.begin(), block_header.end());
    // push back the tree root hash
    hashing_blob.insert(hashing_blob.end(), tree_root_hash.begin(), tree_root_hash.end());

    // count all transactions including the miner tx
    unsigned long all_tx_count = 1 + tx_hashes_count;
    // append it serialized as varint to the blob
    tools::write_varint(hashing_blob, all_tx_count);

    unsigned char vect_size = static_cast<unsigned char>(hashing_blob.size());
    hashing_blob.insert(hashing_blob.begin(), vect_size);

    tools::hash(hashing_blob.data(), hashing_blob.size(), &block_hash[0]);

    // corrupted block, see monero source crypto/cryptonote_format_utils.cpp and function calculate_block_hash
    // we've solved it by hardcoded value, similarly to authors of monero
    if(block_hash.size() == hash::corruptedBlockHash.size() and !memcmp(block_hash.data(), hash::corruptedBlockHash.data(), hash::HASH_SIZE))
    {
        memcpy(block_hash.data(), hash::corruptedBlockHashCorrected.data(), hash::HASH_SIZE);
    }

    return OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r14
pushq %rbx
subq $0x80, %rsp
cmpb $0x0, (%rdi)
je 0x30a2
movq %rsi, %rbx
movq %rdi, %r14
leaq -0x90(%rbp), %rsi
callq 0x2fd0
testl %eax, %eax
je 0x30aa
movq 0x4f66(%rip), %rdi      # 0x7ff0
leaq 0x23ac(%rip), %rsi      # 0x543d
callq 0x2120
movq %rax, %rdi
callq 0x20a0
pushq $-0x3
jmp 0x30a4
pushq $-0x1
popq %rax
jmp 0x31a2
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %rdi
movaps %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
leaq -0x70(%rbp), %rcx
leaq -0x90(%rbp), %rdx
xorl %esi, %esi
callq 0x3212
leaq -0x50(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq 0x80(%r14), %rdx
movq 0x88(%r14), %rcx
callq 0x3232
leaq -0x50(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x3d2b
leaq -0x30(%rbp), %rdi
andq $0x0, 0x10(%rdi)
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq 0x48(%r14), %rdx
movq 0x50(%r14), %rcx
xorl %esi, %esi
callq 0x3232
leaq -0x30(%rbp), %rdi
movq 0x8(%rdi), %rsi
leaq -0x50(%rbp), %rcx
leaq -0x70(%rbp), %rdx
callq 0x3212
movq 0x98(%r14), %rsi
incq %rsi
leaq -0x30(%rbp), %rdi
callq 0x3a7a
leaq -0x30(%rbp), %rdi
movl 0x8(%rdi), %eax
movq (%rdi), %rsi
subl %esi, %eax
leaq -0x11(%rbp), %rdx
movb %al, (%rdx)
callq 0x3252
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
subq %rdi, %rsi
movq %rbx, %rdx
callq 0x3cf9
leaq 0x2348(%rip), %rsi      # 0x54b2
pushq $0x20
popq %rdx
movq %rbx, %rdi
callq 0x2150
testl %eax, %eax
jne 0x318e
movups 0x2362(%rip), %xmm0     # 0x54e2
movups %xmm0, 0x10(%rbx)
movups 0x2347(%rip), %xmm0     # 0x54d2
movups %xmm0, (%rbx)
leaq -0x30(%rbp), %rdi
callq 0x260a
leaq -0x50(%rbp), %rdi
callq 0x260a
xorl %eax, %eax
addq $0x80, %rsp
popq %rbx
popq %r14
popq %rbp
retq
jmp 0x31b6
jmp 0x31b6
jmp 0x31b6
jmp 0x31b6
movq %rax, %rbx
leaq -0x30(%rbp), %rdi
callq 0x260a
jmp 0x31cb
jmp 0x31c8
jmp 0x31c8
movq %rax, %rbx
leaq -0x50(%rbp), %rdi
callq 0x260a
movq %rbx, %rdi
callq 0x2240