<commit_before>// Copyright (c) 2012-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 "consensus/consensus.h"
#include "consensus/validation.h"
#include "key.h"
#include "pubkey.h"
#include "script/interpreter.h"
#include "script/script.h"
#include "script/standard.h"
#include "test/test_bitcoin.h"
#include "uint256.h"
#include "validation.h"

#include <limits>
#include <vector>

#include <boost/test/unit_test.hpp>

// Helpers:
static std::vector<uint8_t> Serialize(const CScript &s) {
    std::vector<uint8_t> sSerialized(s.begin(), s.end());
    return sSerialized;
}

BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(GetSigOpCount) {
    // Test CScript::GetSigOpCount()
    CScript s1;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0U);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0U);

    uint160 dummy;
    s1 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << OP_2
       << OP_CHECKMULTISIG;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2U);
    s1 << OP_IF << OP_CHECKSIG << OP_ENDIF;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U);

    CScript p2sh = GetScriptForDestination(CScriptID(s1));
    CScript scriptSig;
    scriptSig << OP_0 << Serialize(s1);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);

    std::vector<CPubKey> keys;
    for (int i = 0; i < 3; i++) {
        CKey k;
        k.MakeNewKey(true);
        keys.push_back(k.GetPubKey());
    }
    CScript s2 = GetScriptForMultisig(1, keys);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U);

    p2sh = GetScriptForDestination(CScriptID(s2));
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U);
    CScript scriptSig2;
    scriptSig2 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy)
               << Serialize(s2);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U);
}

/**
 * Verifies script execution of the zeroth scriptPubKey of tx output and zeroth
 * scriptSig and witness of tx input.
 */
ScriptError VerifyWithFlag(const CTransaction &output,
                           const CMutableTransaction &input, int flags) {
    ScriptError error;
    CTransaction inputi(input);
    bool ret = VerifyScript(
        inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, flags,
        TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
    BOOST_CHECK_EQUAL((ret == true), (error == SCRIPT_ERR_OK));

    return error;
}

/**
 * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig and
 * witness such that spendingTx spends output zero of creationTx. Also inserts
 * creationTx's output into the coins view.
 */
void BuildTxs(CMutableTransaction &spendingTx, CCoinsViewCache &coins,
              CMutableTransaction &creationTx, const CScript &scriptPubKey,
              const CScript &scriptSig) {
    creationTx.nVersion = 1;
    creationTx.vin.resize(1);
    creationTx.vin[0].prevout = COutPoint();
    creationTx.vin[0].scriptSig = CScript();
    creationTx.vout.resize(1);
    creationTx.vout[0].nValue = Amount(1);
    creationTx.vout[0].scriptPubKey = scriptPubKey;

    spendingTx.nVersion = 1;
    spendingTx.vin.resize(1);
    spendingTx.vin[0].prevout = COutPoint(creationTx.GetId(), 0);
    spendingTx.vin[0].scriptSig = scriptSig;
    spendingTx.vout.resize(1);
    spendingTx.vout[0].nValue = Amount(1);
    spendingTx.vout[0].scriptPubKey = CScript();

    AddCoins(coins, CTransaction(creationTx), 0);
}

BOOST_AUTO_TEST_CASE(GetTxSigOpCost) {
    // Transaction creates outputs
    CMutableTransaction creationTx;
    // Transaction that spends outputs and whose sig op cost is going to be
    // tested
    CMutableTransaction spendingTx;

    // Create utxo set
    CCoinsView coinsDummy;
    CCoinsViewCache coins(&coinsDummy);
    // Create key
    CKey key;
    key.MakeNewKey(true);
    CPubKey pubkey = key.GetPubKey();
    // Default flags
    int flags = SCRIPT_VERIFY_P2SH;

    // Multisig script (legacy counting)
    {
        CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey)
                                         << ToByteVector(pubkey) << 2
                                         << OP_CHECKMULTISIGVERIFY;
        // Do not use a valid signature to avoid using wallet operations.
        CScript scriptSig = CScript() << OP_0 << OP_0;

        BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig);

        // Legacy counting only includes signature operations in scriptSigs and
        // scriptPubKeys of a transaction and does not take the actual executed
        // sig operations into account. spendingTx in itself does not contain a
        // signature operation.
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags),
            0);
        // creationTx contains two signature operations in its scriptPubKey, but
        // legacy counting is not accurate.
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(creationTx), coins, flags),
            MAX_PUBKEYS_PER_MULTISIG);
        // Sanity check: script verification fails because of an invalid
        // signature.
        BOOST_CHECK_EQUAL(
            VerifyWithFlag(CTransaction(creationTx), spendingTx, flags),
            SCRIPT_ERR_CHECKMULTISIGVERIFY);
    }

    // Multisig nested in P2SH
    {
        CScript redeemScript = CScript() << 1 << ToByteVector(pubkey)
                                         << ToByteVector(pubkey) << 2
                                         << OP_CHECKMULTISIGVERIFY;
        CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
        CScript scriptSig = CScript()
                            << OP_0 << OP_0 << ToByteVector(redeemScript);

        BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig);
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags),
            2);
        BOOST_CHECK_EQUAL(
            VerifyWithFlag(CTransaction(creationTx), spendingTx, flags),
            SCRIPT_ERR_CHECKMULTISIGVERIFY);
    }
}

BOOST_AUTO_TEST_CASE(test_consensus_sigops_limit) {
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(123456), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000000), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000001),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1348592),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000000),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000001),
                      3 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2654321),
                      3 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(<commit_msg>Add test case for GetTransactionSigOpCount without the P2SH flags passed in.<commit_after>// Copyright (c) 2012-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 "consensus/consensus.h"
#include "consensus/validation.h"
#include "key.h"
#include "pubkey.h"
#include "script/interpreter.h"
#include "script/script.h"
#include "script/standard.h"
#include "test/test_bitcoin.h"
#include "uint256.h"
#include "validation.h"

#include <limits>
#include <vector>

#include <boost/test/unit_test.hpp>

// Helpers:
static std::vector<uint8_t> Serialize(const CScript &s) {
    std::vector<uint8_t> sSerialized(s.begin(), s.end());
    return sSerialized;
}

BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(GetSigOpCount) {
    // Test CScript::GetSigOpCount()
    CScript s1;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0U);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0U);

    uint160 dummy;
    s1 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << OP_2
       << OP_CHECKMULTISIG;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2U);
    s1 << OP_IF << OP_CHECKSIG << OP_ENDIF;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U);

    CScript p2sh = GetScriptForDestination(CScriptID(s1));
    CScript scriptSig;
    scriptSig << OP_0 << Serialize(s1);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);

    std::vector<CPubKey> keys;
    for (int i = 0; i < 3; i++) {
        CKey k;
        k.MakeNewKey(true);
        keys.push_back(k.GetPubKey());
    }
    CScript s2 = GetScriptForMultisig(1, keys);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U);

    p2sh = GetScriptForDestination(CScriptID(s2));
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U);
    CScript scriptSig2;
    scriptSig2 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy)
               << Serialize(s2);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U);
}

/**
 * Verifies script execution of the zeroth scriptPubKey of tx output and zeroth
 * scriptSig and witness of tx input.
 */
ScriptError VerifyWithFlag(const CTransaction &output,
                           const CMutableTransaction &input, int flags) {
    ScriptError error;
    CTransaction inputi(input);
    bool ret = VerifyScript(
        inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, flags,
        TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
    BOOST_CHECK_EQUAL((ret == true), (error == SCRIPT_ERR_OK));

    return error;
}

/**
 * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig and
 * witness such that spendingTx spends output zero of creationTx. Also inserts
 * creationTx's output into the coins view.
 */
void BuildTxs(CMutableTransaction &spendingTx, CCoinsViewCache &coins,
              CMutableTransaction &creationTx, const CScript &scriptPubKey,
              const CScript &scriptSig) {
    creationTx.nVersion = 1;
    creationTx.vin.resize(1);
    creationTx.vin[0].prevout = COutPoint();
    creationTx.vin[0].scriptSig = CScript();
    creationTx.vout.resize(1);
    creationTx.vout[0].nValue = Amount(1);
    creationTx.vout[0].scriptPubKey = scriptPubKey;

    spendingTx.nVersion = 1;
    spendingTx.vin.resize(1);
    spendingTx.vin[0].prevout = COutPoint(creationTx.GetId(), 0);
    spendingTx.vin[0].scriptSig = scriptSig;
    spendingTx.vout.resize(1);
    spendingTx.vout[0].nValue = Amount(1);
    spendingTx.vout[0].scriptPubKey = CScript();

    AddCoins(coins, CTransaction(creationTx), 0);
}

BOOST_AUTO_TEST_CASE(GetTxSigOpCost) {
    // Transaction creates outputs
    CMutableTransaction creationTx;
    // Transaction that spends outputs and whose sig op cost is going to be
    // tested
    CMutableTransaction spendingTx;

    // Create utxo set
    CCoinsView coinsDummy;
    CCoinsViewCache coins(&coinsDummy);
    // Create key
    CKey key;
    key.MakeNewKey(true);
    CPubKey pubkey = key.GetPubKey();
    // Default flags
    const uint32_t flags = SCRIPT_VERIFY_P2SH;

    // Multisig script (legacy counting)
    {
        CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey)
                                         << ToByteVector(pubkey) << 2
                                         << OP_CHECKMULTISIGVERIFY;
        // Do not use a valid signature to avoid using wallet operations.
        CScript scriptSig = CScript() << OP_0 << OP_0;

        BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig);

        // Legacy counting only includes signature operations in scriptSigs and
        // scriptPubKeys of a transaction and does not take the actual executed
        // sig operations into account. spendingTx in itself does not contain a
        // signature operation.
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags),
            0);
        // creationTx contains two signature operations in its scriptPubKey, but
        // legacy counting is not accurate.
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(creationTx), coins, flags),
            MAX_PUBKEYS_PER_MULTISIG);
        // Sanity check: script verification fails because of an invalid
        // signature.
        BOOST_CHECK_EQUAL(
            VerifyWithFlag(CTransaction(creationTx), spendingTx, flags),
            SCRIPT_ERR_CHECKMULTISIGVERIFY);

        // Make sure non P2SH sigops are counted even if the flag for P2SH is
        // not passed in.
        BOOST_CHECK_EQUAL(GetTransactionSigOpCount(CTransaction(spendingTx),
                                                   coins, SCRIPT_VERIFY_NONE),
                          0);
        BOOST_CHECK_EQUAL(GetTransactionSigOpCount(CTransaction(creationTx),
                                                   coins, SCRIPT_VERIFY_NONE),
                          MAX_PUBKEYS_PER_MULTISIG);
    }

    // Multisig nested in P2SH
    {
        CScript redeemScript = CScript() << 1 << ToByteVector(pubkey)
                                         << ToByteVector(pubkey) << 2
                                         << OP_CHECKMULTISIGVERIFY;
        CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
        CScript scriptSig = CScript()
                            << OP_0 << OP_0 << ToByteVector(redeemScript);

        BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig);
        BOOST_CHECK_EQUAL(
            GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags),
            2);
        BOOST_CHECK_EQUAL(
            VerifyWithFlag(CTransaction(creationTx), spendingTx, flags),
            SCRIPT_ERR_CHECKMULTISIGVERIFY);

        // Make sure P2SH sigops are not counted if the flag for P2SH is not
        // passed in.
        BOOST_CHECK_EQUAL(GetTransactionSigOpCount(CTransaction(spendingTx),
                                                   coins, SCRIPT_VERIFY_NONE),
                          0);
    }
}

BOOST_AUTO_TEST_CASE(test_consensus_sigops_limit) {
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(123456), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000000), MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000001),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1348592),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000000),
                      2 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000001),
                      3 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2654321),
                      3 * MAX_BLOCK_SIGOPS_PER_MB);
    BOOST_CHECK_EQUAL(
{'fraction_non_alphanumeric': 0.09735498232290166, 'fraction_numerical': 0.019968574047400812, 'mean_word_length': 2.974759302628155, 'pattern_counts': {'":': 0, '<': 133, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5423986', 'n_tokens_mistral': 5013, 'n_tokens_neox': 4702, 'n_words': 965}