mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-14 04:00:41 +02:00
[MOVEONLY] Move CSCript::FindAndDelete to interpreter
This commit is contained in:
parent
33a8ecfbce
commit
6a7456ad60
@ -250,6 +250,34 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FindAndDelete(CScript& script, const CScript& b)
|
||||||
|
{
|
||||||
|
int nFound = 0;
|
||||||
|
if (b.empty())
|
||||||
|
return nFound;
|
||||||
|
CScript result;
|
||||||
|
CScript::const_iterator pc = script.begin(), pc2 = script.begin(), end = script.end();
|
||||||
|
opcodetype opcode;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result.insert(result.end(), pc2, pc);
|
||||||
|
while (static_cast<size_t>(end - pc) >= b.size() && std::equal(b.begin(), b.end(), pc))
|
||||||
|
{
|
||||||
|
pc = pc + b.size();
|
||||||
|
++nFound;
|
||||||
|
}
|
||||||
|
pc2 = pc;
|
||||||
|
}
|
||||||
|
while (script.GetOp(pc, opcode));
|
||||||
|
|
||||||
|
if (nFound > 0) {
|
||||||
|
result.insert(result.end(), pc2, end);
|
||||||
|
script = std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nFound;
|
||||||
|
}
|
||||||
|
|
||||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
|
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
|
||||||
{
|
{
|
||||||
static const CScriptNum bnZero(0);
|
static const CScriptNum bnZero(0);
|
||||||
@ -891,7 +919,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
|
|
||||||
// Drop the signature in pre-segwit scripts but not segwit scripts
|
// Drop the signature in pre-segwit scripts but not segwit scripts
|
||||||
if (sigversion == SigVersion::BASE) {
|
if (sigversion == SigVersion::BASE) {
|
||||||
scriptCode.FindAndDelete(CScript(vchSig));
|
FindAndDelete(scriptCode, CScript(vchSig));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
|
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
|
||||||
@ -955,7 +983,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
{
|
{
|
||||||
valtype& vchSig = stacktop(-isig-k);
|
valtype& vchSig = stacktop(-isig-k);
|
||||||
if (sigversion == SigVersion::BASE) {
|
if (sigversion == SigVersion::BASE) {
|
||||||
scriptCode.FindAndDelete(CScript(vchSig));
|
FindAndDelete(scriptCode, CScript(vchSig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,4 +189,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
|
|||||||
|
|
||||||
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
|
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
|
||||||
|
|
||||||
|
int FindAndDelete(CScript& script, const CScript& b);
|
||||||
|
|
||||||
#endif // BITCOIN_SCRIPT_INTERPRETER_H
|
#endif // BITCOIN_SCRIPT_INTERPRETER_H
|
||||||
|
@ -571,34 +571,6 @@ public:
|
|||||||
return (opcodetype)(OP_1+n-1);
|
return (opcodetype)(OP_1+n-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FindAndDelete(const CScript& b)
|
|
||||||
{
|
|
||||||
int nFound = 0;
|
|
||||||
if (b.empty())
|
|
||||||
return nFound;
|
|
||||||
CScript result;
|
|
||||||
const_iterator pc = begin(), pc2 = begin(), end = this->end();
|
|
||||||
opcodetype opcode;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
result.insert(result.end(), pc2, pc);
|
|
||||||
while (static_cast<size_t>(end - pc) >= b.size() && std::equal(b.begin(), b.end(), pc))
|
|
||||||
{
|
|
||||||
pc = pc + b.size();
|
|
||||||
++nFound;
|
|
||||||
}
|
|
||||||
pc2 = pc;
|
|
||||||
}
|
|
||||||
while (GetOp(pc, opcode));
|
|
||||||
|
|
||||||
if (nFound > 0) {
|
|
||||||
result.insert(result.end(), pc2, end);
|
|
||||||
*this = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
|
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
|
||||||
* as 20 sigops. With pay-to-script-hash, that changed:
|
* as 20 sigops. With pay-to-script-hash, that changed:
|
||||||
|
@ -1349,43 +1349,43 @@ BOOST_AUTO_TEST_CASE(script_FindAndDelete)
|
|||||||
s = CScript() << OP_1 << OP_2;
|
s = CScript() << OP_1 << OP_2;
|
||||||
d = CScript(); // delete nothing should be a no-op
|
d = CScript(); // delete nothing should be a no-op
|
||||||
expect = s;
|
expect = s;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = CScript() << OP_1 << OP_2 << OP_3;
|
s = CScript() << OP_1 << OP_2 << OP_3;
|
||||||
d = CScript() << OP_2;
|
d = CScript() << OP_2;
|
||||||
expect = CScript() << OP_1 << OP_3;
|
expect = CScript() << OP_1 << OP_3;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3;
|
s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3;
|
||||||
d = CScript() << OP_3;
|
d = CScript() << OP_3;
|
||||||
expect = CScript() << OP_1 << OP_4;
|
expect = CScript() << OP_1 << OP_4;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 4);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 4);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("0302ff03"); // PUSH 0x02ff03 onto stack
|
s = ScriptFromHex("0302ff03"); // PUSH 0x02ff03 onto stack
|
||||||
d = ScriptFromHex("0302ff03");
|
d = ScriptFromHex("0302ff03");
|
||||||
expect = CScript();
|
expect = CScript();
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("0302ff030302ff03"); // PUSH 0x2ff03 PUSH 0x2ff03
|
s = ScriptFromHex("0302ff030302ff03"); // PUSH 0x2ff03 PUSH 0x2ff03
|
||||||
d = ScriptFromHex("0302ff03");
|
d = ScriptFromHex("0302ff03");
|
||||||
expect = CScript();
|
expect = CScript();
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("0302ff030302ff03");
|
s = ScriptFromHex("0302ff030302ff03");
|
||||||
d = ScriptFromHex("02");
|
d = ScriptFromHex("02");
|
||||||
expect = s; // FindAndDelete matches entire opcodes
|
expect = s; // FindAndDelete matches entire opcodes
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("0302ff030302ff03");
|
s = ScriptFromHex("0302ff030302ff03");
|
||||||
d = ScriptFromHex("ff");
|
d = ScriptFromHex("ff");
|
||||||
expect = s;
|
expect = s;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
// This is an odd edge case: strip of the push-three-bytes
|
// This is an odd edge case: strip of the push-three-bytes
|
||||||
@ -1393,44 +1393,44 @@ BOOST_AUTO_TEST_CASE(script_FindAndDelete)
|
|||||||
s = ScriptFromHex("0302ff030302ff03");
|
s = ScriptFromHex("0302ff030302ff03");
|
||||||
d = ScriptFromHex("03");
|
d = ScriptFromHex("03");
|
||||||
expect = CScript() << ParseHex("ff03") << ParseHex("ff03");
|
expect = CScript() << ParseHex("ff03") << ParseHex("ff03");
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
// Byte sequence that spans multiple opcodes:
|
// Byte sequence that spans multiple opcodes:
|
||||||
s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
|
s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
|
||||||
d = ScriptFromHex("feed51");
|
d = ScriptFromHex("feed51");
|
||||||
expect = s;
|
expect = s;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); // doesn't match 'inside' opcodes
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); // doesn't match 'inside' opcodes
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
|
s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
|
||||||
d = ScriptFromHex("02feed51");
|
d = ScriptFromHex("02feed51");
|
||||||
expect = ScriptFromHex("69");
|
expect = ScriptFromHex("69");
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("516902feed5169");
|
s = ScriptFromHex("516902feed5169");
|
||||||
d = ScriptFromHex("feed51");
|
d = ScriptFromHex("feed51");
|
||||||
expect = s;
|
expect = s;
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("516902feed5169");
|
s = ScriptFromHex("516902feed5169");
|
||||||
d = ScriptFromHex("02feed51");
|
d = ScriptFromHex("02feed51");
|
||||||
expect = ScriptFromHex("516969");
|
expect = ScriptFromHex("516969");
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = CScript() << OP_0 << OP_0 << OP_1 << OP_1;
|
s = CScript() << OP_0 << OP_0 << OP_1 << OP_1;
|
||||||
d = CScript() << OP_0 << OP_1;
|
d = CScript() << OP_0 << OP_1;
|
||||||
expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
|
expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1;
|
s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1;
|
||||||
d = CScript() << OP_0 << OP_1;
|
d = CScript() << OP_0 << OP_1;
|
||||||
expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
|
expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
// Another weird edge case:
|
// Another weird edge case:
|
||||||
@ -1438,13 +1438,13 @@ BOOST_AUTO_TEST_CASE(script_FindAndDelete)
|
|||||||
s = ScriptFromHex("0003feed");
|
s = ScriptFromHex("0003feed");
|
||||||
d = ScriptFromHex("03feed"); // ... can remove the invalid push
|
d = ScriptFromHex("03feed"); // ... can remove the invalid push
|
||||||
expect = ScriptFromHex("00");
|
expect = ScriptFromHex("00");
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
|
|
||||||
s = ScriptFromHex("0003feed");
|
s = ScriptFromHex("0003feed");
|
||||||
d = ScriptFromHex("00");
|
d = ScriptFromHex("00");
|
||||||
expect = ScriptFromHex("03feed");
|
expect = ScriptFromHex("03feed");
|
||||||
BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1);
|
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
|
||||||
BOOST_CHECK(s == expect);
|
BOOST_CHECK(s == expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
|
|||||||
|
|
||||||
// In case concatenating two scripts ends up with two codeseparators,
|
// In case concatenating two scripts ends up with two codeseparators,
|
||||||
// or an extra one at the end, this prevents all those possible incompatibilities.
|
// or an extra one at the end, this prevents all those possible incompatibilities.
|
||||||
scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
|
FindAndDelete(scriptCode, CScript(OP_CODESEPARATOR));
|
||||||
|
|
||||||
// Blank out other inputs' signatures
|
// Blank out other inputs' signatures
|
||||||
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
|
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user