<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "pow.h"
#include "chain.h"
#include "primitives/block.h"
#include "util.h"

/// Used in tests
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
    if (nActualTimespan < params.nTargetTimespan_Version1/4)
        nActualTimespan = params.nTargetTimespan_Version1/4;
    if (nActualTimespan > params.nTargetTimespan_Version1*4)
        nActualTimespan = params.nTargetTimespan_Version1*4;

    // Retarget
    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
    arith_uint256 bnNew;
    arith_uint256 bnOld;
    bnNew.SetCompact(pindexLast->nBits);
    bnOld = bnNew;
    // Solarcoin: intermediate uint256 can overflow by 1 bit
    bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
    if (fShift)
        bnNew >>= 1;
    bnNew *= nActualTimespan;
    bnNew /= params.nTargetTimespan_Version1;
    if (fShift)
        bnNew <<= 1;

    if (bnNew > bnPowLimit)
        bnNew = bnPowLimit;

    return bnNew.GetCompact();
}

// PoST Target adjustment
/* TODO: Convert this code
static unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params)
{
    arith_uint256 bnTargetLimit = UintToArith256(params.posLimit);

    if (pindexLast == nullptr)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == nullptr)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == nullptr)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
    if (nActualSpacing < 0)
        nActualSpacing = nTargetSpacing;

    // ppcoin: target change every block
    // ppcoin: retarget with exponential moving toward target spacing
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);
    int64_t nInterval = nTargetTimespan / nTargetSpacing;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}
*/

unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast, uint64_t TargetBlocksSpacingSeconds, uint64_t PastBlocksMin, uint64_t PastBlocksMax, const Consensus::Params& params) {

    arith_uint256 bnProofOfWorkLimit = UintToArith256(params.powLimit);
    arith_uint256 bnStartDiff        = (bnProofOfWorkLimit >> 6);

    if (pindexLast->nHeight+1 == 160 && !fTestNet) {
        LogPrintf("DEBUG: Height 160: %08x %s\n", bnStartDiff.GetCompact(), ArithToUint256(bnStartDiff).ToString().c_str());
        return bnStartDiff.GetCompact();
    }

    const CBlockIndex *BlockLastSolved  = pindexLast;
    const CBlockIndex *BlockReading = pindexLast;
    uint64_t  PastBlocksMass  = 0;
    int64_t   PastRateActualSeconds   = 0;
    int64_t   PastRateTargetSeconds   = 0;
    double  PastRateAdjustmentRatio = double(1);
    arith_uint256 PastDifficultyAverage;
    arith_uint256 PastDifficultyAveragePrev;
    double  EventHorizonDeviation;
    double  EventHorizonDeviationFast;
    double  EventHorizonDeviationSlow;

    if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) {
        return bnProofOfWorkLimit.GetCompact();
    }

    int64_t LatestBlockTime = BlockLastSolved->GetBlockTime();

    for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
        if (PastBlocksMax > 0 && i > PastBlocksMax) {
            break;
        }
        PastBlocksMass++;

        if (i == 1) {
            PastDifficultyAverage.SetCompact(BlockReading->nBits);
        } else {
            PastDifficultyAverage = ((arith_uint256().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
        }

        PastDifficultyAveragePrev = PastDifficultyAverage;
        PastRateActualSeconds   = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();

        if (LatestBlockTime < BlockReading->GetBlockTime()) {
            if (BlockReading->nHeight > 16000) { // HARD Fork block number
                LatestBlockTime = BlockReading->GetBlockTime();
            }
        }
        PastRateActualSeconds   = LatestBlockTime - BlockReading->GetBlockTime();
        PastRateTargetSeconds   = TargetBlocksSpacingSeconds * PastBlocksMass;
        PastRateAdjustmentRatio = double(1);

        if (PastRateActualSeconds < 0) {
            PastRateActualSeconds = 0;
        }
        if (BlockReading->nHeight > 16000) { // HARD Fork block number
            if (PastRateActualSeconds < 1) {
                PastRateActualSeconds = 1;
            }
        } else {
            if (PastRateActualSeconds < 0) {
                PastRateActualSeconds = 0;
            }
        }
        if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
            PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
        }
        EventHorizonDeviation   = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
        EventHorizonDeviationFast   = EventHorizonDeviation;
        EventHorizonDeviationSlow   = 1 / EventHorizonDeviation;

        if (PastBlocksMass >= PastBlocksMin) {
            if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) {
                assert(BlockReading);
                break;
            }
        }
        if (BlockReading->pprev == NULL) {
            assert(BlockReading);
            break;
        }
        BlockReading = BlockReading->pprev;
    }

    arith_uint256 bnNew(PastDifficultyAverage);
    LogPrintf("DEBUG: bnNew(PastDifficultyAverage): %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());
    if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
        bnNew *= PastRateActualSeconds;
        LogPrintf("DEBUG: bnNew *= PastRateActualSeconds: %08x PastRateActualSeconds: %lu\n", bnNew.GetCompact(), PastRateActualSeconds);
        bnNew /= PastRateTargetSeconds;
        LogPrintf("DEBUG: bnNew /= PastRateTargetSeconds: %08x PastRateTargetSeconds: %lu\n", bnNew.GetCompact(), PastRateTargetSeconds);
    }
    // TODO: bnNew should NOT be greater than bnPoWLimit
    if (bnNew > bnProofOfWorkLimit) {
        LogPrintf("DEBUG: %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());
        bnNew = bnProofOfWorkLimit;
        LogPrintf("DEBUG: bnNew set to bnProofOfWorkLimit.\n");
    }

    /// debug print
    LogPrintf("Difficulty Retarget - Gravity Well\n");
    LogPrintf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio);
    LogPrintf("Before: %08x %s\n", BlockLastSolved->nBits, ArithToUint256(arith_uint256().SetCompact(BlockLastSolved->nBits)).ToString().c_str());
    LogPrintf("After: %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());

    return bnNew.GetCompact();
}

unsigned int static GetNextWorkRequired_V1(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
    bool fTestNet = false; // TODO: params.fTestNet;

    // Genesis block
    if (pindexLast == nullptr)
        return nProofOfWorkLimit;

    unsigned int nInterval;
    unsigned int nTargetTimespan;

    if (pindexLast->nHeight+1 < params.nHeight_Version2)
    {
        nInterval = params.DifficultyAdjustmentInterval_V1();
        nTargetTimespan = params.nTargetTimespan_Version1;
    }
    else
    {
        nInterval = params.DifficultyAdjustmentInterval_V2();
        nTargetTimespan = params.nTargetTimespan_Version2;
    }

    // Only change once per interval
    if ((pindexLast->nHeight+1) % nInterval != 0)
    {
        // Special difficulty rule for testnet:
        if (fTestNet)
        {
            // If the new block's timestamp is more than 2* 10 minutes
            // then allow mining of a min-difficulty block.
            if (pblock->nTime > pindexLast->nTime + params.nTargetSpacing * 2)
                return nProofOfWorkLimit;
            else
            {
                // Return the last non-special-min-difficulty-rules-block
                const CBlockIndex* pindex = pindexLast;
                while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit)
                    pindex = pindex->pprev;
                return pindex->nBits;
            }
        }

        LogPrintf("DEBUG: nTargetTimespan = %lu    nInterval = %ld\n", nTargetTimespan, nInterval);
        return pindexLast->nBits;
    }

    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
    int blockstogoback = nInterval-1;
    if ((pindexLast->nHeight+1) != nInterval)
        blockstogoback = nInterval;

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < blockstogoback; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
    LogPrintf("  nActualTimespan = %ld  before bounds\n", nActualTimespan);
    if (nActualTimespan < nTargetTimespan/4)
        nActualTimespan = nTargetTimespan/4;
    if (nActualTimespan > nTargetTimespan*4)
        nActualTimespan = nTargetTimespan*4;

    // Retarget
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast->nBits);
    bnNew *= nActualTimespan;
    bnNew /= nTargetTimespan;

    arith_uint256 bnProofOfWorkLimit = arith_uint256().SetCompact(nProofOfWorkLimit);

    if (bnNew > bnProofOfWorkLimit)
        bnNew = bnProofOfWorkLimit;

    /// debug print
    LogPrintf("GetNextWorkRequired RETARGET\n");
    LogPrintf("nTargetTimespan = %ld    nActualTimespan = %ld\n", nTargetTimespan, nActualTimespan);
    LogPrintf("Before: %08x  %s\n", pindexLast->nBits, ArithToUint256(arith_uint256().SetCompact(pindexLast->nBits)).ToString().c_str());
    LogPrintf("After:  %08x  %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());

    return bnNew.GetCompact();
}

unsigned int static GetNextWorkRequired_V2(const CBlockIndex* pindexLast, const Consensus::Params& params)
{
    // Kimoto Gravity Well (Patched for Time-warp exploit 4/5/14)
    static const int64_t  BlocksTargetSpacing = 60; // 1 minute
    unsigned int TimeDaySeconds  = 60 * 60 * 24;
    int64_t   PastSecondsMin  = TimeDaySeconds * 0.1;
    int64_t   PastSecondsMax  = TimeDaySeconds * 2.8;
    uint64_t  PastBlocksMin   = PastSecondsMin / BlocksTargetSpacing;
    uint64_t  PastBlocksMax   = PastSecondsMax / BlocksTargetSpacing;

    if (fTestNet && gArgs.GetBoolArg("-zerogravity", false))
        return UintToArith256(params.powLimit).GetCompact();
    else
        return KimotoGravityWell(pindexLast, BlocksTargetSpacing, PastBlocksMin, PastBlocksMax, params);
}

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    int DiffMode = (pindexLast->nHeight+1 >= 310000 ? 2 : 1);

    LogPrintf("DEBUG: DiffMode = %d\n", DiffMode);
    if (DiffMode == 1) {
        return GetNextWorkRequired_V1(pindexLast, pblock, params); // nHeight_Version2 = 208440 (less than 310000)
    } else {
        return GetNextWorkRequired_V2(pindexLast, params);
    }
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
    bool fNegative;
    bool fOverflow;
    arith_uint256 bnTarget;

    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);

    // DEBUG
    LogPrintf("DEBUG: CheckProofOfWork: nBits=%08x bnTarget=%s\n", nBits, bnTarget.ToString().c_str());

        // Check range
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
        return false;

    // Check proof of work matches claimed amount
    if (UintToArith256(hash) > bnTarget)
        return false;

    return true;
}
<commit_msg>debugs<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "pow.h"
#include "chain.h"
#include "primitives/block.h"
#include "util.h"

/// Used in tests
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
    if (nActualTimespan < params.nTargetTimespan_Version1/4)
        nActualTimespan = params.nTargetTimespan_Version1/4;
    if (nActualTimespan > params.nTargetTimespan_Version1*4)
        nActualTimespan = params.nTargetTimespan_Version1*4;

    // Retarget
    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
    arith_uint256 bnNew;
    arith_uint256 bnOld;
    bnNew.SetCompact(pindexLast->nBits);
    bnOld = bnNew;
    // Solarcoin: intermediate uint256 can overflow by 1 bit
    bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
    if (fShift)
        bnNew >>= 1;
    bnNew *= nActualTimespan;
    bnNew /= params.nTargetTimespan_Version1;
    if (fShift)
        bnNew <<= 1;

    if (bnNew > bnPowLimit)
        bnNew = bnPowLimit;

    return bnNew.GetCompact();
}

// PoST Target adjustment
/* TODO: Convert this code
static unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params)
{
    arith_uint256 bnTargetLimit = UintToArith256(params.posLimit);

    if (pindexLast == nullptr)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == nullptr)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == nullptr)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
    if (nActualSpacing < 0)
        nActualSpacing = nTargetSpacing;

    // ppcoin: target change every block
    // ppcoin: retarget with exponential moving toward target spacing
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);
    int64_t nInterval = nTargetTimespan / nTargetSpacing;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}
*/

unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast, uint64_t TargetBlocksSpacingSeconds, uint64_t PastBlocksMin, uint64_t PastBlocksMax, const Consensus::Params& params) {

    arith_uint256 bnProofOfWorkLimit = UintToArith256(params.powLimit);
    arith_uint256 bnStartDiff        = (bnProofOfWorkLimit >> 6);

    if (pindexLast->nHeight+1 == 160 && !fTestNet) {
        LogPrintf("DEBUG: Height 160: %08x %s\n", bnStartDiff.GetCompact(), ArithToUint256(bnStartDiff).ToString().c_str());
        return bnStartDiff.GetCompact();
    }

    const CBlockIndex *BlockLastSolved  = pindexLast;
    const CBlockIndex *BlockReading = pindexLast;
    uint64_t  PastBlocksMass  = 0;
    int64_t   PastRateActualSeconds   = 0;
    int64_t   PastRateTargetSeconds   = 0;
    double  PastRateAdjustmentRatio = double(1);
    arith_uint256 PastDifficultyAverage;
    arith_uint256 PastDifficultyAveragePrev;
    double  EventHorizonDeviation;
    double  EventHorizonDeviationFast;
    double  EventHorizonDeviationSlow;

    if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) {
        return bnProofOfWorkLimit.GetCompact();
    }

    int64_t LatestBlockTime = BlockLastSolved->GetBlockTime();

    for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
        if (PastBlocksMax > 0 && i > PastBlocksMax) {
            break;
        }
        PastBlocksMass++;

        if (i == 1) {
            PastDifficultyAverage.SetCompact(BlockReading->nBits);
        } else {
            PastDifficultyAverage = ((arith_uint256().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
        }

        PastDifficultyAveragePrev = PastDifficultyAverage;
        PastRateActualSeconds   = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();

        if (LatestBlockTime < BlockReading->GetBlockTime()) {
            if (BlockReading->nHeight > 16000) { // HARD Fork block number
                LatestBlockTime = BlockReading->GetBlockTime();
            }
        }
        PastRateActualSeconds   = LatestBlockTime - BlockReading->GetBlockTime();
        PastRateTargetSeconds   = TargetBlocksSpacingSeconds * PastBlocksMass;
        PastRateAdjustmentRatio = double(1);

        if (PastRateActualSeconds < 0) {
            PastRateActualSeconds = 0;
        }
        if (BlockReading->nHeight > 16000) { // HARD Fork block number
            if (PastRateActualSeconds < 1) {
                PastRateActualSeconds = 1;
            }
        } else {
            if (PastRateActualSeconds < 0) {
                PastRateActualSeconds = 0;
            }
        }
        if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
            PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
        }
        EventHorizonDeviation   = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
        EventHorizonDeviationFast   = EventHorizonDeviation;
        EventHorizonDeviationSlow   = 1 / EventHorizonDeviation;

        if (PastBlocksMass >= PastBlocksMin) {
            if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) {
                assert(BlockReading);
                break;
            }
        }
        if (BlockReading->pprev == NULL) {
            assert(BlockReading);
            break;
        }
        BlockReading = BlockReading->pprev;
        // DEBUG:
        printf("i=%d ", i);
    }
    // DEBUG:
    printf("\n");

    arith_uint256 bnNew(PastDifficultyAverage);
    LogPrintf("DEBUG: bnNew(PastDifficultyAverage): %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());
    if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
        bnNew *= PastRateActualSeconds;
        LogPrintf("DEBUG: bnNew *= PastRateActualSeconds: %08x PastRateActualSeconds: %lu\n", bnNew.GetCompact(), PastRateActualSeconds);
        bnNew /= PastRateTargetSeconds;
        LogPrintf("DEBUG: bnNew /= PastRateTargetSeconds: %08x PastRateTargetSeconds: %lu\n", bnNew.GetCompact(), PastRateTargetSeconds);
    }
    // TODO: bnNew should NOT be greater than bnPoWLimit
    if (bnNew > bnProofOfWorkLimit) {
        LogPrintf("DEBUG: %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());
        bnNew = bnProofOfWorkLimit;
        LogPrintf("DEBUG: bnNew set to bnProofOfWorkLimit.\n");
    }

    /// debug print
    LogPrintf("Difficulty Retarget - Gravity Well\n");
    LogPrintf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio);
    LogPrintf("Before: %08x %s\n", BlockLastSolved->nBits, ArithToUint256(arith_uint256().SetCompact(BlockLastSolved->nBits)).ToString().c_str());
    LogPrintf("After: %08x %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());

    return bnNew.GetCompact();
}

unsigned int static GetNextWorkRequired_V1(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
    bool fTestNet = false; // TODO: params.fTestNet;

    // Genesis block
    if (pindexLast == nullptr)
        return nProofOfWorkLimit;

    unsigned int nInterval;
    unsigned int nTargetTimespan;

    if (pindexLast->nHeight+1 < params.nHeight_Version2)
    {
        nInterval = params.DifficultyAdjustmentInterval_V1();
        nTargetTimespan = params.nTargetTimespan_Version1;
    }
    else
    {
        nInterval = params.DifficultyAdjustmentInterval_V2();
        nTargetTimespan = params.nTargetTimespan_Version2;
    }

    // Only change once per interval
    if ((pindexLast->nHeight+1) % nInterval != 0)
    {
        // Special difficulty rule for testnet:
        if (fTestNet)
        {
            // If the new block's timestamp is more than 2* 10 minutes
            // then allow mining of a min-difficulty block.
            if (pblock->nTime > pindexLast->nTime + params.nTargetSpacing * 2)
                return nProofOfWorkLimit;
            else
            {
                // Return the last non-special-min-difficulty-rules-block
                const CBlockIndex* pindex = pindexLast;
                while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit)
                    pindex = pindex->pprev;
                return pindex->nBits;
            }
        }

        LogPrintf("DEBUG: nTargetTimespan = %lu    nInterval = %ld\n", nTargetTimespan, nInterval);
        return pindexLast->nBits;
    }

    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
    int blockstogoback = nInterval-1;
    if ((pindexLast->nHeight+1) != nInterval)
        blockstogoback = nInterval;

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < blockstogoback; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
    LogPrintf("  nActualTimespan = %ld  before bounds\n", nActualTimespan);
    if (nActualTimespan < nTargetTimespan/4)
        nActualTimespan = nTargetTimespan/4;
    if (nActualTimespan > nTargetTimespan*4)
        nActualTimespan = nTargetTimespan*4;

    // Retarget
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast->nBits);
    bnNew *= nActualTimespan;
    bnNew /= nTargetTimespan;

    arith_uint256 bnProofOfWorkLimit = arith_uint256().SetCompact(nProofOfWorkLimit);

    if (bnNew > bnProofOfWorkLimit)
        bnNew = bnProofOfWorkLimit;

    /// debug print
    LogPrintf("GetNextWorkRequired RETARGET\n");
    LogPrintf("nTargetTimespan = %ld    nActualTimespan = %ld\n", nTargetTimespan, nActualTimespan);
    LogPrintf("Before: %08x  %s\n", pindexLast->nBits, ArithToUint256(arith_uint256().SetCompact(pindexLast->nBits)).ToString().c_str());
    LogPrintf("After:  %08x  %s\n", bnNew.GetCompact(), ArithToUint256(bnNew).ToString().c_str());

    return bnNew.GetCompact();
}

unsigned int static GetNextWorkRequired_V2(const CBlockIndex* pindexLast, const Consensus::Params& params)
{
    // Kimoto Gravity Well (Patched for Time-warp exploit 4/5/14)
    static const int64_t  BlocksTargetSpacing = 60; // 1 minute
    unsigned int TimeDaySeconds  = 60 * 60 * 24;
    int64_t   PastSecondsMin  = TimeDaySeconds * 0.1;
    int64_t   PastSecondsMax  = TimeDaySeconds * 2.8;
    uint64_t  PastBlocksMin   = PastSecondsMin / BlocksTargetSpacing;
    uint64_t  PastBlocksMax   = PastSecondsMax / BlocksTargetSpacing;

    if (fTestNet && gArgs.GetBoolArg("-zerogravity", false))
        return UintToArith256(params.powLimit).GetCompact();
    else
        return KimotoGravityWell(pindexLast, BlocksTargetSpacing, PastBlocksMin, PastBlocksMax, params);
}

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    int DiffMode = (pindexLast->nHeight+1 >= 310000 ? 2 : 1);

    LogPrintf("DEBUG: DiffMode = %d\n", DiffMode);
    if (DiffMode == 1) {
        return GetNextWorkRequired_V1(pindexLast, pblock, params); // nHeight_Version2 = 208440 (less than 310000)
    } else {
        return GetNextWorkRequired_V2(pindexLast, params);
    }
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
    bool fNegative;
    bool fOverflow;
    arith_uint256 bnTarget;

    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);

    // DEBUG
    LogPrintf("DEBUG: CheckProofOfWork: nBits=%08x bnTarget=%s\n", nBits, bnTarget.ToString().c_str());

        // Check range
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
        return false;

    // Check proof of work matches claimed amount
    if (UintToArith256(hash) > bnTarget)
        return false;

    return true;
}
<|endoftext|>


<commit_before>#include "ppr.hxx"
#include <list>

namespace miniml
{

Ptr<String> Ppr::string() const
{
  SStream stream;
  stream << *this;
  return ptr<String>(stream.str());
}

void PprString::output(OStream &out, unsigned indent) const
{
  out << String(indent, ' ') << m_val;
}

void PprIndent::output(OStream &out, unsigned indent) const
{
  m_child->output(out, indent + m_indent);
}

void PprHCat::output(OStream &out, unsigned indent) const
{
  out << String(indent, ' ');
  for (auto child: *m_children) {
    child->output(out, 0);
  }
}

void PprVCat::output(OStream &out, unsigned indent) const
{
  bool first = true;
  for (auto child: *m_children) {
    if (first) {
      first = false;
    } else {
      out << std::endl;
    }
    child->output(out, indent);
  }
}

namespace
{
  template <typename T>
  Ptr<T> cat(Ptr<Ppr> a, Ptr<Ppr> b)
  {
    return std::shared_ptr<T>(new T {a, b});
  }
}

namespace ppr
{
  Ptr<Ppr> string(const String &str)
  {
    return ptr<PprString>(str);
  }

  Ptr<Ppr> string(const Char *str)
  {
    return ptr<PprString>(String(str));
  }

  Ptr<Ppr> indent(Ptr<Ppr> ppr, unsigned ind)
  {
    return ptr<PprIndent>(ppr, ind);
  }

  Ptr<Ppr> parens_if(bool b, const Ptr<Ppr> ppr)
  {
    if (b)
      return hcat({'('_p, ppr, ')'_p});
    else
      return ppr;
  }

  Ptr<Ppr> vcat(std::initializer_list<Ptr<Ppr>> pprs)
  {
    return ptr<PprVCat>(pprs);
  }

  Ptr<Ppr> hcat(std::initializer_list<Ptr<Ppr>> pprs)
  {
    return ptr<PprHCat>(pprs);
  }
}

Ptr<Ppr> operator>>(Ptr<Ppr> ppr, unsigned ind)
{
  return ppr::indent(ppr, ind * Ppr::default_indent);
}

Ptr<Ppr> operator""_p(const Char *str, size_t len)
{
  return ptr<PprString>(String(str));
}

Ptr<Ppr> operator""_p(Char c)
{
  return ptr<PprString>(String(1, c));
}

Ptr<Ppr> operator+(Ptr<Ppr> p)
{
  return ppr::hcat({' '_p, p});
}

}
<commit_msg>Fix operator""_p<commit_after>#include "ppr.hxx"
#include <list>

namespace miniml
{

Ptr<String> Ppr::string() const
{
  SStream stream;
  stream << *this;
  return ptr<String>(stream.str());
}

void PprString::output(OStream &out, unsigned indent) const
{
  out << String(indent, ' ') << m_val;
}

void PprIndent::output(OStream &out, unsigned indent) const
{
  m_child->output(out, indent + m_indent);
}

void PprHCat::output(OStream &out, unsigned indent) const
{
  out << String(indent, ' ');
  for (auto child: *m_children) {
    child->output(out, 0);
  }
}

void PprVCat::output(OStream &out, unsigned indent) const
{
  bool first = true;
  for (auto child: *m_children) {
    if (first) {
      first = false;
    } else {
      out << std::endl;
    }
    child->output(out, indent);
  }
}

namespace
{
  template <typename T>
  Ptr<T> cat(Ptr<Ppr> a, Ptr<Ppr> b)
  {
    return std::shared_ptr<T>(new T {a, b});
  }
}

namespace ppr
{
  Ptr<Ppr> string(const String &str)
  {
    return ptr<PprString>(str);
  }

  Ptr<Ppr> string(const Char *str)
  {
    return ptr<PprString>(String(str));
  }

  Ptr<Ppr> indent(Ptr<Ppr> ppr, unsigned ind)
  {
    return ptr<PprIndent>(ppr, ind);
  }

  Ptr<Ppr> parens_if(bool b, const Ptr<Ppr> ppr)
  {
    if (b)
      return hcat({'('_p, ppr, ')'_p});
    else
      return ppr;
  }

  Ptr<Ppr> vcat(std::initializer_list<Ptr<Ppr>> pprs)
  {
    return ptr<PprVCat>(pprs);
  }

  Ptr<Ppr> hcat(std::initializer_list<Ptr<Ppr>> pprs)
  {
    return ptr<PprHCat>(pprs);
  }
}

Ptr<Ppr> operator>>(Ptr<Ppr> ppr, unsigned ind)
{
  return ppr::indent(ppr, ind * Ppr::default_indent);
}

Ptr<Ppr> operator""_p(const Char *str, size_t len)
{
  return ptr<PprString>(String(str, len));
}

Ptr<Ppr> operator""_p(Char c)
{
  return ptr<PprString>(String(1, c));
}

Ptr<Ppr> operator+(Ptr<Ppr> p)
{
  return ppr::hcat({' '_p, p});
}

}
<|endoftext|>


<commit_before>#include "kmeans.hpp"

#include <set>

using namespace SuppleSearch::Algorithms;

KMeans::KMeans(Measure::shared measure, size_t k, size_t max_iterations)
  : k_(k), max_iterations_(max_iterations), measure_(measure) {
  srand(time(0));
  // srand(123);
}

arma::vec KMeans::process(arma::mat documents) {
  arma::mat distances = arma::zeros(k_, documents.n_cols);
  arma::mat centroids = arma::zeros(k_, documents.n_rows);
  arma::vec current_clusters = arma::zeros(documents.n_cols);

  std::set<size_t> used_documents;

  // random seed
  for (size_t i = 0; i < k_; i++) {
    size_t index;

    do {
      index = rand() % documents.n_cols;
    } while(used_documents.find(index) != used_documents.end());

    centroids.row(i) = documents.col(index).t();
    used_documents.insert(index);
  }

  for (size_t iteration = 0; iteration < max_iterations_; iteration++) {
    // calculate distances
    for (size_t document = 0; document < documents.n_cols; document++) {
      for (size_t i = 0; i < k_; i++) {
        distances(i, document) = measure_->compare((arma::vec)documents.col(document), centroids.row(i).t());
      }
    }

    bool has_changed = false;

    // find closest centroid and assign to cluster
    for (size_t document = 0; document < documents.n_cols; document++) {
      arma::uword cluster;

      distances.col(document).max(cluster);

      if (current_clusters(document) != cluster) {
        current_clusters(document) = cluster;
        has_changed = true;
      }
    }

    if (!has_changed) {
      std::cout << "Done after " << iteration << " iterations." << std::endl << std::endl;
      break;
    }

    // calculate new centroid
    for (size_t cluster = 0; cluster < k_; cluster++) {
      arma::vec mean = arma::zeros(documents.n_rows);
      size_t size = 0;

      for (size_t document = 0; document < current_clusters.n_rows; document++) {
        if (current_clusters(document) != cluster)
          continue;

        mean += documents.col(document);
        size++;
      }

      centroids.row(cluster) = mean.t();
    }
  }

  return current_clusters;
}

<commit_msg>forgot to calcualte mean<commit_after>#include "kmeans.hpp"

#include <set>

using namespace SuppleSearch::Algorithms;

KMeans::KMeans(Measure::shared measure, size_t k, size_t max_iterations)
  : k_(k), max_iterations_(max_iterations), measure_(measure) {
  srand(time(0));
  // srand(123);
}

arma::vec KMeans::process(arma::mat documents) {
  arma::mat distances = arma::zeros(k_, documents.n_cols);
  arma::mat centroids = arma::zeros(k_, documents.n_rows);
  arma::vec current_clusters = arma::zeros(documents.n_cols);

  std::set<size_t> used_documents;

  // random seed
  for (size_t i = 0; i < k_; i++) {
    size_t index;

    do {
      index = rand() % documents.n_cols;
    } while(used_documents.find(index) != used_documents.end());

    centroids.row(i) = documents.col(index).t();
    used_documents.insert(index);
  }

  for (size_t iteration = 0; iteration < max_iterations_; iteration++) {
    // calculate distances
    for (size_t document = 0; document < documents.n_cols; document++) {
      for (size_t i = 0; i < k_; i++) {
        distances(i, document) = measure_->compare((arma::vec)documents.col(document), centroids.row(i).t());
      }
    }

    bool has_changed = false;

    // find closest centroid and assign to cluster
    for (size_t document = 0; document < documents.n_cols; document++) {
      arma::uword cluster;

      distances.col(document).max(cluster);

      if (current_clusters(document) != cluster) {
        current_clusters(document) = cluster;
        has_changed = true;
      }
    }

    if (!has_changed) {
      std::cout << "Done after " << iteration << " iterations." << std::endl << std::endl;
      break;
    }

    // calculate new centroid
    for (size_t cluster = 0; cluster < k_; cluster++) {
      arma::vec mean = arma::zeros(documents.n_rows);
      size_t size = 0;

      for (size_t document = 0; document < current_clusters.n_rows; document++) {
        if (current_clusters(document) != cluster)
          continue;

        mean += documents.col(document);
        size++;
      }

      mean /= size;

      centroids.row(cluster) = mean.t();
    }
  }

  return current_clusters;
}

<|endoftext|>


<commit_before>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/rule.h"

#include <stdio.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <list>
#include <utility>

#include "operators/operator.h"
#include "actions/action.h"
#include "modsecurity/modsecurity.h"
#include "actions/transformations/none.h"
#include "variables/variations/exclusion.h"
#include "src/utils.h"
#include "src/macro_expansion.h"

using ModSecurity::Variables::Variations::Exclusion;

namespace ModSecurity {

using operators::Operator;
using actions::Action;
using Variables::Variable;
using actions::transformations::None;

Rule::~Rule() {
    if (op != NULL) {
        delete op;
    }
    while (actions_conf.empty() == false) {
        auto *a = actions_conf.back();
        actions_conf.pop_back();
        delete a;
    }
    while (actions_runtime_pre.empty() == false) {
        auto *a = actions_runtime_pre.back();
        actions_runtime_pre.pop_back();
        delete a;
    }
    while (actions_runtime_pos.empty() == false) {
        auto *a = actions_runtime_pos.back();
        actions_runtime_pos.pop_back();
        delete a;
    }
    while (variables != NULL && variables->empty() == false) {
        auto *a = variables->back();
        variables->pop_back();
        delete a;
    }

    if (variables != NULL) {
        delete variables;
    }
}

Rule::Rule(std::string marker)
    : chained(false),
    chainedRule(NULL),
    variables(NULL),
    op(NULL),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(true),
    m_marker(marker),
    m_referenceCount(0) { };

Rule::Rule(Operator *_op,
        std::vector<Variable *> *_variables,
        std::vector<Action *> *actions)
    : chained(false),
    chainedRule(NULL),
    variables(_variables),
    op(_op),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(false),
    m_marker(""),
    m_referenceCount(0) {
    for (Action *a : *actions) {
        if (a->action_kind == Action::ConfigurationKind) {
            actions_conf.push_back(a);
            a->evaluate(this, NULL);
        } else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) {
            actions_runtime_pre.push_back(a);
        } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) {
            actions_runtime_pos.push_back(a);
        } else {
            std::cout << "General failure, action: " << a->name;
            std::cout << " has an unknown type." << std::endl;
            delete a;
        }
    }
    /**
     * If phase is not entered, we assume phase 2. For historical reasons.
     *
     */
    if (phase == -1) {
        phase = ModSecurity::Phases::RequestHeadersPhase;
    }

    if (op == NULL) {
        m_unconditional = true;
    }

    delete actions;
}

bool Rule::evaluateActions(Assay *assay) {
    int none = 0;
    int transformations = 0;
    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        if (z != NULL) {
            none++;
        }
    }

    assay->debug(4, "Running unconditional rule.");

    if (none == 0) {
        /*
        for (Action *a : assay->m_rules->defaultActions[this->phase]) {
            if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                value = a->evaluate(value, assay);
                assay->debug(9, "(SecDefaultAction) T (" + \
                    std::to_string(transformations) + ") " + \
                    a->name + ": \"" + value +"\"");
                    transformations++;
            }
        }
        */
    }

    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        /*
        if (none == 0) {
            value = a->evaluate(value, assay);
            assay->debug(9, " T (" + \
                std::to_string(transformations) + ") " + \
                a->name + ": \"" + value +"\"");
                transformations++;
        }
        */
        if (z != NULL) {
            none--;
        }
    }

    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
            a->evaluate(this, assay);
        }
    }

    for (Action *a :
        this->actions_runtime_pos) {
        assay->debug(4, "Running action: " + a->action);
        a->evaluate(this, assay);
    }

    return true;
}

bool Rule::evaluate(Assay *assay) {
    bool ret = false;
    std::vector<Variable *> *variables = this->variables;

    if (m_secmarker == true) {
        return true;
    }
    if (m_unconditional == true) {
        return evaluateActions(assay);
    }

    assay->debug(4, "(Rule: " + std::to_string(rule_id) \
        + ") Executing operator \"" + this->op->op \
        + "\" with param: " \
        + MacroExpansion::expandKeepOriginal(this->op->param, assay) \
        + ", against " \
        + Variable::to_s(variables) + ".");

    clock_t begin = clock();

    std::list<std::string> exclusions;
    for (int i = 0; i < variables->size(); i++) {
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);

        if (exl != NULL) {
            std::list<std::pair<std::string, std::string>> z =
                variable->evaluate(assay);
            for (auto &y : z) {
                exclusions.push_back(y.first);
            }
            exclusions.push_back(variable->name);
        }
    }

    for (int i = 0; i < variables->size(); i++) {
        int transformations = 0;
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);
        if (exl != NULL) {
            continue;
        }

        std::list<std::pair<std::string, std::string>> e =
            variable->evaluate(assay);

        for (auto &v : e) {
            if (std::find(exclusions.begin(), exclusions.end(),
                v.first) != exclusions.end()) {
                assay->debug(9, "Variable: " + v.first + " is part of the" +
                    " exclusion list, skipping...");
                continue;
            }
            std::string value = v.second;
            int none = 0;
            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (z != NULL) {
                    none++;
                }
            }

            // Check for transformations on the SecDefaultAction
            // Notice that first we make sure that won't be a t:none
            // on the target rule.
            if (none == 0) {
                for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                    if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                        value = a->evaluate(value, assay);
                        assay->debug(9, "(SecDefaultAction) T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                        transformations++;
                    }
                }
            }

            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (none == 0) {
                    value = a->evaluate(value, assay);
                    assay->debug(9, " T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                    transformations++;
                }
                if (z != NULL) {
                    none--;
                }
            }

            assay->debug(9, "Target value: \"" + limitTo(80, toHexIfNeeded(value)) + \
                "\" (Variable: " + v.first + ")");

            ret = this->op->evaluate(assay, value);

            clock_t end = clock();
            double elapsed_secs = static_cast<double>(end - begin) \
                / CLOCKS_PER_SEC;

            assay->debug(4, "Operator completed in " + \
                std::to_string(elapsed_secs) + " seconds");

            if (ret) {
                bool chainResult = false;
                assay->debug(4, "Rule returned 1.");

                if (this->chained && this->chainedRule == NULL) {
                    assay->debug(4, "Rule is marked as chained but there " \
                        "isn't a subsequent rule.");
                }
                if (this->chained && this->chainedRule != NULL) {
                    assay->debug(4, "Executing chained rule.");
                    if (assay->update_variable_first("MATCHED_VAR",
                        value) == false) {
                        assay->store_variable("MATCHED_VAR", value);
                    }
                    if (assay->update_variable_first("MATCHED_VAR_NAME",
                        v.first) == false) {
                        assay->store_variable("MATCHED_VAR_NAME", v.first);
                    }
                    assay->store_variable("MATCHED_VARS:" + v.first, value);
                    assay->store_variable("MATCHED_VARS_NAMES:" + v.first,
                        v.first);
                    chainResult = this->chainedRule->evaluate(assay);
                    assay->update_variable_first("MATCHED_VAR", "");
                    assay->delete_variable("MATCHED_VARS:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                }
                if (this->chained && chainResult == true || !this->chained) {
                    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
                            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
                            a->evaluate(this, assay);
                        }
                    }
                    for (Action *a :
                        this->actions_runtime_pos) {
                        assay->debug(4, "Running action: " + a->action);
                        a->evaluate(this, assay);
                    }
                }

            } else {
                assay->debug(4, "Rule returned 0.");
            }
        }
    }
    return ret;
}

}  // namespace ModSecurity
<commit_msg>Fix the rule execution debug log, so that tests won't complain<commit_after>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/rule.h"

#include <stdio.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <list>
#include <utility>

#include "operators/operator.h"
#include "actions/action.h"
#include "modsecurity/modsecurity.h"
#include "actions/transformations/none.h"
#include "variables/variations/exclusion.h"
#include "src/utils.h"
#include "src/macro_expansion.h"

using ModSecurity::Variables::Variations::Exclusion;

namespace ModSecurity {

using operators::Operator;
using actions::Action;
using Variables::Variable;
using actions::transformations::None;

Rule::~Rule() {
    if (op != NULL) {
        delete op;
    }
    while (actions_conf.empty() == false) {
        auto *a = actions_conf.back();
        actions_conf.pop_back();
        delete a;
    }
    while (actions_runtime_pre.empty() == false) {
        auto *a = actions_runtime_pre.back();
        actions_runtime_pre.pop_back();
        delete a;
    }
    while (actions_runtime_pos.empty() == false) {
        auto *a = actions_runtime_pos.back();
        actions_runtime_pos.pop_back();
        delete a;
    }
    while (variables != NULL && variables->empty() == false) {
        auto *a = variables->back();
        variables->pop_back();
        delete a;
    }

    if (variables != NULL) {
        delete variables;
    }
}

Rule::Rule(std::string marker)
    : chained(false),
    chainedRule(NULL),
    variables(NULL),
    op(NULL),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(true),
    m_marker(marker),
    m_referenceCount(0) { };

Rule::Rule(Operator *_op,
        std::vector<Variable *> *_variables,
        std::vector<Action *> *actions)
    : chained(false),
    chainedRule(NULL),
    variables(_variables),
    op(_op),
    rule_id(0),
    phase(-1),
    m_unconditional(false),
    m_secmarker(false),
    m_marker(""),
    m_referenceCount(0) {
    for (Action *a : *actions) {
        if (a->action_kind == Action::ConfigurationKind) {
            actions_conf.push_back(a);
            a->evaluate(this, NULL);
        } else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) {
            actions_runtime_pre.push_back(a);
        } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) {
            actions_runtime_pos.push_back(a);
        } else {
            std::cout << "General failure, action: " << a->name;
            std::cout << " has an unknown type." << std::endl;
            delete a;
        }
    }
    /**
     * If phase is not entered, we assume phase 2. For historical reasons.
     *
     */
    if (phase == -1) {
        phase = ModSecurity::Phases::RequestHeadersPhase;
    }

    if (op == NULL) {
        m_unconditional = true;
    }

    delete actions;
}

bool Rule::evaluateActions(Assay *assay) {
    int none = 0;
    int transformations = 0;
    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        if (z != NULL) {
            none++;
        }
    }

    assay->debug(4, "Running unconditional rule.");

    if (none == 0) {
        /*
        for (Action *a : assay->m_rules->defaultActions[this->phase]) {
            if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                value = a->evaluate(value, assay);
                assay->debug(9, "(SecDefaultAction) T (" + \
                    std::to_string(transformations) + ") " + \
                    a->name + ": \"" + value +"\"");
                    transformations++;
            }
        }
        */
    }

    for (Action *a : this->actions_runtime_pre) {
        None *z = dynamic_cast<None *>(a);
        /*
        if (none == 0) {
            value = a->evaluate(value, assay);
            assay->debug(9, " T (" + \
                std::to_string(transformations) + ") " + \
                a->name + ": \"" + value +"\"");
                transformations++;
        }
        */
        if (z != NULL) {
            none--;
        }
    }

    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
            a->evaluate(this, assay);
        }
    }

    for (Action *a :
        this->actions_runtime_pos) {
        assay->debug(4, "Running action: " + a->action);
        a->evaluate(this, assay);
    }

    return true;
}

bool Rule::evaluate(Assay *assay) {
    bool ret = false;
    std::vector<Variable *> *variables = this->variables;

    if (m_secmarker == true) {
        return true;
    }
    if (m_unconditional == true) {
        return evaluateActions(assay);
    }

    std::string eparam = MacroExpansion::expand(this->op->param, assay);

    if (this->op->param != eparam) {
        eparam = "\"" + eparam + "\" Was: \"" + this->op->param + "\"";
    } else {
        eparam = "\"" + eparam + "\"";
    }

    assay->debug(4, "(Rule: " + std::to_string(rule_id) \
        + ") Executing operator \"" + this->op->op \
        + "\" with param " \
        + eparam \
        + " against " \
        + Variable::to_s(variables) + ".");

    clock_t begin = clock();

    std::list<std::string> exclusions;
    for (int i = 0; i < variables->size(); i++) {
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);

        if (exl != NULL) {
            std::list<std::pair<std::string, std::string>> z =
                variable->evaluate(assay);
            for (auto &y : z) {
                exclusions.push_back(y.first);
            }
            exclusions.push_back(variable->name);
        }
    }

    for (int i = 0; i < variables->size(); i++) {
        int transformations = 0;
        Variable *variable = variables->at(i);
        Exclusion *exl = dynamic_cast<Exclusion *>(variable);
        if (exl != NULL) {
            continue;
        }

        std::list<std::pair<std::string, std::string>> e =
            variable->evaluate(assay);

        for (auto &v : e) {
            if (std::find(exclusions.begin(), exclusions.end(),
                v.first) != exclusions.end()) {
                assay->debug(9, "Variable: " + v.first + " is part of the" +
                    " exclusion list, skipping...");
                continue;
            }
            std::string value = v.second;
            int none = 0;
            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (z != NULL) {
                    none++;
                }
            }

            // Check for transformations on the SecDefaultAction
            // Notice that first we make sure that won't be a t:none
            // on the target rule.
            if (none == 0) {
                for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                    if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
                        value = a->evaluate(value, assay);
                        assay->debug(9, "(SecDefaultAction) T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                        transformations++;
                    }
                }
            }

            for (Action *a : this->actions_runtime_pre) {
                None *z = dynamic_cast<None *>(a);
                if (none == 0) {
                    value = a->evaluate(value, assay);
                    assay->debug(9, " T (" + \
                            std::to_string(transformations) + ") " + \
                            a->name + ": \"" + value +"\"");
                    transformations++;
                }
                if (z != NULL) {
                    none--;
                }
            }

            assay->debug(9, "Target value: \"" + limitTo(80, toHexIfNeeded(value)) + \
                "\" (Variable: " + v.first + ")");

            ret = this->op->evaluate(assay, value);

            clock_t end = clock();
            double elapsed_secs = static_cast<double>(end - begin) \
                / CLOCKS_PER_SEC;

            assay->debug(4, "Operator completed in " + \
                std::to_string(elapsed_secs) + " seconds");

            if (ret) {
                bool chainResult = false;
                assay->debug(4, "Rule returned 1.");

                if (this->chained && this->chainedRule == NULL) {
                    assay->debug(4, "Rule is marked as chained but there " \
                        "isn't a subsequent rule.");
                }
                if (this->chained && this->chainedRule != NULL) {
                    assay->debug(4, "Executing chained rule.");
                    if (assay->update_variable_first("MATCHED_VAR",
                        value) == false) {
                        assay->store_variable("MATCHED_VAR", value);
                    }
                    if (assay->update_variable_first("MATCHED_VAR_NAME",
                        v.first) == false) {
                        assay->store_variable("MATCHED_VAR_NAME", v.first);
                    }
                    assay->store_variable("MATCHED_VARS:" + v.first, value);
                    assay->store_variable("MATCHED_VARS_NAMES:" + v.first,
                        v.first);
                    chainResult = this->chainedRule->evaluate(assay);
                    assay->update_variable_first("MATCHED_VAR", "");
                    assay->delete_variable("MATCHED_VARS:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                    assay->delete_variable("MATCHED_VARS_NAMES:" + v.first);
                }
                if (this->chained && chainResult == true || !this->chained) {
                    for (Action *a : assay->m_rules->defaultActions[this->phase]) {
                        if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
                            assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
                            a->evaluate(this, assay);
                        }
                    }
                    for (Action *a :
                        this->actions_runtime_pos) {
                        assay->debug(4, "Running action: " + a->action);
                        a->evaluate(this, assay);
                    }
                }

            } else {
                assay->debug(4, "Rule returned 0.");
            }
        }
    }
    return ret;
}

}  // namespace ModSecurity
<|endoftext|>


<commit_before>// [[Rcpp::plugins(cpp14)]]
#include <Rcpp.h>
#include <tumopp/simulation.hpp>

//' Run C++ simulation
//' @return conf and population as strings
//' @rdname tumopp
// [[Rcpp::export]]
std::vector<std::string> cpp_tumopp(const std::vector<std::string>& args, const size_t npair=0) {
    tumopp::Simulation sim(args);
    sim.run();
    return {
        sim.conf(),
        sim.tissue().specimens(),
        sim.tissue().drivers(),
        sim.tissue().pairwise_distance(npair)};
}
<commit_msg>:arrow_up: Get results from tumopp with a new method<commit_after>// [[Rcpp::plugins(cpp14)]]
#include <Rcpp.h>
#include <tumopp/simulation.hpp>

//' Run C++ simulation
//' @return conf and population as strings
//' @rdname tumopp
// [[Rcpp::export]]
std::vector<std::string> cpp_tumopp(const std::vector<std::string>& args, const size_t npair=0) {
    tumopp::Simulation sim(args);
    sim.run();
    return sim.results();
}
<|endoftext|>


<commit_before>// Copyright (2015) Gustav

#include "finans/core/commandline.h"

#include <cassert>
#include <algorithm>

namespace argparse {

  ParserError::ParserError(const std::string& error)
    : runtime_error("error: " + error)
  {
  }

  Arguments::Arguments(int argc, char* argv[]) : name_(argv[0])
  {
    for (int i = 1; i < argc; ++i)
    {
      args_.push_back(argv[i]);
    }
  }
  Arguments::Arguments(const std::string& name, const std::vector<std::string>& args) : name_(name), args_(args) {
  }

  const std::string Arguments::operator[](int index) const
  {
    return args_[index];
  }
  const bool Arguments::is_empty() const
  {
    return args_.empty();
  }
  const std::string Arguments::name() const
  {
    return name_;
  }
  const size_t Arguments::size() const
  {
    return args_.size();
  }
  const std::string Arguments::ConsumeOne(const std::string& error)
  {
    if (is_empty()) throw ParserError(error);
    const std::string r = args_[0];
    args_.erase(args_.begin());
    return r;
  }

  Count::Count(size_t c)
    : count_(c)
    , type_(Const)
  {
  }

  Count::Count(Count::Type t)
    : count_(0)
    , type_(t)
  {
    assert(t != Const);
  }

  Count::Type Count::type() const
  {
    return type_;
  }
  size_t Count::count() const
  {
    return count_;
  }

  Running::Running(const std::string& aapp, std::ostream& ao)
    : app(aapp)
    , o(ao)
  {
  }

  Argument::~Argument()
  {
  }

  Argument::Argument(const Count& co)
    : count_(co)
    , has_been_parsed_(false)
    , has_several_(false)
  {
  }

  bool Argument::has_been_parsed() const {
    return has_been_parsed_;
  }

  void Argument::set_has_been_parsed(bool v) {
    if (has_several_) return;
    has_been_parsed_ = v;
  }

  void Argument::ConsumeArguments(Running& r, Arguments& args, const std::string& argname) {
    switch (count_.type())
    {
    case Count::Const:
      for (size_t i = 0; i < count_.count(); ++i)
      {
        std::stringstream ss;
        ss << "argument " << argname << ": expected ";
        if (count_.count() == 1)
        {
          ss << "one argument";
        }
        else
        {
          ss << count_.count() << " argument(s), " << i << " already given";
        }
        OnArgument(r, args.ConsumeOne(ss.str()));

        // abort on optional?
      }
      return;
    case Count::MoreThanOne:
      OnArgument(r, args.ConsumeOne("argument " + argname + ": expected atleast one argument"));
      // fall through
    case Count::ZeroOrMore:
      while (args.is_empty() == false)
      {
        OnArgument(r, args.ConsumeOne("internal error"));
      }
      return;
    case Count::Optional:
      if (args.is_empty()) {
        OnArgument(r, "");
        return;
      }
      if (IsOptional(args[0])) {
        OnArgument(r, "");
        return;
      }
      OnArgument(r, args.ConsumeOne("internal error"));
      return;
    case Count::None:
      OnArgument(r, "");
      return;
    default:
      assert(0 && "internal error, ArgumentT::parse invalid Count");
      throw "internal error, ArgumentT::parse invalid Count";
    }
  }

  void Argument::set_has_several() {
    has_several_ = true;
  }

  bool IsOptional(const std::string& arg)
  {
    if (arg.empty()) return false; // todo: assert this?
    return arg[0] == '-';
  }

  Extra::Extra()
    : count_(1)
    , has_several_(false)
  {
  }

  Extra& Extra::help(const std::string& h)
  {
    help_ = h;
    return *this;
  }
  const std::string& Extra::help() const
  {
    return help_;
  }

  Extra& Extra::count(const Count c)
  {
    count_ = c;
    return *this;
  }
  const Count& Extra::count() const
  {
    return count_;
  }

  Extra& Extra::metavar(const std::string& metavar)
  {
    metaVar_ = metavar;
    return *this;
  }

  const std::string& Extra::metavar() const
  {
    return metaVar_;
  }

  Extra& Extra::several() {
    has_several_ = true;
    return *this;
  }
  bool Extra::has_several() const {
    return has_several_;
  }

  std::string ToUpper(const std::string& s)
  {
    std::string str = s;
    std::transform(str.begin(), str.end(), str.begin(), toupper);
    return str;
  }

  Help::Help(const std::string& name, const Extra& e)
    : name_(name)
    , help_(e.help())
    , metavar_(e.metavar())
    , count_(e.count().type())
    , countcount_(e.count().count())

  {
  }

  const std::string Help::GetUsage() const
  {
    if (IsOptional(name_))
    {
      const auto rep = GetMetavarReprestentation();
      if( rep.empty()) return "[" + name_ + "]";
      return "[" + name_ + " " + rep + "]";
    }
    else
    {
      return GetMetavarReprestentation();
    }
  }

  const std::string Help::GetMetavarReprestentation() const
  {
    switch (count_)
    {
    case Count::None:
      return "";
    case Count::MoreThanOne:
      return GetMetavarName() + " [" + GetMetavarName() + " ...]";
    case Count::Optional:
      return "[" + GetMetavarName() + "]";
    case Count::ZeroOrMore:
      return "[" + GetMetavarName() + " [" + GetMetavarName() + " ...]]";
    case Count::Const:
    {
      std::ostringstream ss;
      ss << "[";
      for (size_t i = 0; i < countcount_; ++i)
      {
        if (i != 0)
        {
          ss << " ";
        }
        ss << GetMetavarName();
      }
      ss << "]";
      return ss.str();
    }
    default:
      assert(false && "missing case");
      throw "invalid count type in " __FUNCTION__;
    }
  }

  const std::string Help::GetMetavarName() const
  {
    if (metavar_.empty() == false)
    {
      return metavar_;
    }
    else
    {
      if (IsOptional(name_))
      {
        return ToUpper(name_.substr(1));
      }
      else
      {
        return name_;
      }
    }
  }

  const std::string Help::GetHelpCommand() const
  {
    if (IsOptional(name_))
    {
      return name_ + " " + GetMetavarReprestentation();
    }
    else
    {
      return GetMetavarName();
    }
  }

  const std::string& Help::help() const
  {
    return help_;
  }

  struct CallHelp : public Argument
  {
    CallHelp(Parser* on)
      : Argument( Count(Count::Optional) )
      , parser(on)
    {
    }

    void OnArgument(Running& r, const std::string& argname) override
    {
      parser->WriteHelp(r);
      exit(0);
    }

    Parser* parser;
  };

  class ParserChild : public Parser {
  public:
    ParserChild(const std::string& desc, const Parser* parent) : Parser(desc), parent_(parent) {}

    void WriteUsage(Running& r) const override {
      parent_->WriteUsage(r);
      Parser::WriteUsage(r);
    }

  private:
    const Parser* parent_;
  };

  Parser::Parser(const std::string& d, const std::string aappname)
    : positionalIndex_(0)
    , description_(d)
    , appname_(aappname)
    , sub_parsers_("subparser")
  {
    std::shared_ptr<Argument> arg(new CallHelp(this));
    AddArgument("-h", arg, Extra().count(Count(Count::None)).help("show this help message and exit"));
  }

  Parser::ParseStatus Parser::ParseArgs(int argc, char* argv[], std::ostream& out, std::ostream& error) const
  {
    Arguments args(argc, argv);
    return ParseArgs(args, out, error);
  }

  Parser& Parser::AddSubParser(const std::string& name, SubParser* parser) {
    sub_parsers_(name, parser);
    return *this;
  }

  Parser::ParseStatus Parser::ParseArgs(const Arguments& arguments, std::ostream& out, std::ostream& error) const {
    Arguments args = arguments;
    Running running(arguments.name(), out);

    try
    {
      while (false == args.is_empty())
      {
        bool isParsed = false;
        const bool isParsingPositionals = positionalIndex_ < positionals_.size();

        if (IsOptional(args[0]))
        {
          // optional
          const std::string arg = args[0];
          Optionals::const_iterator r = optionals_.find(arg);
          if (r == optionals_.end())
          {
            if( isParsingPositionals == false ) {
              throw ParserError("Unknown optional argument: " + arg); // todo: implement partial matching of arguments?
            }
          }
          else {
            if( false == r->second->has_been_parsed() ) {
              isParsed = true;
              args.ConsumeOne(); // the optional command = arg[0}
              r->second->ConsumeArguments(running, args, arg);
              r->second->set_has_been_parsed(true);
            }
          }
        }

        bool consumed = false;

        if( isParsed == false ) {
          if (positionalIndex_ >= positionals_.size())
          {
            if( sub_parsers_.empty() ) {
              throw ParserError("All positional arguments have been consumed: " + args[0]);
            }
            else {
              std::string subname;
              SubParser* sub = sub_parsers_.Convert(args[0], &subname);
              ParserChild parser(args[0], this);
              sub->AddParser(parser);
              consumed = true;
              args.ConsumeOne("SUBCOMMAND");
              auto res = parser.ParseArgs(args, out, error);
              if (res != ParseStatus::ParseComplete) {
                error << "Failed to parse " << subname << "\n";
                return res;
              }
              return ParseStatus::ParseComplete;
            }
          }
          if (consumed == false) {
            ArgumentPtr p = positionals_[positionalIndex_];
            ++positionalIndex_;
            p->ConsumeArguments(running, args, "POSITIONAL"); // todo: give better name or something
          }
        }
      }

      if (positionalIndex_ != positionals_.size())
      {
        throw ParserError("too few arguments."); // todo: list a few missing arguments...
      }

      return ParseComplete;
    }
    catch (ParserError& p)
    {
      WriteUsage(running);
      error << p.what() << "\n";
      out << "\n";
      return ParseFailed;
    }
  }

  void Parser::WriteHelp(Running& r) const
  {
    WriteUsage(r);
    r.o << std::endl << description_ << std::endl << std::endl;

    const std::string sep = "\t";
    const std::string ins = "  ";

    if (helpPositional_.empty() == false)
    {
      r.o << "Positional arguments: " << std::endl;
      for (const Help& positional : helpPositional_)
      {
        r.o << ins << positional.GetHelpCommand() << sep << positional.help() << std::endl;
      }

      r.o << std::endl;
    }

    if (helpOptional_.empty() == false)
    {
      r.o << "Optional arguments: " << std::endl;
      for (const Help& optional : helpOptional_)
      {
        r.o << ins << optional.GetHelpCommand() << sep << optional.help() << std::endl;
      }
    }

    r.o << std::endl;
  }

  void Parser::WriteUsage(Running& r) const
  {
    r.o << "Usage:";
    for (const Help& optional : helpOptional_)
    {
      r.o << " " << optional.GetUsage();
    }

    if (false == sub_parsers_.empty()) {
      const auto sp = sub_parsers_.names();
      r.o << " {";
      bool first = true;
      for (const auto& p : sp) {
        if (first == false) {
          r.o << "|";
        }
        first = false;
        r.o << p;
      }
      r.o << "}";
    }

    for (const Help& positional : helpPositional_)
    {
      r.o << " " << positional.GetUsage();
    }
  }

  Parser& Parser::AddArgument(const std::string& commands, ArgumentPtr arg, const Extra& extra)
  {
    if( extra.has_several() ) {
      arg->set_has_several();
    }
    const auto names = Tokenize(commands, ",", true);
    std::string thename = "";
    for(const auto name: names) {
      if (IsOptional(name))
      {
        optionals_.insert(Optionals::value_type(name, arg));
        if (thename.empty()) thename = name.substr(1);
      }
      else
      {
        positionals_.push_back(arg);
        if( thename.empty() ) thename = name;
      }
    }
    Extra e = extra;
    if (e.metavar().empty()) {
      e.metavar(thename);
    }
    helpOptional_.push_back(Help(commands, e));
    return *this;
  }
}
<commit_msg>WriteUsage shouldn't print "usage"<commit_after>// Copyright (2015) Gustav

#include "finans/core/commandline.h"

#include <cassert>
#include <algorithm>

namespace argparse {

  ParserError::ParserError(const std::string& error)
    : runtime_error("error: " + error)
  {
  }

  Arguments::Arguments(int argc, char* argv[]) : name_(argv[0])
  {
    for (int i = 1; i < argc; ++i)
    {
      args_.push_back(argv[i]);
    }
  }
  Arguments::Arguments(const std::string& name, const std::vector<std::string>& args) : name_(name), args_(args) {
  }

  const std::string Arguments::operator[](int index) const
  {
    return args_[index];
  }
  const bool Arguments::is_empty() const
  {
    return args_.empty();
  }
  const std::string Arguments::name() const
  {
    return name_;
  }
  const size_t Arguments::size() const
  {
    return args_.size();
  }
  const std::string Arguments::ConsumeOne(const std::string& error)
  {
    if (is_empty()) throw ParserError(error);
    const std::string r = args_[0];
    args_.erase(args_.begin());
    return r;
  }

  Count::Count(size_t c)
    : count_(c)
    , type_(Const)
  {
  }

  Count::Count(Count::Type t)
    : count_(0)
    , type_(t)
  {
    assert(t != Const);
  }

  Count::Type Count::type() const
  {
    return type_;
  }
  size_t Count::count() const
  {
    return count_;
  }

  Running::Running(const std::string& aapp, std::ostream& ao)
    : app(aapp)
    , o(ao)
  {
  }

  Argument::~Argument()
  {
  }

  Argument::Argument(const Count& co)
    : count_(co)
    , has_been_parsed_(false)
    , has_several_(false)
  {
  }

  bool Argument::has_been_parsed() const {
    return has_been_parsed_;
  }

  void Argument::set_has_been_parsed(bool v) {
    if (has_several_) return;
    has_been_parsed_ = v;
  }

  void Argument::ConsumeArguments(Running& r, Arguments& args, const std::string& argname) {
    switch (count_.type())
    {
    case Count::Const:
      for (size_t i = 0; i < count_.count(); ++i)
      {
        std::stringstream ss;
        ss << "argument " << argname << ": expected ";
        if (count_.count() == 1)
        {
          ss << "one argument";
        }
        else
        {
          ss << count_.count() << " argument(s), " << i << " already given";
        }
        OnArgument(r, args.ConsumeOne(ss.str()));

        // abort on optional?
      }
      return;
    case Count::MoreThanOne:
      OnArgument(r, args.ConsumeOne("argument " + argname + ": expected atleast one argument"));
      // fall through
    case Count::ZeroOrMore:
      while (args.is_empty() == false)
      {
        OnArgument(r, args.ConsumeOne("internal error"));
      }
      return;
    case Count::Optional:
      if (args.is_empty()) {
        OnArgument(r, "");
        return;
      }
      if (IsOptional(args[0])) {
        OnArgument(r, "");
        return;
      }
      OnArgument(r, args.ConsumeOne("internal error"));
      return;
    case Count::None:
      OnArgument(r, "");
      return;
    default:
      assert(0 && "internal error, ArgumentT::parse invalid Count");
      throw "internal error, ArgumentT::parse invalid Count";
    }
  }

  void Argument::set_has_several() {
    has_several_ = true;
  }

  bool IsOptional(const std::string& arg)
  {
    if (arg.empty()) return false; // todo: assert this?
    return arg[0] == '-';
  }

  Extra::Extra()
    : count_(1)
    , has_several_(false)
  {
  }

  Extra& Extra::help(const std::string& h)
  {
    help_ = h;
    return *this;
  }
  const std::string& Extra::help() const
  {
    return help_;
  }

  Extra& Extra::count(const Count c)
  {
    count_ = c;
    return *this;
  }
  const Count& Extra::count() const
  {
    return count_;
  }

  Extra& Extra::metavar(const std::string& metavar)
  {
    metaVar_ = metavar;
    return *this;
  }

  const std::string& Extra::metavar() const
  {
    return metaVar_;
  }

  Extra& Extra::several() {
    has_several_ = true;
    return *this;
  }
  bool Extra::has_several() const {
    return has_several_;
  }

  std::string ToUpper(const std::string& s)
  {
    std::string str = s;
    std::transform(str.begin(), str.end(), str.begin(), toupper);
    return str;
  }

  Help::Help(const std::string& name, const Extra& e)
    : name_(name)
    , help_(e.help())
    , metavar_(e.metavar())
    , count_(e.count().type())
    , countcount_(e.count().count())

  {
  }

  const std::string Help::GetUsage() const
  {
    if (IsOptional(name_))
    {
      const auto rep = GetMetavarReprestentation();
      if( rep.empty()) return "[" + name_ + "]";
      return "[" + name_ + " " + rep + "]";
    }
    else
    {
      return GetMetavarReprestentation();
    }
  }

  const std::string Help::GetMetavarReprestentation() const
  {
    switch (count_)
    {
    case Count::None:
      return "";
    case Count::MoreThanOne:
      return GetMetavarName() + " [" + GetMetavarName() + " ...]";
    case Count::Optional:
      return "[" + GetMetavarName() + "]";
    case Count::ZeroOrMore:
      return "[" + GetMetavarName() + " [" + GetMetavarName() + " ...]]";
    case Count::Const:
    {
      std::ostringstream ss;
      ss << "[";
      for (size_t i = 0; i < countcount_; ++i)
      {
        if (i != 0)
        {
          ss << " ";
        }
        ss << GetMetavarName();
      }
      ss << "]";
      return ss.str();
    }
    default:
      assert(false && "missing case");
      throw "invalid count type in " __FUNCTION__;
    }
  }

  const std::string Help::GetMetavarName() const
  {
    if (metavar_.empty() == false)
    {
      return metavar_;
    }
    else
    {
      if (IsOptional(name_))
      {
        return ToUpper(name_.substr(1));
      }
      else
      {
        return name_;
      }
    }
  }

  const std::string Help::GetHelpCommand() const
  {
    if (IsOptional(name_))
    {
      return name_ + " " + GetMetavarReprestentation();
    }
    else
    {
      return GetMetavarName();
    }
  }

  const std::string& Help::help() const
  {
    return help_;
  }

  struct CallHelp : public Argument
  {
    CallHelp(Parser* on)
      : Argument( Count(Count::Optional) )
      , parser(on)
    {
    }

    void OnArgument(Running& r, const std::string& argname) override
    {
      parser->WriteHelp(r);
      exit(0);
    }

    Parser* parser;
  };

  class ParserChild : public Parser {
  public:
    ParserChild(const std::string& desc, const Parser* parent) : Parser(desc), parent_(parent) {}

    void WriteUsage(Running& r) const override {
      parent_->WriteUsage(r);
      Parser::WriteUsage(r);
    }

  private:
    const Parser* parent_;
  };

  Parser::Parser(const std::string& d, const std::string aappname)
    : positionalIndex_(0)
    , description_(d)
    , appname_(aappname)
    , sub_parsers_("subparser")
  {
    std::shared_ptr<Argument> arg(new CallHelp(this));
    AddArgument("-h", arg, Extra().count(Count(Count::None)).help("show this help message and exit"));
  }

  Parser::ParseStatus Parser::ParseArgs(int argc, char* argv[], std::ostream& out, std::ostream& error) const
  {
    Arguments args(argc, argv);
    return ParseArgs(args, out, error);
  }

  Parser& Parser::AddSubParser(const std::string& name, SubParser* parser) {
    sub_parsers_(name, parser);
    return *this;
  }

  Parser::ParseStatus Parser::ParseArgs(const Arguments& arguments, std::ostream& out, std::ostream& error) const {
    Arguments args = arguments;
    Running running(arguments.name(), out);

    try
    {
      while (false == args.is_empty())
      {
        bool isParsed = false;
        const bool isParsingPositionals = positionalIndex_ < positionals_.size();

        if (IsOptional(args[0]))
        {
          // optional
          const std::string arg = args[0];
          Optionals::const_iterator r = optionals_.find(arg);
          if (r == optionals_.end())
          {
            if( isParsingPositionals == false ) {
              throw ParserError("Unknown optional argument: " + arg); // todo: implement partial matching of arguments?
            }
          }
          else {
            if( false == r->second->has_been_parsed() ) {
              isParsed = true;
              args.ConsumeOne(); // the optional command = arg[0}
              r->second->ConsumeArguments(running, args, arg);
              r->second->set_has_been_parsed(true);
            }
          }
        }

        bool consumed = false;

        if( isParsed == false ) {
          if (positionalIndex_ >= positionals_.size())
          {
            if( sub_parsers_.empty() ) {
              throw ParserError("All positional arguments have been consumed: " + args[0]);
            }
            else {
              std::string subname;
              SubParser* sub = sub_parsers_.Convert(args[0], &subname);
              ParserChild parser(args[0], this);
              sub->AddParser(parser);
              consumed = true;
              args.ConsumeOne("SUBCOMMAND");
              auto res = parser.ParseArgs(args, out, error);
              if (res != ParseStatus::ParseComplete) {
                error << "Failed to parse " << subname << "\n";
                return res;
              }
              return ParseStatus::ParseComplete;
            }
          }
          if (consumed == false) {
            ArgumentPtr p = positionals_[positionalIndex_];
            ++positionalIndex_;
            p->ConsumeArguments(running, args, "POSITIONAL"); // todo: give better name or something
          }
        }
      }

      if (positionalIndex_ != positionals_.size())
      {
        throw ParserError("too few arguments."); // todo: list a few missing arguments...
      }

      return ParseComplete;
    }
    catch (ParserError& p)
    {
      running.o << "Usage:";
      WriteUsage(running);
      error << p.what() << "\n";
      out << "\n";
      return ParseFailed;
    }
  }

  void Parser::WriteHelp(Running& r) const
  {
    r.o << "Usage:";
    WriteUsage(r);
    r.o << std::endl << description_ << std::endl << std::endl;

    const std::string sep = "\t";
    const std::string ins = "  ";

    if (helpPositional_.empty() == false)
    {
      r.o << "Positional arguments: " << std::endl;
      for (const Help& positional : helpPositional_)
      {
        r.o << ins << positional.GetHelpCommand() << sep << positional.help() << std::endl;
      }

      r.o << std::endl;
    }

    if (helpOptional_.empty() == false)
    {
      r.o << "Optional arguments: " << std::endl;
      for (const Help& optional : helpOptional_)
      {
        r.o << ins << optional.GetHelpCommand() << sep << optional.help() << std::endl;
      }
    }

    r.o << std::endl;
  }

  void Parser::WriteUsage(Running& r) const
  {
    for (const Help& optional : helpOptional_)
    {
      r.o << " " << optional.GetUsage();
    }

    if (false == sub_parsers_.empty()) {
      const auto sp = sub_parsers_.names();
      r.o << " {";
      bool first = true;
      for (const auto& p : sp) {
        if (first == false) {
          r.o << "|";
        }
        first = false;
        r.o << p;
      }
      r.o << "}";
    }

    for (const Help& positional : helpPositional_)
    {
      r.o << " " << positional.GetUsage();
    }
  }

  Parser& Parser::AddArgument(const std::string& commands, ArgumentPtr arg, const Extra& extra)
  {
    if( extra.has_several() ) {
      arg->set_has_several();
    }
    const auto names = Tokenize(commands, ",", true);
    std::string thename = "";
    for(const auto name: names) {
      if (IsOptional(name))
      {
        optionals_.insert(Optionals::value_type(name, arg));
        if (thename.empty()) thename = name.substr(1);
      }
      else
      {
        positionals_.push_back(arg);
        if( thename.empty() ) thename = name;
      }
    }
    Extra e = extra;
    if (e.metavar().empty()) {
      e.metavar(thename);
    }
    helpOptional_.push_back(Help(commands, e));
    return *this;
  }
}
<|endoftext|>


<commit_before>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <stdexcept>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <stdio.h>

#include <stan/mcmc/chains.hpp>

namespace testing {

  /**
   * Model_Test_Fixture is a test fixture for google test
   * to aid in running models.
   *
   * Derived classes must define:
   *   static std::vector<std::string> get_model_path()
   *
   * Template parameters:
   *   bool has_data: indicates whether the model has data
   *   size_t chains: number of chains to run
   */
  template <class Derived>
  class Model_Test_Fixture : public ::testing::Test {

  protected:
    static char path_separator;
    static std::string base_name;
    static const size_t chains = 2;
    static const bool has_data = false;

    static void SetUpTestCase() {
      set_path_separator();
      set_base_name(get_model_path());
    }

    static void set_path_separator() {
      FILE *in;
      if(!(in = popen("make path_separator --no-print-directory", "r")))
        throw std::runtime_error("\"make path_separator\" has failed.");
      path_separator = fgetc(in);
      pclose(in);
    }

    static void
    set_base_name(const std::vector<std::string> model_path) {
      base_name.clear();
      if (model_path.size() < 0)
        return;
      base_name.append(model_path[0]);
      for (size_t i = 1; i < model_path.size(); i++) {
        base_name.append(1, path_separator);
        base_name.append(model_path[i]);
      }
    }

    static std::string get_command(size_t chain) {
      std::stringstream command;
      command << base_name;
      command << " --samples=" << base_name << "." << chain << ".csv";
      //if (Model_Test_Fixture::has_data) {
      //command << " --data=" << base_name << ".Rdata";
      //}
      return command.str();
    }

    static void run() {
      for (size_t chain = 0; chain < chains; chain++) {
        std::string command = get_command(chain);
        EXPECT_EQ(0, system(command.c_str()))
          << "Can not execute command: " << command << std::endl;
      }
    }

  public:
    /**
     * Return the path to the model (without the extension) as
     * a vector.
     *
     * @return the path to the model
     */
    static std::vector<std::string> get_model_path() {
      return Derived::get_model_path();
    }

  };

  template<class Derived>
  char Model_Test_Fixture<Derived>::path_separator;

  template<class Derived>
  std::string Model_Test_Fixture<Derived>::base_name;
}
#endif
<commit_msg>test-models: updating Model_Test_Fixture<commit_after>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <stdexcept>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <stdio.h>

#include <stan/mcmc/chains.hpp>

namespace testing {

  /**
   * Model_Test_Fixture is a test fixture for google test
   * to aid in running models.
   *
   * Derived classes must define:
   *   static std::vector<std::string> get_model_path()
   *
   * Template parameters:
   *   bool has_data: indicates whether the model has data
   *   size_t chains: number of chains to run
   */
  template <class Derived,
            bool has_data = false>
  class Model_Test_Fixture : public ::testing::Test {

  protected:
    static char path_separator;
    static std::string base_name;
    static const size_t chains = 2;

    static void SetUpTestCase() {
      set_path_separator();
      set_base_name(get_model_path());
    }

    static void set_path_separator() {
      FILE *in;
      if(!(in = popen("make path_separator --no-print-directory", "r")))
        throw std::runtime_error("\"make path_separator\" has failed.");
      path_separator = fgetc(in);
      pclose(in);
    }

    static void
    set_base_name(const std::vector<std::string> model_path) {
      base_name.clear();
      if (model_path.size() < 0)
        return;
      base_name.append(model_path[0]);
      for (size_t i = 1; i < model_path.size(); i++) {
        base_name.append(1, path_separator);
        base_name.append(model_path[i]);
      }
    }

    static std::string get_command(size_t chain) {
      std::stringstream command;
      command << base_name;
      command << " --samples=" << base_name << "." << chain << ".csv";
      //if (Model_Test_Fixture::has_data) {
      //command << " --data=" << base_name << ".Rdata";
      //}
      return command.str();
    }

    static void run() {
      for (size_t chain = 0; chain < chains; chain++) {
        std::string command = get_command(chain);
        EXPECT_EQ(0, system(command.c_str()))
          << "Can not execute command: " << command << std::endl;
      }
    }

  public:
    /**
     * Return the path to the model (without the extension) as
     * a vector.
     *
     * @return the path to the model
     */
    static std::vector<std::string> get_model_path() {
      return Derived::get_model_path();
    }

  };

  template<class Derived, bool has_data>
  char Model_Test_Fixture<Derived, has_data>::path_separator;

  template<class Derived, has_data>
  std::string Model_Test_Fixture<Derived, has_data>::base_name;
}
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/test/unit_test.hpp>
#include <consensus/validation.h>
#include <primitives/block.h>
#include <scheduler.h>
#include <test/util/setup_common.h>
#include <util/check.h>
#include <validationinterface.h>

BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)

struct TestSubscriberNoop final : public CValidationInterface {
    void BlockChecked(const CBlock&, const BlockValidationState&) override {}
};

BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
{
    std::atomic<bool> generate{true};

    // Start thread to generate notifications
    std::thread gen{[&] {
        const CBlock block_dummy;
        const BlockValidationState state_dummy;
        while (generate) {
            GetMainSignals().BlockChecked(block_dummy, state_dummy);
        }
    }};

    // Start thread to consume notifications
    std::thread sub{[&] {
        // keep going for about 1 sec, which is 250k iterations
        for (int i = 0; i < 250000; i++) {
            auto sub = std::make_shared<TestSubscriberNoop>();
            RegisterSharedValidationInterface(sub);
            UnregisterSharedValidationInterface(sub);
        }
        // tell the other thread we are done
        generate = false;
    }};

    gen.join();
    sub.join();
    BOOST_CHECK(!generate);
}

class TestInterface : public CValidationInterface
{
public:
    TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
        : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
    {
    }
    virtual ~TestInterface()
    {
        if (m_on_destroy) m_on_destroy();
    }
    void BlockChecked(const CBlock& block, const BlockValidationState& state) override
    {
        if (m_on_call) m_on_call();
    }
    static void Call()
    {
        CBlock block;
        BlockValidationState state;
        GetMainSignals().BlockChecked(block, state);
    }
    std::function<void()> m_on_call;
    std::function<void()> m_on_destroy;
};

// Regression test to ensure UnregisterAllValidationInterfaces calls don't
// destroy a validation interface while it is being called. Bug:
// https://github.com/bitcoin/bitcoin/pull/18551
BOOST_AUTO_TEST_CASE(unregister_all_during_call)
{
    bool destroyed = false;
    RegisterSharedValidationInterface(std::make_shared<TestInterface>(
        [&] {
            // First call should decrements reference count 2 -> 1
            UnregisterAllValidationInterfaces();
            BOOST_CHECK(!destroyed);
            // Second call should not decrement reference count 1 -> 0
            UnregisterAllValidationInterfaces();
            BOOST_CHECK(!destroyed);
        },
        [&] { destroyed = true; }));
    TestInterface::Call();
    BOOST_CHECK(destroyed);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>test: Remove const to work around compiler error on xenial<commit_after>// Copyright (c) 2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/test/unit_test.hpp>
#include <consensus/validation.h>
#include <primitives/block.h>
#include <scheduler.h>
#include <test/util/setup_common.h>
#include <util/check.h>
#include <validationinterface.h>

BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)

struct TestSubscriberNoop final : public CValidationInterface {
    void BlockChecked(const CBlock&, const BlockValidationState&) override {}
};

BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
{
    std::atomic<bool> generate{true};

    // Start thread to generate notifications
    std::thread gen{[&] {
        const CBlock block_dummy;
        BlockValidationState state_dummy;
        while (generate) {
            GetMainSignals().BlockChecked(block_dummy, state_dummy);
        }
    }};

    // Start thread to consume notifications
    std::thread sub{[&] {
        // keep going for about 1 sec, which is 250k iterations
        for (int i = 0; i < 250000; i++) {
            auto sub = std::make_shared<TestSubscriberNoop>();
            RegisterSharedValidationInterface(sub);
            UnregisterSharedValidationInterface(sub);
        }
        // tell the other thread we are done
        generate = false;
    }};

    gen.join();
    sub.join();
    BOOST_CHECK(!generate);
}

class TestInterface : public CValidationInterface
{
public:
    TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
        : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy))
    {
    }
    virtual ~TestInterface()
    {
        if (m_on_destroy) m_on_destroy();
    }
    void BlockChecked(const CBlock& block, const BlockValidationState& state) override
    {
        if (m_on_call) m_on_call();
    }
    static void Call()
    {
        CBlock block;
        BlockValidationState state;
        GetMainSignals().BlockChecked(block, state);
    }
    std::function<void()> m_on_call;
    std::function<void()> m_on_destroy;
};

// Regression test to ensure UnregisterAllValidationInterfaces calls don't
// destroy a validation interface while it is being called. Bug:
// https://github.com/bitcoin/bitcoin/pull/18551
BOOST_AUTO_TEST_CASE(unregister_all_during_call)
{
    bool destroyed = false;
    RegisterSharedValidationInterface(std::make_shared<TestInterface>(
        [&] {
            // First call should decrements reference count 2 -> 1
            UnregisterAllValidationInterfaces();
            BOOST_CHECK(!destroyed);
            // Second call should not decrement reference count 1 -> 0
            UnregisterAllValidationInterfaces();
            BOOST_CHECK(!destroyed);
        },
        [&] { destroyed = true; }));
    TestInterface::Call();
    BOOST_CHECK(destroyed);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>