// File: 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
subq $0x140, %rsp            # imm = 0x140
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0xe0(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x21e0
movl $0x0, -0x2c(%rbp)
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x344f
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x344f
movq 0x9ba5(%rip), %rdi      # 0xcfd0
leaq 0x5d8a(%rip), %rsi      # 0x91bc
callq 0x2160
movq %rax, %rdi
movq 0x9b7f(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xf0(%rbp)
leaq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0xf0(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x38(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x34cc
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x34cc
movq 0x9b28(%rip), %rdi      # 0xcfd0
leaq 0x5d29(%rip), %rsi      # 0x91d8
callq 0x2160
movq %rax, %rdi
movq 0x9b02(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0x50(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0xf8(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3549
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3549
movq 0x9aab(%rip), %rdi      # 0xcfd0
leaq 0x5cc8(%rip), %rsi      # 0x91f4
callq 0x2160
movq %rax, %rdi
movq 0x9a85(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x100(%rbp)
leaq -0x60(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x100(%rbp), %rdi
movq -0x60(%rbp), %rsi
movq -0x58(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x35c3
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x35c3
movq 0x9a31(%rip), %rdi      # 0xcfd0
leaq 0x5c6a(%rip), %rsi      # 0x9210
callq 0x2160
movq %rax, %rdi
movq 0x9a0b(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x108(%rbp)
leaq -0x70(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x108(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq -0x68(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3640
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3640
movq 0x99b4(%rip), %rdi      # 0xcfd0
leaq 0x5c09(%rip), %rsi      # 0x922c
callq 0x2160
movq %rax, %rdi
movq 0x998e(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x110(%rbp)
leaq -0x80(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x110(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x78(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x36bd
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x36bd
movq 0x9937(%rip), %rdi      # 0xcfd0
leaq 0x5ba8(%rip), %rsi      # 0x9248
callq 0x2160
movq %rax, %rdi
movq 0x9911(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0x90(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x118(%rbp), %rdi
movq -0x90(%rbp), %rsi
movq -0x88(%rbp), %rdx
callq 0x21e0
movq -0x18(%rbp), %rdi
movl $0x2, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3743
movq -0x18(%rbp), %rdi
movl $0x3, %esi
callq 0x78c0
cmpl $0x0, %eax
jne 0x3743
movq 0x98b1(%rip), %rdi      # 0xcfd0
leaq 0x5b3e(%rip), %rsi      # 0x9264
callq 0x2160
movq %rax, %rdi
movq 0x988b(%rip), %rsi      # 0xcfc0
callq 0x2190
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x1, -0x2c(%rbp)
je 0x3777
movq 0x98a0(%rip), %rdi      # 0xcff0
leaq 0x5b29(%rip), %rsi      # 0x9280
callq 0x2160
movq %rax, %rdi
movq 0x985a(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x39dc
movq -0x18(%rbp), %rax
movq %rax, -0x120(%rbp)
leaq -0xa0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x120(%rbp), %rdi
movq -0xa0(%rbp), %rsi
movq -0x98(%rbp), %rdx
callq 0x21e0
movl $0x0, -0xa4(%rbp)
cmpl $0x3, -0xa4(%rbp)
jge 0x380e
movq -0x18(%rbp), %rdi
callq 0x7b90
cmpl $0x0, %eax
jge 0x37fb
movq 0x981c(%rip), %rdi      # 0xcff0
leaq 0x5aa5(%rip), %rsi      # 0x9280
callq 0x2160
movq %rax, %rdi
movq 0x97d6(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x39dc
jmp 0x37fd
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x37b6
movq -0xe8(%rbp), %rdi
movq -0x18(%rbp), %rax
movq %rax, -0x130(%rbp)
addq $0x28, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2f00
movq -0xe8(%rbp), %rdi
movq %rax, -0x128(%rbp)
addq $0x28, %rdi
callq 0x2ef0
movq -0x130(%rbp), %rdi
movq -0x128(%rbp), %rsi
movq %rax, %rdx
callq 0x21d0
movq -0x18(%rbp), %rdi
movq (%rdi), %rax
addq -0x18(%rax), %rdi
callq 0x22a0
testb $0x1, %al
jne 0x389c
movq 0x977b(%rip), %rdi      # 0xcff0
leaq 0x5a22(%rip), %rsi      # 0x929e
callq 0x2160
movq %rax, %rdi
movq 0x9735(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x39dc
movq -0x18(%rbp), %rdi
movl $0x4, %esi
callq 0x7c80
cmpl $0x0, %eax
jge 0x38dd
movq 0x973a(%rip), %rdi      # 0xcff0
leaq 0x59c3(%rip), %rsi      # 0x9280
callq 0x2160
movq %rax, %rdi
movq 0x96f4(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x39dc
movq -0x18(%rbp), %rdi
callq 0x22c0
movq %rax, -0xc0(%rbp)
movq %rdx, -0xb8(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x45c0
movq -0xe8(%rbp), %rdi
movq %rax, -0xb0(%rbp)
addq $0x48, %rdi
movq -0xb0(%rbp), %rsi
movb $0x0, -0xc1(%rbp)
leaq -0xc1(%rbp), %rdx
callq 0x45e0
movq -0x18(%rbp), %rax
movq %rax, -0x140(%rbp)
leaq -0xd8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4580
movq -0x140(%rbp), %rdi
movq -0xd8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
callq 0x21e0
movq -0xe8(%rbp), %rdi
movq -0x18(%rbp), %rax
movq %rax, -0x138(%rbp)
addq $0x48, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4690
movq -0x138(%rbp), %rdi
movq %rax, %rsi
movq -0xb0(%rbp), %rdx
callq 0x21d0
movq -0x18(%rbp), %rdi
movq (%rdi), %rax
addq -0x18(%rax), %rdi
callq 0x22a0
testb $0x1, %al
jne 0x39d5
movq 0x963f(%rip), %rdi      # 0xcff0
leaq 0x58e6(%rip), %rsi      # 0x929e
callq 0x2160
movq %rax, %rdi
movq 0x95f9(%rip), %rsi      # 0xcfc0
callq 0x2190
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x39dc
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
nopl (%rax,%rax)