Changeset View
Changeset View
Standalone View
Standalone View
src/script/script.h
Show First 20 Lines • Show All 340 Lines • ▼ Show 20 Lines | int getint() const { | ||||
else if (m_value < std::numeric_limits<int>::min()) | else if (m_value < std::numeric_limits<int>::min()) | ||||
return std::numeric_limits<int>::min(); | return std::numeric_limits<int>::min(); | ||||
return m_value; | return m_value; | ||||
} | } | ||||
std::vector<uint8_t> getvch() const { return serialize(m_value); } | std::vector<uint8_t> getvch() const { return serialize(m_value); } | ||||
static std::vector<uint8_t> serialize(const int64_t &value) { | static std::vector<uint8_t> serialize(const int64_t &value) { | ||||
if (value == 0) return std::vector<uint8_t>(); | if (value == 0) { | ||||
return {}; | |||||
} | |||||
std::vector<uint8_t> result; | std::vector<uint8_t> result; | ||||
const bool neg = value < 0; | const bool neg = value < 0; | ||||
uint64_t absvalue = neg ? -value : value; | uint64_t absvalue = neg ? -value : value; | ||||
while (absvalue) { | while (absvalue) { | ||||
result.push_back(absvalue & 0xff); | result.push_back(absvalue & 0xff); | ||||
absvalue >>= 8; | absvalue >>= 8; | ||||
Show All 13 Lines | static std::vector<uint8_t> serialize(const int64_t &value) { | ||||
result.back() |= 0x80; | result.back() |= 0x80; | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
private: | private: | ||||
static int64_t set_vch(const std::vector<uint8_t> &vch) { | static int64_t set_vch(const std::vector<uint8_t> &vch) { | ||||
if (vch.empty()) return 0; | if (vch.empty()) { | ||||
return 0; | |||||
} | |||||
int64_t result = 0; | int64_t result = 0; | ||||
for (size_t i = 0; i != vch.size(); ++i) | for (size_t i = 0; i != vch.size(); ++i) { | ||||
result |= static_cast<int64_t>(vch[i]) << 8 * i; | result |= int64_t(vch[i]) << 8 * i; | ||||
} | |||||
// If the input vector's most significant byte is 0x80, remove it from | // If the input vector's most significant byte is 0x80, remove it from | ||||
// the result's msb and return a negative. | // the result's msb and return a negative. | ||||
if (vch.back() & 0x80) | if (vch.back() & 0x80) { | ||||
return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); | return -int64_t(result & ~(0x80ULL << (8 * (vch.size() - 1)))); | ||||
} | |||||
return result; | return result; | ||||
} | } | ||||
int64_t m_value; | int64_t m_value; | ||||
}; | }; | ||||
typedef prevector<28, uint8_t> CScriptBase; | typedef prevector<28, uint8_t> CScriptBase; | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | public: | ||||
explicit CScript(opcodetype b) { operator<<(b); } | explicit CScript(opcodetype b) { operator<<(b); } | ||||
explicit CScript(const CScriptNum &b) { operator<<(b); } | explicit CScript(const CScriptNum &b) { operator<<(b); } | ||||
explicit CScript(const std::vector<uint8_t> &b) { operator<<(b); } | explicit CScript(const std::vector<uint8_t> &b) { operator<<(b); } | ||||
CScript &operator<<(int64_t b) { return push_int64(b); } | CScript &operator<<(int64_t b) { return push_int64(b); } | ||||
CScript &operator<<(opcodetype opcode) { | CScript &operator<<(opcodetype opcode) { | ||||
if (opcode < 0 || opcode > 0xff) | if (opcode < 0 || opcode > 0xff) { | ||||
throw std::runtime_error("CScript::operator<<(): invalid opcode"); | throw std::runtime_error("CScript::operator<<(): invalid opcode"); | ||||
} | |||||
insert(end(), uint8_t(opcode)); | insert(end(), uint8_t(opcode)); | ||||
return *this; | return *this; | ||||
} | } | ||||
CScript &operator<<(const CScriptNum &b) { | CScript &operator<<(const CScriptNum &b) { | ||||
*this << b.getvch(); | *this << b.getvch(); | ||||
return *this; | return *this; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | public: | ||||
bool GetOp2(const_iterator &pc, opcodetype &opcodeRet, | bool GetOp2(const_iterator &pc, opcodetype &opcodeRet, | ||||
std::vector<uint8_t> *pvchRet) const { | std::vector<uint8_t> *pvchRet) const { | ||||
opcodeRet = OP_INVALIDOPCODE; | opcodeRet = OP_INVALIDOPCODE; | ||||
if (pvchRet) pvchRet->clear(); | if (pvchRet) pvchRet->clear(); | ||||
if (pc >= end()) return false; | if (pc >= end()) return false; | ||||
// Read instruction | // Read instruction | ||||
if (end() - pc < 1) return false; | if (end() - pc < 1) return false; | ||||
unsigned int opcode = *pc++; | |||||
uint32_t opcode = *pc++; | |||||
// Immediate operand | // Immediate operand | ||||
if (opcode <= OP_PUSHDATA4) { | if (opcode <= OP_PUSHDATA4) { | ||||
unsigned int nSize = 0; | uint32_t nSize = 0; | ||||
if (opcode < OP_PUSHDATA1) { | if (opcode < OP_PUSHDATA1) { | ||||
nSize = opcode; | nSize = opcode; | ||||
} else if (opcode == OP_PUSHDATA1) { | } else if (opcode == OP_PUSHDATA1) { | ||||
if (end() - pc < 1) return false; | if (end() - pc < 1) return false; | ||||
nSize = *pc++; | nSize = *pc++; | ||||
} else if (opcode == OP_PUSHDATA2) { | } else if (opcode == OP_PUSHDATA2) { | ||||
if (end() - pc < 2) return false; | if (end() - pc < 2) return false; | ||||
nSize = ReadLE16(&pc[0]); | nSize = ReadLE16(&pc[0]); | ||||
pc += 2; | pc += 2; | ||||
} else if (opcode == OP_PUSHDATA4) { | } else if (opcode == OP_PUSHDATA4) { | ||||
if (end() - pc < 4) return false; | if (end() - pc < 4) return false; | ||||
nSize = ReadLE32(&pc[0]); | nSize = ReadLE32(&pc[0]); | ||||
pc += 4; | pc += 4; | ||||
} | } | ||||
if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize) | if (end() - pc < 0 || uint32_t(end() - pc) < nSize) { | ||||
return false; | return false; | ||||
} | |||||
if (pvchRet) pvchRet->assign(pc, pc + nSize); | if (pvchRet) pvchRet->assign(pc, pc + nSize); | ||||
pc += nSize; | pc += nSize; | ||||
} | } | ||||
opcodeRet = (opcodetype)opcode; | opcodeRet = (opcodetype)opcode; | ||||
return true; | return true; | ||||
} | } | ||||
/** Encode/decode small integers: */ | /** Encode/decode small integers: */ | ||||
static int DecodeOP_N(opcodetype opcode) { | static int DecodeOP_N(opcodetype opcode) { | ||||
if (opcode == OP_0) return 0; | if (opcode == OP_0) { | ||||
return 0; | |||||
} | |||||
assert(opcode >= OP_1 && opcode <= OP_16); | assert(opcode >= OP_1 && opcode <= OP_16); | ||||
return (int)opcode - (int)(OP_1 - 1); | return int(opcode) - int(OP_1 - 1); | ||||
} | } | ||||
static opcodetype EncodeOP_N(int n) { | static opcodetype EncodeOP_N(int n) { | ||||
assert(n >= 0 && n <= 16); | assert(n >= 0 && n <= 16); | ||||
if (n == 0) return OP_0; | if (n == 0) { | ||||
return OP_0; | |||||
} | |||||
return (opcodetype)(OP_1 + n - 1); | return (opcodetype)(OP_1 + n - 1); | ||||
} | } | ||||
int FindAndDelete(const CScript &b) { | int FindAndDelete(const CScript &b) { | ||||
int nFound = 0; | int nFound = 0; | ||||
if (b.empty()) return nFound; | if (b.empty()) { | ||||
return nFound; | |||||
} | |||||
CScript result; | CScript result; | ||||
iterator pc = begin(), pc2 = begin(); | iterator pc = begin(), pc2 = begin(); | ||||
opcodetype opcode; | opcodetype opcode; | ||||
do { | do { | ||||
result.insert(result.end(), pc2, pc); | result.insert(result.end(), pc2, pc); | ||||
while (static_cast<size_t>(end() - pc) >= b.size() && | while (size_t(end() - pc) >= b.size() && | ||||
std::equal(b.begin(), b.end(), pc)) { | std::equal(b.begin(), b.end(), pc)) { | ||||
pc = pc + b.size(); | pc = pc + b.size(); | ||||
++nFound; | ++nFound; | ||||
} | } | ||||
pc2 = pc; | pc2 = pc; | ||||
} while (GetOp(pc, opcode)); | } while (GetOp(pc, opcode)); | ||||
if (nFound > 0) { | if (nFound > 0) { | ||||
result.insert(result.end(), pc2, end()); | result.insert(result.end(), pc2, end()); | ||||
*this = result; | *this = result; | ||||
} | } | ||||
return nFound; | return nFound; | ||||
} | } | ||||
int Find(opcodetype op) const { | int Find(opcodetype op) const { | ||||
int nFound = 0; | int nFound = 0; | ||||
opcodetype opcode; | opcodetype opcode; | ||||
for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);) | for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);) { | ||||
if (opcode == op) ++nFound; | if (opcode == op) { | ||||
++nFound; | |||||
} | |||||
} | |||||
return nFound; | return nFound; | ||||
} | } | ||||
/** | /** | ||||
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs as 20 sigops. With | * Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs as 20 sigops. With | ||||
* pay-to-script-hash, that changed: CHECKMULTISIGs serialized in scriptSigs | * pay-to-script-hash, that changed: CHECKMULTISIGs serialized in scriptSigs | ||||
* are counted more accurately, assuming they are of the form | * are counted more accurately, assuming they are of the form | ||||
* ... OP_N CHECKMULTISIG ... | * ... OP_N CHECKMULTISIG ... | ||||
*/ | */ | ||||
unsigned int GetSigOpCount(bool fAccurate) const; | unsigned int GetSigOpCount(bool fAccurate) const; | ||||
/** | /** | ||||
* Accurately count sigOps, including sigOps in pay-to-script-hash | * Accurately count sigOps, including sigOps in pay-to-script-hash | ||||
* transactions: | * transactions: | ||||
*/ | */ | ||||
unsigned int GetSigOpCount(const CScript &scriptSig) const; | unsigned int GetSigOpCount(const CScript &scriptSig) const; | ||||
bool IsPayToScriptHash() const; | bool IsPayToScriptHash() const; | ||||
bool IsCommitment(const std::vector<uint8_t> &data) const; | bool IsCommitment(const std::vector<uint8_t> &data) const; | ||||
bool IsWitnessProgram(int &version, std::vector<uint8_t> &program) const; | bool IsWitnessProgram(int &version, std::vector<uint8_t> &program) const; | ||||
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it | /** | ||||
* consensus-critical). */ | * Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it | ||||
* consensus-critical). | |||||
*/ | |||||
bool IsPushOnly(const_iterator pc) const; | bool IsPushOnly(const_iterator pc) const; | ||||
bool IsPushOnly() const; | bool IsPushOnly() const; | ||||
/** | /** | ||||
* Returns whether the script is guaranteed to fail at execution, regardless | * Returns whether the script is guaranteed to fail at execution, regardless | ||||
* of the initial stack. This allows outputs to be pruned instantly when | * of the initial stack. This allows outputs to be pruned instantly when | ||||
* entering the UTXO set. | * entering the UTXO set. | ||||
*/ | */ | ||||
Show All 20 Lines |