// File: contracts/adapters/Wormhole/IWormhole.sol



// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

struct Signature {
    bytes32 r;
    bytes32 s;
    uint8 v;
    uint8 guardianIndex;
}

struct VM {
    uint8 version;
    uint32 timestamp;
    uint32 nonce;
    uint16 emitterChainId;
    bytes32 emitterAddress;
    uint64 sequence;
    uint8 consistencyLevel;
    bytes payload;
    uint32 guardianSetIndex;
    Signature[] signatures;
    bytes32 hash;
}

interface IWormhole {
    /// @dev Publish a message to be attested by the Wormhole network.
    function publishMessage(
        uint32 nonce,
        bytes memory payload,
        uint8 consistencyLevel
    ) external payable returns (uint64 sequence);

    /// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption
    function parseAndVerifyVM(
        bytes calldata encodedVM
    ) external view returns (VM memory vm, bool valid, string memory reason);
}

// File: contracts/adapters/Wormhole/WormholeHeaderReporter.sol



// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

import { IHeaderStorage } from "../../interfaces/IHeaderStorage.sol";
import { IWormhole } from "./IWormhole.sol";

contract WormholeHeaderReporter {
    IWormhole public immutable wormhole;
    IHeaderStorage public immutable headerStorage;

    constructor(IWormhole wormhole_, IHeaderStorage headerStorage_) {
        wormhole = wormhole_;
        headerStorage = headerStorage_;
    }

    /// @dev Reports the given block header to the adapter via the Wormhole.
    /// @param blockNumbers Uint256 array of block numbers to pass over the Wormhole.
    /// @param sequence Uint64 value used to retrive generated VAA from the wormhole network.
    function reportHeaders(uint256[] calldata blockNumbers) external returns (uint64 sequence) {
        bytes32[] memory blockHeaders = new bytes32[](blockNumbers.length);
        for (uint256 i = 0; i < blockNumbers.length; i++) {
            blockHeaders[i] = headerStorage.storeBlockHeader(blockNumbers[i]);
        }
        bytes memory payload = abi.encode(blockNumbers, blockHeaders);
        uint32 nonce = 0;
        uint8 consistencyLevel = 201;
        sequence = wormhole.publishMessage(nonce, payload, consistencyLevel);
    }
}

// File: contracts/interfaces/IHeaderStorage.sol



// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

interface IHeaderStorage {
    event HeaderStored(uint256 indexed blockNumber, bytes32 indexed blockHeader);

    error HeaderOutOfRange(address emitter, uint256 blockNumber);

    function storeBlockHeader(uint256 blockNumber) external returns (bytes32 blockHeader);

    function storeBlockHeaders(uint256[] memory blockNumbers) external returns (bytes32[] memory);
}