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

#include "test/test_bitcoin.h"

#include "script/interpreter.h"

#include <boost/test/unit_test.hpp>

using valtype = std::vector<unsigned char>;

BOOST_FIXTURE_TEST_SUITE(sigencoding_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(checkpubkeyencoding_test) {
    valtype compressedKey0{<KEY>,<commit_msg>Add test cases for CheckSignatureEncoding<commit_after>// Copyright (c) 2018 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_bitcoin.h"

#include "script/interpreter.h"
#include "script/sighashtype.h"

#include <boost/test/unit_test.hpp>

using valtype = std::vector<unsigned char>;

BOOST_FIXTURE_TEST_SUITE(sigencoding_tests, BasicTestingSetup)

static valtype SignatureWithHashType(valtype vchSig, SigHashType sigHash) {
    vchSig.push_back(static_cast<uint8_t>(sigHash));
    return vchSig;
}

static void CheckSignatureEncodingWithSigHashType(const valtype &vchSig,
                                                  uint32_t flags) {
    const bool hasForkId = (flags & SCRIPT_ENABLE_SIGHASH_FORKID) != 0;
    const bool hasStrictEnc = (flags & SCRIPT_VERIFY_STRICTENC) != 0;

    std::vector<SigHashType> allBaseTypes{
        SigHashType::ALL, SigHashType::NONE, SigHashType::SINGLE};

    std::vector<SigHashType> baseSigHashes;
    for (const SigHashType baseType : allBaseTypes) {
        baseSigHashes.push_back(baseType);
        baseSigHashes.push_back(baseType | SigHashType::ANYONECANPAY);
    }

    for (const SigHashType baseSigHash : baseSigHashes) {
        ScriptError err = SCRIPT_ERR_OK;

        // Check the signature with the proper forkid flag.
        SigHashType sigHash = baseSigHash;
        if (hasForkId) {
            sigHash |= SigHashType::FORKID;
        }
        valtype validSig = SignatureWithHashType(vchSig, sigHash);
        BOOST_CHECK(CheckSignatureEncoding(validSig, flags, &err));

        // If we have strict encoding, we prevent the use of undefined flags.
        std::array<SigHashType, 2> undefSigHashes{
            SigHashType(sigHash | SigHashType(0x20)),
            SigHashType::UNDEFINED
        };

        for (SigHashType undefSigHash : undefSigHashes) {
            valtype undefSighash = SignatureWithHashType(vchSig, undefSigHash);
            BOOST_CHECK_EQUAL(CheckSignatureEncoding(undefSighash, flags, &err),
                              !hasStrictEnc);
            if (hasStrictEnc) {
                BOOST_CHECK_EQUAL(err, SCRIPT_ERR_SIG_HASHTYPE);
            }
        }

        // If we check strict encoding, then invalid forkid is an error.
        SigHashType invalidSigHash = hasForkId
            ? baseSigHash & ~SigHashType::FORKID
            : baseSigHash | SigHashType::FORKID;
        valtype invalidSig = SignatureWithHashType(vchSig, invalidSigHash);

        BOOST_CHECK_EQUAL(CheckSignatureEncoding(invalidSig, flags, &err),
                          !hasStrictEnc);
        if (hasStrictEnc) {
            BOOST_CHECK_EQUAL(err,
                              hasForkId ? SCRIPT_ERR_MUST_USE_FORKID
                                        : SCRIPT_ERR_ILLEGAL_FORKID);
        }
    }
}

BOOST_AUTO_TEST_CASE(checksignatureencoding_test) {
    valtype nullfailsig{};
    valtype minimalsig{0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01};

    // If we add many more flags, this loop can get too expensive, but we can
    // rewrite in the future to randomly pick a set of flags to evaluate.
    for (uint32_t flags = 0; flags < (1U << 17); flags++) {
        ScriptError err = SCRIPT_ERR_OK;

        // Empty sig is always valid.
        BOOST_CHECK(CheckSignatureEncoding({}, flags, &err));

        // Signature are valid as long as the forkid flag is correct.
        CheckSignatureEncodingWithSigHashType(minimalsig, flags);
    }
}

BOOST_AUTO_TEST_CASE(checkpubkeyencoding_test) {
    valtype compressedKey0{<KEY>,
{'fraction_non_alphanumeric': 0.08784596871239471, 'fraction_numerical': 0.011793020457280385, 'mean_word_length': 3.0077145612343297, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3285852', 'n_tokens_mistral': 1328, 'n_tokens_neox': 1246, 'n_words': 286}