/*
* This file is part of the Flowee project
* Copyright (C) 2009-2010 Satoshi Nakamoto
* Copyright (C) 2009-2015 The Bitcoin Core developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef FLOWEE_SCRIPT_INTERPRETER_H
#define FLOWEE_SCRIPT_INTERPRETER_H
#include "script_error.h"
#include "../primitives/Tx.h"
#include
#include
class PublicKey;
class CScript;
class CScriptNum;
class CTransaction;
class uint256;
/** Signature hash types/flags */
enum
{
SIGHASH_ALL = 1,
SIGHASH_NONE = 2,
SIGHASH_SINGLE = 3,
SIGHASH_UTXOS = 0x20,
SIGHASH_FORKID = 0x40,
SIGHASH_ANYONECANPAY = 0x80,
};
/** Script verification flags */
enum
{
SCRIPT_VERIFY_NONE = 0,
// Evaluate P2SH subscripts (softfork safe, BIP16).
SCRIPT_VERIFY_P2SH = (1U << 0),
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
// Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure.
// (softfork safe, but not used or intended as a consensus rule).
SCRIPT_VERIFY_STRICTENC = (1U << 1),
// Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
SCRIPT_VERIFY_DERSIG = (1U << 2),
// Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
// (softfork safe, BIP62 rule 5).
SCRIPT_VERIFY_LOW_S = (1U << 3),
// verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
SCRIPT_VERIFY_NULLDUMMY = (1U << 4),
// Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5),
// Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
// pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
// any other push causes the script to fail (BIP62 rule 3).
// In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
// (softfork safe)
SCRIPT_VERIFY_MINIMALDATA = (1U << 6),
// Discourage use of NOPs reserved for upgrades (NOP1-10)
//
// Provided so that nodes can avoid accepting or mining transactions
// containing executed NOP's whose meaning may change after a soft-fork,
// thus rendering the script invalid; with this flag set executing
// discouraged NOPs fails the script. This verification flag will never be
// a mandatory flag applied to scripts in a block. NOPs that are not
// executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7),
// Require that only a single stack element remains after evaluation. This changes the success criterion from
// "At least one stack element must remain, and when interpreted as a boolean, it must be true" to
// "Exactly one stack element must remain, and when interpreted as a boolean, it must be true".
// (softfork safe, BIP62 rule 6)
// Note: CLEANSTACK should never be used without P2SH.
SCRIPT_VERIFY_CLEANSTACK = (1U << 8),
// Verify CHECKLOCKTIMEVERIFY
//
// See BIP65 for details.
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
// support CHECKSEQUENCEVERIFY opcode
//
// See BIP112 for details
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10),
// Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
//
SCRIPT_VERIFY_NULLFAIL = (1U << 14),
// Do we accept signature using SIGHASH_FORKID
//
SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16),
// If OP_CHECKDATASIG* are allowed.
SCRIPT_ENABLE_CHECKDATASIG = (1U << 17),
SCRIPT_ENABLE_SCHNORR = (1U << 18),
SCRIPT_ENABLE_SCHNORR_MULTISIG = (1U << 19),
// Allows the miner to appropriate coins sent to p2sh segwit addresses
SCRIPT_ALLOW_SEGWIT_RECOVERY = (1U << 20),
// Whether the new OP_REVERSEBYTES opcode can be used.
SCRIPT_ENABLE_OP_REVERSEBYTES = (1U << 21),
// Enable pay-to-script-hash using OP_HASH256 with a 32-byte script hash.
SCRIPT_ENABLE_P2SH_32 = (1U << 22),
// Enable CHIP-2024-07-BigInt high-precision script integer arithmetic.
SCRIPT_ENABLE_MAY2025 = (1U << 23),
// Enable May 2022 native transaction introspection opcodes.
SCRIPT_ENABLE_NATIVE_INTROSPECTION = (1U << 24),
// Enable May 2023 SIGHASH_UTXOS signing serialization.
SCRIPT_ENABLE_SIGHASH_UTXOS = (1U << 25),
// Enable May 2023 CashTokens script introspection.
SCRIPT_ENABLE_CASHTOKENS = (1U << 26),
// Use May 2025 VM-limit relay costing rules.
SCRIPT_VM_LIMITS_STANDARD = (1U << 27),
// Enable May 2026 script upgrades.
SCRIPT_ENABLE_MAY2026 = (1U << 28),
// Enable May 2022 64-bit script integer arithmetic.
SCRIPT_ENABLE_64_BIT_INTEGERS = (1U << 29),
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int64_t amount, int nHashType,
uint32_t flags = SCRIPT_ENABLE_SIGHASH_FORKID, const std::vector *spentOutputs = nullptr,
size_t *bytesHashed = nullptr);
class BaseSignatureChecker
{
public:
virtual bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey,
const CScript& scriptCode, uint32_t flags, size_t *bytesHashed = nullptr) const
{
if (bytesHashed)
*bytesHashed = 0;
return false;
}
virtual bool CheckLockTime(const CScriptNum& nLockTime) const
{
return false;
}
virtual bool CheckSequence(const CScriptNum& nSequence) const
{
return false;
}
virtual bool hasTransactionContext() const
{
return false;
}
virtual const CTransaction* transaction() const
{
return nullptr;
}
virtual Tx tx() const
{
return Tx();
}
virtual unsigned int inputIndex() const
{
return 0;
}
virtual bool isLimitedContext() const
{
return true;
}
virtual bool spentOutput(unsigned int, Tx::Output&) const
{
return false;
}
virtual ~BaseSignatureChecker() {}
};
class TransactionSignatureChecker : public BaseSignatureChecker
{
private:
const CTransaction* oldTxTo;
const Tx &txTo;
unsigned int nIn;
int64_t amount;
const std::vector *spentOutputs;
protected:
virtual bool VerifySignature(const std::vector& vchSig, const PublicKey& vchPubKey, const uint256& sighash, uint32_t flags) const;
public:
TransactionSignatureChecker(const CTransaction* oldTxToIn, const Tx &txToIn, unsigned int nInIn, int64_t amountIn,
const std::vector *spentOutputsIn = nullptr)
: oldTxTo(oldTxToIn), txTo(txToIn), nIn(nInIn), amount(amountIn), spentOutputs(spentOutputsIn) {}
bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey,
const CScript& scriptCode, uint32_t flags, size_t *bytesHashed = nullptr) const override;
bool CheckLockTime(const CScriptNum& nLockTime) const override;
bool CheckSequence(const CScriptNum& nSequence) const override;
bool hasTransactionContext() const override;
const CTransaction* transaction() const override;
Tx tx() const override;
unsigned int inputIndex() const override;
bool isLimitedContext() const override;
bool spentOutput(unsigned int index, Tx::Output &output) const override;
};
namespace Script {
struct State {
State() = default;
State(uint32_t flags) : flags(flags) {}
uint32_t flags = SCRIPT_VERIFY_NONE; // validation flags
uint32_t sigCheckCount = 0;
uint64_t vmLimitScriptSigSize = 0;
int64_t opCost = 0;
int64_t hashDigestIterations = 0;
ScriptError error = SCRIPT_ERR_OK;
const char* errorString() const;
};
bool eval(std::vector > &stack, const CScript &script, const BaseSignatureChecker &checker, Script::State &state);
bool verify(const CScript& scriptSig, const CScript& scriptPubKey, const BaseSignatureChecker& checker, Script::State &state);
bool checkTransactionSignatureEncoding(const std::vector &vchSig, State &state);
}
#endif