// File: /workspace/github_cpp_makefile_star2_O3/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 0x3653
movq %rsi, %rbx
movq %rdi, %r14
leaq -0x90(%rbp), %rsi
callq 0x3550
testl %eax, %eax
je 0x365d
movq 0x49e2(%rip), %rbx      # 0x7ff0
leaq 0x1e73(%rip), %rsi      # 0x5488
movl $0x2b, %edx
movq %rbx, %rdi
callq 0x2160
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
jmp 0x3779
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x3779
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %rdi
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
leaq -0x70(%rbp), %rcx
leaq -0x90(%rbp), %rdx
xorl %esi, %esi
callq 0x3a7c
leaq -0x50(%rbp), %rdi
movq 0x8(%rdi), %rsi
movq 0x80(%r14), %rdx
movq 0x88(%r14), %rcx
callq 0x3c74
leaq -0x50(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x4557
xorps %xmm0, %xmm0
leaq -0x30(%rbp), %rdi
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
movq 0x48(%r14), %rdx
movq 0x50(%r14), %rcx
xorl %esi, %esi
callq 0x3c74
leaq -0x30(%rbp), %rdi
movq 0x8(%rdi), %rsi
leaq -0x50(%rbp), %rcx
leaq -0x70(%rbp), %rdx
callq 0x3a7c
movq 0x98(%r14), %rsi
incq %rsi
leaq -0x30(%rbp), %rdi
callq 0x414a
leaq -0x30(%rbp), %rdi
movl 0x8(%rdi), %eax
movq (%rdi), %rsi
subl %esi, %eax
leaq -0x11(%rbp), %rdx
movb %al, (%rdx)
callq 0x37f4
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
subq %rdi, %rsi
movq %rbx, %rdx
callq 0x4523
movdqu (%rbx), %xmm0
movdqu 0x10(%rbx), %xmm1
pcmpeqb 0x19e3(%rip), %xmm1     # 0x5110
pcmpeqb 0x19eb(%rip), %xmm0     # 0x5120
pand %xmm1, %xmm0
pmovmskb %xmm0, %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jne 0x375b
movups 0x1de2(%rip), %xmm0     # 0x552d
movups %xmm0, 0x10(%rbx)
movdqu 0x1dc6(%rip), %xmm0     # 0x551d
movdqu %xmm0, (%rbx)
movq -0x30(%rbp), %rdi
testq %rdi, %rdi
je 0x3769
callq 0x2110
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x3777
callq 0x2110
xorl %eax, %eax
addq $0x80, %rsp
popq %rbx
popq %r14
popq %rbp
retq
jmp 0x378d
jmp 0x378d
jmp 0x378d
jmp 0x378d
movq %rax, %rbx
movq -0x30(%rbp), %rdi
testq %rdi, %rdi
je 0x37a7
callq 0x2110
jmp 0x37a7
jmp 0x37a4
jmp 0x37a4
movq %rax, %rbx
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x37b5
callq 0x2110
movq %rbx, %rdi
callq 0x2220
nop