case TX_PUBKEYHASH: return "pubkeyhash";
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
+ case TX_NULL_DATA: return "nulldata";
}
return NULL;
}
// Sender provides N pubkeys, receivers provides M signatures
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
+
+ // Empty, provably prunable, data-carrying output
+ mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
}
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
else
break;
}
+ else if (opcode2 == OP_SMALLDATA)
+ {
+ // small pushdata, <= 80 bytes
+ if (vch1.size() > 80)
+ break;
+ }
else if (opcode1 != opcode2 || vch1 != vch2)
{
// Others must match exactly
switch (whichTypeRet)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
{
case TX_NONSTANDARD:
return -1;
+ case TX_NULL_DATA:
+ return 1;
case TX_PUBKEY:
return 1;
case TX_PUBKEYHASH:
return -1;
}
-bool IsStandard(const CScript& scriptPubKey)
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
vector<valtype> vSolutions;
- txnouttype whichType;
if (!Solver(scriptPubKey, whichType, vSolutions))
return false;
switch (whichType)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
vector<valtype> vSolutions;
if (!Solver(scriptPubKey, typeRet, vSolutions))
return false;
+ if (typeRet == TX_NULL_DATA)
+ return true;
if (typeRet == TX_MULTISIG)
{
switch (txType)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
// Don't know anything about this, assume bigger one is correct:
if (sigs1.size() >= sigs2.size())
return PushAll(sigs1);
this->at(22) == OP_EQUAL);
}
+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: