mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Merge pull request #3025 from sipa/noncanpush
Make signatures with non-canonical data pushes non-standard.
This commit is contained in:
commit
2bc52f1c4a
4 changed files with 72 additions and 18 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;
|
||||
|
|
|
@ -1863,6 +1863,51 @@ bool CScript::IsPayToScriptHash() const
|
|||
this->at(22) == OP_EQUAL);
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
while (pc < end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
if (!GetOp(pc, opcode))
|
||||
return false;
|
||||
// Note that IsPushOnly() *does* consider OP_RESERVED to be a
|
||||
// push-type opcode, however execution of OP_RESERVED fails, so
|
||||
// it's not relevant to P2SH as the scriptSig would fail prior to
|
||||
// the P2SH special validation code being executed.
|
||||
if (opcode > OP_16)
|
||||
return false;
|
||||
}
|
||||
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:
|
||||
|
|
23
src/script.h
23
src/script.h
|
@ -541,24 +541,11 @@ public:
|
|||
|
||||
bool IsPayToScriptHash() const;
|
||||
|
||||
// Called by IsStandardTx
|
||||
bool IsPushOnly() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
while (pc < end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
if (!GetOp(pc, opcode))
|
||||
return false;
|
||||
// Note that IsPushOnly() *does* consider OP_RESERVED to be a
|
||||
// push-type opcode, however execution of OP_RESERVED fails, so
|
||||
// it's not relevant to P2SH as the scriptSig would fail prior to
|
||||
// the P2SH special validation code being executed.
|
||||
if (opcode > OP_16)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 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
|
||||
|
|
|
@ -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