// File: /workspace/github_cpp_makefile_star2_O3/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 0x2190
movq %rbx, %rdi
movl $0x1, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2d94
xorl %r12d, %r12d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2d94
movq 0x527d(%rip), %r15      # 0x7fd0
leaq 0x24ab(%rip), %rsi      # 0x5205
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
movl $0x1, %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x1, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2e07
movq %rbx, %rdi
movl $0x1, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2e07
movq 0x5207(%rip), %r15      # 0x7fd0
leaq 0x2451(%rip), %rsi      # 0x5221
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x1, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2e7a
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2e7a
movq 0x5194(%rip), %r15      # 0x7fd0
leaq 0x23fa(%rip), %rsi      # 0x523d
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2eea
movq %rbx, %rdi
xorl %esi, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2eea
movq 0x5124(%rip), %r15      # 0x7fd0
leaq 0x23a6(%rip), %rsi      # 0x5259
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2f5d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2f5d
movq 0x50b1(%rip), %r15      # 0x7fd0
leaq 0x234f(%rip), %rsi      # 0x5275
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2fd0
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x2fd0
movq 0x503e(%rip), %r15      # 0x7fd0
leaq 0x22f8(%rip), %rsi      # 0x5291
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq %rbx, %rdi
movl $0x2, %esi
callq 0x40c1
testl %eax, %eax
jne 0x3043
movq %rbx, %rdi
movl $0x3, %esi
callq 0x40c1
testl %eax, %eax
jne 0x3043
movq 0x4fcb(%rip), %r15      # 0x7fd0
leaq 0x22a1(%rip), %rsi      # 0x52ad
movl $0x1b, %edx
movq %r15, %rdi
callq 0x2160
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2120
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20d0
incl %r12d
cmpl $0x1, %r12d
jne 0x3141
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movl $0x3, %r15d
movq %rbx, %rdi
callq 0x43ac
testl %eax, %eax
js 0x3141
decl %r15d
jne 0x305f
leaq 0x28(%r14), %rsi
movl $0x20, %edx
movq %rbx, %rdi
callq 0x2180
movq (%rbx), %rax
movq -0x18(%rax), %rax
cmpl $0x0, 0x20(%rbx,%rax)
je 0x30e0
movq 0x4f56(%rip), %rbx      # 0x7ff0
leaq 0x2246(%rip), %rsi      # 0x52e7
movl $0x25, %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, %r15d      # imm = 0xFFFFFFFD
jmp 0x3189
movq %rbx, %rdi
movl $0x4, %esi
callq 0x4487
testl %eax, %eax
js 0x3141
movq %rbx, %rdi
callq 0x2210
movq %rax, %r12
leaq 0x48(%r14), %rdi
leaq -0x21(%rbp), %rdx
movb $0x0, (%rdx)
movq %rax, %rsi
callq 0x37be
xorl %r15d, %r15d
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2190
movq 0x48(%r14), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x2180
movq (%rbx), %rax
movq -0x18(%rax), %rax
cmpl $0x0, 0x20(%rbx,%rax)
jne 0x3093
jmp 0x3189
movq 0x4ea8(%rip), %rbx      # 0x7ff0
leaq 0x217a(%rip), %rsi      # 0x52c9
movl $0x1d, %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 $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %r15d, %eax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
nop