all files / contracts/ TestnetRelay.sol

0% Statements 0/22
0% Branches 0/10
0% Functions 0/4
0% Lines 0/20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96                                                                                                                                                                                               
pragma solidity ^0.5.10;
 
/** @title TestnetRelay */
/** @author Summa (https://summa.one) */
 
import {OnDemandSPV} from "./OnDemandSPV.sol";
 
contract TestnetRelay is OnDemandSPV {
 
    constructor(
        bytes memory _genesisHeader,
        uint256 _height,
        bytes32 _periodStart,
        uint256 _firstID
    ) OnDemandSPV(
        _genesisHeader,
        _height,
        _periodStart,
        _firstID
    ) public {return ;}
 
    function _addHeadersWithRetarget(
        bytes memory, // _oldPeriodStartHeader,
        bytes memory _oldPeriodEndHeader,
        bytes memory _headers
    ) internal returns (bool) {
        return _addHeaders(_oldPeriodEndHeader, _headers);
    }
 
    function _addHeaders(bytes memory _anchor, bytes memory _headers, bool) internal returns (bool) {
        return _addHeaders(_anchor, _headers);
    }
 
    /// @notice             Adds headers to storage after validating
    /// @dev                We check integrity and consistency of the header chain
    /// @param  _anchor     The header immediately preceeding the new chain
    /// @param  _headers    A tightly-packed list of new 80-byte Bitcoin headers to record
    /// @return             True if successfully written, error otherwise
    function _addHeaders(bytes memory _anchor, bytes memory _headers) internal returns (bool) {
        uint256 _height;
        bytes memory _header;
        bytes32 _currentDigest;
        bytes32 _previousDigest = _anchor.hash256();
 
        /* uint256 _target = _headers.slice(0, 80).extractTarget(); */
        uint256 _anchorHeight = _findHeight(_previousDigest);  /* NB: errors if unknown */
 
        /* require(
            _internal || _anchor.extractTarget() == _target,
            "Unexpected retarget on external call"); */
        require(_headers.length % 80 == 0, "Header array length must be divisible by 80");
 
        /*
        NB:
        1. check that the header has sufficient work
        2. check that headers are in a coherent chain (no retargets, hash links good)
        3. Store the block connection
        4. Store the height
        */
        for (uint256 i = 0; i < _headers.length / 80; i = i.add(1)) {
            _header = _headers.slice(i.mul(80), 80);
            _height = _anchorHeight.add(i + 1);
            _currentDigest = _header.hash256();
 
            /*
            NB:
            if the block is already authenticated, we don't need to a work check
            Or write anything to state. This saves gas
            */
            if (previousBlock[_currentDigest] == bytes32(0)) {
                require(
                    abi.encodePacked(_currentDigest).reverseEndianness().bytesToUint() <= _header.extractTarget(),
                    "Header work is insufficient");
                previousBlock[_currentDigest] = _previousDigest;
                if (_height % HEIGHT_INTERVAL == 0) {
                    /*
                    NB: We store the height only every 4th header to save gas
                    */
                    blockHeight[_currentDigest] = _height;
                }
            }
 
            /* NB: we do still need to make chain level checks tho */
            /* require(_header.extractTarget() == _target, "Target changed unexpectedly"); */
            require(_header.validateHeaderPrevHash(_previousDigest), "Headers do not form a consistent chain");
 
            _previousDigest = _currentDigest;
        }
 
        emit Extension(
            _anchor.hash256(),
            _currentDigest);
        return true;
    }
}