// File: /workspace/github_cpp_makefile_star2_O2/adamjanovsky[P]PA193_test_parser_monero/src/block.cpp
// Function: Block::load_header(std::basic_ifstream<char, std::char_traits<char>>&)
int Block::load_header(ifstream & in) {
    // To be sure, move to the beginning of the stream
    in.seekg(in.beg);
    
    // The first byte (major version) is 1 or 2
    int expected_res = 0;
    
    // If the first byte (major version) is 1, the second byte (minor version) should be 0, 1 or 2
    
    // Check if major.minor is 1.0
    if (tools::expect_byte_2(in, 0x01) == 0 and
        tools::expect_byte_2(in, 0x00) == 0){
        std::cout << "major.minor version is: 1.0" << std::endl;
        expected_res ++;
    }
    
    // Check if major.minor is 1.1
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x01) == 0 and
        tools::expect_byte_2(in, 0x01) == 0){
        std::cout << "major.minor version is: 1.1" << std::endl;
        expected_res ++;
    }

    // Check if major.minor is 1.2
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x01) == 0 and
        tools::expect_byte_2(in, 0x02) == 0){
        std::cout << "major.minor version is: 1.2" << std::endl;
        expected_res ++;
    }
    
    // If the first byte (major version) is 2, the second byte (minor version) should be 0, 1, 2 or 3
    // Check if major.minor is 2.0
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x02) == 0 and
        tools::expect_byte_2(in, 0x00) == 0){
        std::cout << "major.minor version is: 2.0" << std::endl;
        expected_res ++;
    }
    
    // Check if major.minor is 2.1
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x02) == 0 and
        tools::expect_byte_2(in, 0x01) == 0){
        std::cout << "major.minor version is: 2.1" << std::endl;
        expected_res ++;
    }

    // Check if major.minor is 2.2
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x02) == 0 and
        tools::expect_byte_2(in, 0x02) == 0){
        std::cout << "major.minor version is: 2.2" << std::endl;
        expected_res ++;
    }
    
    // Check if major.minor is 2.3
    in.seekg(in.beg);
    if (tools::expect_byte_2(in, 0x02) == 0 and
        tools::expect_byte_2(in, 0x03) == 0){
        std::cout << "major.minor version is: 2.3" << std::endl;
        expected_res ++;
    }
    
    // If none of them holds, then the block header has an invalid format
    if(expected_res != 1){
        std::cerr << "Block header: Invalid format." << std::endl;
        return ERR_BL_LOADHDR_INVALID_FORMAT;
    }
    
    // Skip the first three bytes
    in.seekg(in.beg);
    for (int i = 0; i < 3; i++) {
        if (tools::skip_varint(in) < 0) {
            std::cerr << "Block header: Invalid format." << std::endl;
            return ERR_BL_LOADHDR_INVALID_FORMAT;
        }
    }
    
    // Alloc and load the hash
    in.read(reinterpret_cast<char *>(&prev_id[0]), prev_id.size());
    if (!in.good()) {
        std::cerr << "Block header: Unexpected end of file." << std::endl;
        return ERR_BL_LOADHDR_EOF;
    }

    // Skip the nonce at the end of the header
    if (tools::skip_bytes(in, 4) < 0) {
        std::cerr << "Block header: Invalid format." << std::endl;
        return ERR_BL_LOADHDR_INVALID_FORMAT;
    }

    // Get the header length
    long long block_header_length = in.tellg();

    // Alloc space for the header
    block_header.resize(block_header_length, 0x00);

    // Read the whole header
    in.seekg(in.beg);
    in.read(reinterpret_cast<char *>(&block_header[0]), block_header_length);

    // To be sure, check once more if we have loaded the header sucessfully
    if (!in.good()) {
        std::cerr << "Block header: Unexpected end of file." << std::endl;
        return ERR_BL_LOADHDR_EOF;
    }

    return OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rsi, %rbx
movq %rdi, %r14
xorl %r12d, %r12d
movq %rsi, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x1
popq %r15
movq %rbx, %rdi
movl %r15d, %esi
callq 0x3a1c
testl %eax, %eax
jne 0x2a7c
xorl %r12d, %r12d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x3a1c
testl %eax, %eax
jne 0x2a7c
movq 0x556b(%rip), %rdi      # 0x7fd0
leaq 0x274e(%rip), %rsi      # 0x51ba
callq 0x2120
movq %rax, %rdi
callq 0x20a0
movl %r15d, %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2ac4
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2ac4
movq 0x5523(%rip), %rdi      # 0x7fd0
leaq 0x2722(%rip), %rsi      # 0x51d6
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2b0c
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2b0c
movq 0x54db(%rip), %rdi      # 0x7fd0
leaq 0x26f6(%rip), %rsi      # 0x51f2
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2b53
movq %rbx, %rdi
xorl %esi, %esi
callq 0x3a1c
testl %eax, %eax
jne 0x2b53
movq 0x5494(%rip), %rdi      # 0x7fd0
leaq 0x26cb(%rip), %rsi      # 0x520e
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2b9b
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2b9b
movq 0x544c(%rip), %rdi      # 0x7fd0
leaq 0x269f(%rip), %rsi      # 0x522a
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2be3
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2be3
movq 0x5404(%rip), %rdi      # 0x7fd0
leaq 0x2673(%rip), %rsi      # 0x5246
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2c2b
pushq $0x3
popq %rsi
movq %rbx, %rdi
callq 0x3a1c
testl %eax, %eax
jne 0x2c2b
movq 0x53bc(%rip), %rdi      # 0x7fd0
leaq 0x2647(%rip), %rsi      # 0x5262
callq 0x2120
movq %rax, %rdi
callq 0x20a0
incl %r12d
cmpl $0x1, %r12d
jne 0x2c52
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
pushq $0x4
popq %r15
decl %r15d
je 0x2c71
movq %rbx, %rdi
callq 0x3c02
testl %eax, %eax
jns 0x2c41
movq 0x5397(%rip), %rdi      # 0x7ff0
leaq 0x261e(%rip), %rsi      # 0x527e
callq 0x2120
movq %rax, %rdi
callq 0x20a0
pushq $-0x1
jmp 0x2cab
leaq 0x28(%r14), %rsi
pushq $0x20
popq %rdx
movq %rbx, %rdi
callq 0x2190
movq (%rbx), %rax
movq -0x18(%rax), %rax
cmpl $0x0, 0x20(%rbx,%rax)
je 0x2cbd
movq 0x535b(%rip), %rdi      # 0x7ff0
leaq 0x2600(%rip), %rsi      # 0x529c
callq 0x2120
movq %rax, %rdi
callq 0x20a0
pushq $-0x3
popq %r15
movl %r15d, %eax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
pushq $0x4
popq %rsi
movq %rbx, %rdi
callq 0x3c9f
testl %eax, %eax
js 0x2c52
movq %rbx, %rdi
callq 0x2230
movq %rax, %r12
leaq 0x48(%r14), %rdi
leaq -0x21(%rbp), %rdx
movb $0x0, (%rdx)
movq %rax, %rsi
callq 0x31dc
xorl %r15d, %r15d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21a0
movq 0x48(%r14), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x2190
movq (%rbx), %rax
movq -0x18(%rax), %rax
cmpl $0x0, 0x20(%rbx,%rax)
jne 0x2c8e
jmp 0x2cad