// File: 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
subq $0x200, %rsp            # imm = 0x200
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x148(%rbp)
movb (%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x4056
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x44c9
movq -0x148(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x3ec0
cmpl $0x0, %eax
je 0x4099
movq 0x8f7e(%rip), %rdi      # 0xcff0
leaq 0x53c6(%rip), %rsi      # 0x943f
callq 0x2160
movq %rax, %rdi
movq 0x8f38(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x44c9
leaq -0x50(%rbp), %rdi
movq %rdi, -0x160(%rbp)
callq 0x2860
movq -0x160(%rbp), %rdi
callq 0x4790
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x47c0
leaq -0x38(%rbp), %rdi
movq %rdi, -0x168(%rbp)
callq 0x4560
movq -0x168(%rbp), %rdi
movq %rax, -0x158(%rbp)
callq 0x4800
movq -0x160(%rbp), %rdi
movq -0x158(%rbp), %rdx
movq %rax, %rcx
movq -0x58(%rbp), %rsi
callq 0x46f0
movq %rax, -0x150(%rbp)
jmp 0x410c
movq -0x150(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0x4790
movq %rax, -0x88(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x47c0
movq -0x148(%rbp), %rdi
subq $-0x80, %rdi
movq %rdi, -0x180(%rbp)
callq 0x48d0
movq -0x180(%rbp), %rdi
movq %rax, -0x90(%rbp)
callq 0x4900
movq -0x178(%rbp), %rdi
movq %rax, -0x98(%rbp)
movq -0x80(%rbp), %rsi
movq -0x90(%rbp), %rdx
movq -0x98(%rbp), %rcx
callq 0x4820
movq %rax, -0x170(%rbp)
jmp 0x4196
movq -0x170(%rbp), %rax
movq %rax, -0xa0(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x7d90
jmp 0x41b6
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x190(%rbp)
callq 0x2860
movq -0x190(%rbp), %rdi
callq 0x4790
movq %rax, -0xe8(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x47c0
movq -0x148(%rbp), %rdi
addq $0x48, %rdi
movq %rdi, -0x198(%rbp)
callq 0x48d0
movq -0x198(%rbp), %rdi
movq %rax, -0xf0(%rbp)
callq 0x4900
movq -0x190(%rbp), %rdi
movq %rax, -0xf8(%rbp)
movq -0xe0(%rbp), %rsi
movq -0xf0(%rbp), %rdx
movq -0xf8(%rbp), %rcx
callq 0x4820
movq %rax, -0x188(%rbp)
jmp 0x424a
movq -0x188(%rbp), %rax
movq %rax, -0x100(%rbp)
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x1b0(%rbp)
callq 0x4790
movq %rax, -0x110(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x47c0
leaq -0xc0(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x4560
movq -0x1b8(%rbp), %rdi
movq %rax, -0x1a8(%rbp)
callq 0x4800
movq -0x1b0(%rbp), %rdi
movq -0x1a8(%rbp), %rdx
movq %rax, %rcx
movq -0x108(%rbp), %rsi
callq 0x46f0
movq %rax, -0x1a0(%rbp)
jmp 0x42d1
movq -0x148(%rbp), %rax
movq -0x1a0(%rbp), %rcx
movq %rcx, -0x118(%rbp)
movq 0x98(%rax), %rax
incq %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x7950
jmp 0x430c
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0x46b0
movq -0x1c8(%rbp), %rdi
movb %al, -0x121(%rbp)
callq 0x4b10
movq %rax, -0x138(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x47c0
movq -0x1c8(%rbp), %rdi
movq -0x130(%rbp), %rsi
leaq -0x121(%rbp), %rdx
callq 0x4930
movq %rax, -0x1c0(%rbp)
jmp 0x436e
movq -0x1c0(%rbp), %rax
movq %rax, -0x140(%rbp)
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0x4b40
movq -0x1e0(%rbp), %rdi
movq %rax, -0x1d8(%rbp)
callq 0x46b0
movq %rax, -0x1d0(%rbp)
movq -0x18(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2f00
movq -0x1d8(%rbp), %rdi
movq -0x1d0(%rbp), %rsi
movq %rax, %rdx
callq 0x7d30
jmp 0x43ce
movq -0x18(%rbp), %rdi
callq 0x2ef0
movq %rax, -0x1e8(%rbp)
leaq 0x50cf(%rip), %rdi      # 0x94b4
callq 0x2ef0
movq %rax, %rcx
movq -0x1e8(%rbp), %rax
cmpq %rcx, %rax
jne 0x44a0
movq -0x18(%rbp), %rdi
callq 0x2f30
movq %rax, -0x1f0(%rbp)
leaq 0x50a0(%rip), %rdi      # 0x94b4
callq 0x4b60
movq -0x1f0(%rbp), %rdi
movq %rax, %rsi
movl $0x20, %edx
callq 0x20d0
cmpl $0x0, %eax
jne 0x44a0
movq -0x18(%rbp), %rdi
callq 0x2f30
movq %rax, -0x1f8(%rbp)
leaq 0x508b(%rip), %rdi      # 0x94d4
callq 0x4b60
movq %rax, %rcx
movq -0x1f8(%rbp), %rax
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x10(%rcx), %rdx
movq %rdx, 0x10(%rax)
movq 0x18(%rcx), %rcx
movq %rcx, 0x18(%rax)
jmp 0x44a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x44be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x2930
jmp 0x44be
movl $0x0, -0x4(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x2930
leaq -0x50(%rbp), %rdi
callq 0x2930
jmp 0x44c9
leaq -0x50(%rbp), %rdi
callq 0x2930
jmp 0x44d5
movl -0x4(%rbp), %eax
addq $0x200, %rsp            # imm = 0x200
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0x22d0
nop