{
case TX_NONSTANDARD: return "nonstandard";
case TX_PUBKEY: return "pubkey";
+ case TX_PUBKEY_DROP: return "pubkeydrop";
case TX_PUBKEYHASH: return "pubkeyhash";
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
if (5 + nLenR >= vchSig.size())
return error("Non-canonical signature: S length misplaced");
unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR + nLenS + (fWithHashType ? 7 : 6)) != vchSig.size())
+ if ((nLenR + nLenS + (fWithHashType ? 7 : 6)) != vchSig.size())
return error("Non-canonical signature: R+S length mismatch");
const unsigned char *R = &vchSig[4];
if (!(flags & SCRIPT_VERIFY_STRICTENC))
return true;
- return IsDERSignature(vchSig, true, flags & SCRIPT_VERIFY_LOW_S);
+ return IsDERSignature(vchSig, true, (flags & SCRIPT_VERIFY_LOW_S) != 0);
}
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType)
// Standard tx, sender provides pubkey, receiver adds signature
mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
+ if (fTestNet || GetTime() > SMALLDATA_SWITCH_TIME)
+ {
+ // Malleable pubkey tx hack, sender provides generated pubkey combined with R parameter. The R parameter is dropped before checking a signature.
+ mTemplates.insert(make_pair(TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG));
+ }
+
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
}
else if (opcode2 == OP_SMALLDATA)
{
- // small pushdata, <= 80 bytes
- if (vch1.size() > 80)
+ // small pushdata, <= 1024 bytes
+ if (vch1.size() > (GetTime() > SMALLDATA_SWITCH_TIME ? 1024 : 80))
break;
}
else if (opcode1 != opcode2 || vch1 != vch2)
}
-bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool Sign1(const CKeyID& address, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet)
{
CKey key;
if (!keystore.GetKey(address, key))
return true;
}
-bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool SignR(const CPubKey& pubKey, const CPubKey& R, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet)
+{
+ CKey key;
+ if (!keystore.CreatePrivKey(pubKey, R, key))
+ return false;
+
+ vector<unsigned char> vchSig;
+ if (!key.Sign(hash, vchSig))
+ return false;
+ vchSig.push_back((unsigned char)nHashType);
+ scriptSigRet << vchSig;
+
+ return true;
+}
+
+bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet)
{
int nSigned = 0;
int nRequired = multisigdata.front()[0];
// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
// Returns false if scriptPubKey could not be completely satisfied.
//
-bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType,
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, const uint256& hash, int nHashType,
CScript& scriptSigRet, txnouttype& whichTypeRet)
{
scriptSigRet.clear();
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
return Sign1(keyID, keystore, hash, nHashType, scriptSigRet);
+ case TX_PUBKEY_DROP:
+ {
+ CPubKey key = CPubKey(vSolutions[0]);
+ CPubKey R = CPubKey(vSolutions[1]);
+ return SignR(key, R, keystore, hash, nHashType, scriptSigRet);
+ }
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
case TX_NULL_DATA:
return 1;
case TX_PUBKEY:
+ case TX_PUBKEY_DROP:
return 1;
case TX_PUBKEYHASH:
return 2;
if (keystore.HaveKey(keyID))
return MINE_SPENDABLE;
break;
+ case TX_PUBKEY_DROP:
+ {
+ CPubKey key = CPubKey(vSolutions[0]);
+ CPubKey R = CPubKey(vSolutions[1]);
+ if (keystore.CheckOwnership(key, R))
+ return MINE_SPENDABLE;
+ }
+ break;
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
if (keystore.HaveKey(keyID))
class CAffectedKeysVisitor : public boost::static_visitor<void> {
private:
const CKeyStore &keystore;
+ CAffectedKeysVisitor& operator=(CAffectedKeysVisitor const&);
std::vector<CKeyID> &vKeys;
public:
if (!Solver(scriptPubKey, typeRet, vSolutions))
return false;
if (typeRet == TX_NULL_DATA)
+ {
+ nRequiredRet = 0;
return true;
+ }
if (typeRet == TX_MULTISIG)
{
else
{
nRequiredRet = 1;
+ if (typeRet == TX_PUBKEY_DROP)
+ return true;
CTxDestination address;
if (!ExtractDestination(scriptPubKey, address))
return false;
return result;
}
-static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
{
return result;
}
-static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const txnouttype txType, const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
{
return PushAll(sigs1);
return PushAll(sigs2);
case TX_PUBKEY:
+ case TX_PUBKEY_DROP:
case TX_PUBKEYHASH:
// Signatures are bigger than placeholders or empty scripts:
if (sigs1.empty() || sigs1[0].empty())
return CScript();
}
-CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const CScript& scriptSig1, const CScript& scriptSig2)
{
txnouttype txType;
boost::apply_visitor(CScriptVisitor(this), dest);
}
+void CScript::SetDestination(const CPubKey& R, CPubKey& pubKeyVariant)
+{
+ this->clear();
+ *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG;
+}
+
+
void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
{
this->clear();