function purchaseTokens(
        bytes32 _r,
        bytes32 _s,
        uint8 _v,
        uint256 _blockNum,
        uint256 _etherPrice
    )
        public
        payable
        onlyDuring(Status.started)
        onlyWithValidCode( _r, _s, _v, _blockNum, _etherPrice)
    {
        if (_isPurchaseValid(msg.sender, msg.value)) {
            uint256 _etherAmount = msg.value;
            uint256 _tokenAmount = _etherAmount.getTokenAmount(
                _etherPrice,
                startTime,
                baseRate
            );
            emit TokenPurchase(msg.sender, _etherAmount, _etherPrice, _tokenAmount);
            
            _registerPurchase(msg.sender, _tokenAmount);
        }
    }