Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 96 additions & 61 deletions src/script/interpreter.cpp

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/script/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,16 +333,16 @@ class DeferringSignatureChecker : public BaseSignatureChecker
};

/** Compute the BIP341 tapleaf hash from leaf version & script. */
uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script);
uint256 ComputeTapleafHash(uint8_t leaf_version, Span<const unsigned char> script);
/** Compute the BIP341 taproot script tree Merkle root from control block and leaf hash.
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash);

bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);
bool EvalScript(std::vector<std::vector<unsigned char>>& stack, Span<const unsigned char> script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
bool EvalScript(std::vector<std::vector<unsigned char>>& stack, Span<const unsigned char> script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
bool VerifyScript(Span<const unsigned char> scriptSig, Span<const unsigned char> scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);

size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
size_t CountWitnessSigOps(Span<const unsigned char> scriptSig, Span<const unsigned char> scriptPubKey, const CScriptWitness* witness, unsigned int flags);

int FindAndDelete(CScript& script, const CScript& b);

Expand Down
55 changes: 30 additions & 25 deletions src/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <script/script.h>

#include <span.h>
#include <util/strencodings.h>

#include <string>
Expand Down Expand Up @@ -280,18 +281,15 @@ bool CScript::HasValidOps() const
return true;
}

bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
bool GetScriptOp(Span<const unsigned char>& script, opcodetype& opcodeRet, Span<const unsigned char>* data_out)
{
opcodeRet = OP_INVALIDOPCODE;
if (pvchRet)
pvchRet->clear();
if (pc >= end)
return false;
if (data_out) *data_out = {};

// Read instruction
if (end - pc < 1)
return false;
unsigned int opcode = *pc++;
if (script.size() < 1) return false;
unsigned int opcode = script.front();
script = script.subspan(1);

// Immediate operand
if (opcode <= OP_PUSHDATA4)
Expand All @@ -303,29 +301,25 @@ bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator en
}
else if (opcode == OP_PUSHDATA1)
{
if (end - pc < 1)
return false;
nSize = *pc++;
if (script.size() < 1) return false;
nSize = script.front();
script = script.subspan(1);
}
else if (opcode == OP_PUSHDATA2)
{
if (end - pc < 2)
return false;
nSize = ReadLE16(&pc[0]);
pc += 2;
if (script.size() < 2) return false;
nSize = ReadLE16(script.data());
script = script.subspan(2);
}
else if (opcode == OP_PUSHDATA4)
{
if (end - pc < 4)
return false;
nSize = ReadLE32(&pc[0]);
pc += 4;
if (script.size() < 4) return false;
nSize = ReadLE32(script.data());
script = script.subspan(4);
}
if (end - pc < 0 || (unsigned int)(end - pc) < nSize)
return false;
if (pvchRet)
pvchRet->assign(pc, pc + nSize);
pc += nSize;
if (script.size() < nSize) return false;
if (data_out) *data_out = script.first(nSize);
script = script.subspan(nSize);
}

opcodeRet = static_cast<opcodetype>(opcode);
Expand All @@ -340,7 +334,7 @@ bool IsOpSuccess(const opcodetype& opcode)
(opcode >= 187 && opcode <= 254);
}

bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode) {
bool CheckMinimalPush(Span<const unsigned char> data, opcodetype opcode) {
// Excludes OP_1NEGATE, OP_1-16 since they are by definition minimal
assert(0 <= opcode && opcode <= OP_PUSHDATA4);
if (data.size() == 0) {
Expand All @@ -364,3 +358,14 @@ bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode)
}
return true;
}

bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
{
if (pc >= end) return false;
Span<const unsigned char> script(&*pc, end - pc);
Span<const unsigned char> data;
bool ret = GetScriptOp(script, opcodeRet, &data);
if (pvchRet) pvchRet->assign(data.begin(), data.end());
pc = end - script.size();
return ret;
}
8 changes: 5 additions & 3 deletions src/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <crypto/common.h>
#include <prevector.h>
#include <serialize.h>
#include <span.h>

#include <assert.h>
#include <climits>
Expand Down Expand Up @@ -404,6 +405,7 @@ class CScriptNum
*/
typedef prevector<28, unsigned char> CScriptBase;

bool GetScriptOp(Span<const unsigned char>& script, opcodetype& opcodeRet, Span<const unsigned char>* data_out);
bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet);

/** Serialized script, used inside transaction inputs and outputs */
Expand Down Expand Up @@ -460,7 +462,7 @@ class CScript : public CScriptBase
return *this;
}

CScript& operator<<(const std::vector<unsigned char>& b) LIFETIMEBOUND
CScript& operator<<(const Span<const unsigned char>& b) LIFETIMEBOUND
{
if (b.size() < OP_PUSHDATA1)
{
Expand Down Expand Up @@ -534,7 +536,7 @@ class CScript : public CScriptBase
bool IsPayToWitnessScriptHash() const;
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;

/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
/** Called by IsStandardTx. */
bool IsPushOnly(const_iterator pc) const;
bool IsPushOnly() const;

Expand Down Expand Up @@ -578,7 +580,7 @@ struct CScriptWitness
/** Test for OP_SUCCESSx opcodes as defined by BIP342. */
bool IsOpSuccess(const opcodetype& opcode);

bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode);
bool CheckMinimalPush(Span<const unsigned char> data, opcodetype opcode);

/** Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<. */
template<typename... Ts>
Expand Down
6 changes: 3 additions & 3 deletions src/uint256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <string.h>

template <unsigned int BITS>
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch)
base_blob<BITS>::base_blob(Span<const unsigned char> vch)
{
assert(vch.size() == sizeof(m_data));
memcpy(m_data, vch.data(), sizeof(m_data));
Expand Down Expand Up @@ -67,14 +67,14 @@ std::string base_blob<BITS>::ToString() const
}

// Explicit instantiations for base_blob<160>
template base_blob<160>::base_blob(const std::vector<unsigned char>&);
template base_blob<160>::base_blob(Span<const unsigned char>);
template std::string base_blob<160>::GetHex() const;
template std::string base_blob<160>::ToString() const;
template void base_blob<160>::SetHex(const char*);
template void base_blob<160>::SetHex(const std::string&);

// Explicit instantiations for base_blob<256>
template base_blob<256>::base_blob(const std::vector<unsigned char>&);
template base_blob<256>::base_blob(Span<const unsigned char>);
template std::string base_blob<256>::GetHex() const;
template std::string base_blob<256>::ToString() const;
template void base_blob<256>::SetHex(const char*);
Expand Down
6 changes: 3 additions & 3 deletions src/uint256.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class base_blob
/* constructor for constants between 1 and 255 */
constexpr explicit base_blob(uint8_t v) : m_data{v} {}

explicit base_blob(const std::vector<unsigned char>& vch);
explicit base_blob(Span<const unsigned char> vch);

bool IsNull() const
{
Expand Down Expand Up @@ -115,7 +115,7 @@ class base_blob
class uint160 : public base_blob<160> {
public:
constexpr uint160() {}
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {}
};

/** 256-bit opaque blob.
Expand All @@ -127,7 +127,7 @@ class uint256 : public base_blob<256> {
public:
constexpr uint256() {}
constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {}
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {}
static const uint256 ZERO;
static const uint256 ONE;
};
Expand Down