mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Add HasCanonicalPushes(), and use it in IsStandardTx
This commit is contained in:
parent
9aea601b05
commit
87fe71e1fc
4 changed files with 53 additions and 1 deletions
|
@ -442,6 +442,10 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
|||
reason = "scriptsig-not-pushonly";
|
||||
return false;
|
||||
}
|
||||
if (!txin.scriptSig.HasCanonicalPushes()) {
|
||||
reason = "non-canonical-push";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int nDataOut = 0;
|
||||
|
|
|
@ -1881,6 +1881,33 @@ bool CScript::IsPushOnly() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CScript::HasCanonicalPushes() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
while (pc < end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
std::vector<unsigned char> data;
|
||||
if (!GetOp(pc, opcode, data))
|
||||
return false;
|
||||
if (opcode > OP_16)
|
||||
continue;
|
||||
if (opcode < OP_PUSHDATA1 && opcode > OP_0 && (data.size() == 1 && data[0] <= 16))
|
||||
// Could have used an OP_n code, rather than a 1-byte push.
|
||||
return false;
|
||||
if (opcode == OP_PUSHDATA1 && data.size() < OP_PUSHDATA1)
|
||||
// Could have used a normal n-byte push, rather than OP_PUSHDATA1.
|
||||
return false;
|
||||
if (opcode == OP_PUSHDATA2 && data.size() <= 0xFF)
|
||||
// Could have used an OP_PUSHDATA1.
|
||||
return false;
|
||||
if (opcode == OP_PUSHDATA4 && data.size() <= 0xFFFF)
|
||||
// Could have used an OP_PUSHDATA2.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class CScriptVisitor : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -541,9 +541,12 @@ public:
|
|||
|
||||
bool IsPayToScriptHash() const;
|
||||
|
||||
// Called by IsStandardTx
|
||||
// Called by IsStandardTx and P2SH VerifyScript (which makes it consensus-critical).
|
||||
bool IsPushOnly() const;
|
||||
|
||||
// Called by IsStandardTx.
|
||||
bool HasCanonicalPushes() const;
|
||||
|
||||
// Returns whether the script is guaranteed to fail at execution,
|
||||
// regardless of the initial stack. This allows outputs to be pruned
|
||||
// instantly when entering the UTXO set.
|
||||
|
|
|
@ -438,4 +438,22 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||
BOOST_CHECK(combined == partial3c);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_push)
|
||||
{
|
||||
for (int i=0; i<1000; i++) {
|
||||
CScript script;
|
||||
script << i;
|
||||
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
|
||||
BOOST_CHECK_MESSAGE(script.HasCanonicalPushes(), "Number " << i << " push is not canonical.");
|
||||
}
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
std::vector<unsigned char> data(i, '\111');
|
||||
CScript script;
|
||||
script << data;
|
||||
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
|
||||
BOOST_CHECK_MESSAGE(script.HasCanonicalPushes(), "Length " << i << " push is not canonical.");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in a new issue