// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#include "script/sign.h"
#include "cc/CCinclude.h"
#include "cc/eval.h"
#include "key_io.h"
+#include "pbaas/identity.h"
#include <boost/foreach.hpp>
typedef std::vector<unsigned char> valtype;
-TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
+TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const CScript &scriptPubKey, uint32_t spendHeight, int nHashTypeIn)
+ : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn, &scriptPubKey, keystoreIn, spendHeight) {}
-bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId, CKey *pprivKey, void *extraData) const
+TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn)
+ : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
+
+bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char> &vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId, CKey *pprivKey, void *extraData) const
{
CKey key;
if (pprivKey)
return false;
}
- if (scriptCode.IsPayToCryptoCondition())
+ COptCCParams p;
+ if (scriptCode.IsPayToCryptoCondition(p))
{
- CC *cc = (CC *)extraData;
- // assume either 1of1 or 1of2. if the condition created by the
- if (!cc || cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()) == 0)
- return false;
- vchSig = CCSigVec(cc);
+ if (p.IsValid() && p.version >= p.VERSION_V3)
+ {
+ CSmartTransactionSignatures signatures(nHashType, std::map<uint160, CSmartTransactionSignature>());
+ if (vchSig.size())
+ {
+ signatures = CSmartTransactionSignatures(vchSig);
+ if (!signatures.IsValid())
+ {
+ return false;
+ }
+ }
+ unsigned char *onesig;
+ if (!cc_MakeSecp256k1Signature(hash.begin(), key.begin(), &onesig))
+ {
+ return false;
+ }
+ CSmartTransactionSignature signature(CSmartTransactionSignature::SIGTYPE_SECP256K1, key.GetPubKey(), std::vector<unsigned char>(onesig, onesig + CSmartTransactionSignature::SIGTYPE_SECP256K1_LEN));
+ free(onesig);
+ signatures.AddSignature(signature);
+ vchSig = signatures.AsVector();
+
+
+ /*
+ printf("signatures: %s\n", signatures.ToUniValue().write().c_str());
+ CC *cc = (CC *)extraData;
+ if (!cc || cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()) == 0)
+ return false;
+ char *jsonCondStr = cc_conditionToJSONString(cc);
+ if (jsonCondStr)
+ {
+ printf("Signed condition: %s\n", jsonCondStr);
+ cJSON_free(jsonCondStr);
+ }
+ */
+ }
+ else
+ {
+ CC *cc = (CC *)extraData;
+
+ if (!cc || cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()) == 0)
+ return false;
+ vchSig = CCSigVec(cc);
+ }
return true;
}
else
return CCNewThreshold(2, {condCC, Sig});
}
-CScript _CCPubKey(const CC *cond)
+CC *CCcond1(uint8_t evalcode, CTxDestination dest)
{
- unsigned char buf[1000];
- size_t len = cc_conditionBinary(cond, buf);
- return CScript() << std::vector<unsigned char>(buf, buf+len) << OP_CHECKCRYPTOCONDITION;
+ CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest);
+ std::vector<CC*> pks;
+ if (pk.IsValid())
+ {
+ pks.push_back(CCNewSecp256k1(pk));
+ }
+ else
+ {
+ pks.push_back(CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest))));
+ }
+ CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
+ CC *Sig = CCNewThreshold(1, pks);
+ return CCNewThreshold(2, {condCC, Sig});
}
-static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scriptPubKey, vector<valtype> &vSolutions,
- vector<valtype>& ret, uint32_t consensusBranchId)
+CC *CCcondAny(uint8_t evalcode, std::vector<CTxDestination> dests)
{
- CScript subScript;
- vector<CTxDestination> vPK;
- vector<valtype> vParams = vector<valtype>();
- COptCCParams p;
+ std::vector<CC*> pks;
+ for (auto dest : dests)
+ {
+ CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest);
+ if (pk.IsValid())
+ {
+ pks.push_back(CCNewSecp256k1(pk));
+ }
+ else
+ {
+ pks.push_back(CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest))));
+ }
+ }
- // get information to sign with
- CCcontract_info C;
+ CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
+ CC *Sig = CCNewThreshold(1, pks);
+ return CCNewThreshold(2, {condCC, Sig});
+}
- scriptPubKey.IsPayToCryptoCondition(&subScript, vParams);
- if (vParams.empty())
+CC *MakeCCcondMofN(uint8_t evalcode, const std::vector<CTxDestination> &dests, int M)
+{
+ std::vector<CC*> pks;
+ for (auto dest : dests)
{
- uint32_t ecode;
- scriptPubKey.IsPayToCryptoCondition(&ecode);
-
- // use the cryptocondition's pubkey, we have nothing else
- if (CCinit(&C, p.evalCode))
+ CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest);
+ if (pk.IsValid())
{
- vPK.push_back(CTxDestination(CPubKey(ParseHex(C.CChexstr))));
- p = COptCCParams(p.VERSION_V1, C.evalcode, 1, 1, vPK, vParams);
+ pks.push_back(CCNewSecp256k1(pk));
}
+ else
+ {
+ pks.push_back(CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest))));
+ }
+ }
+
+ if (M > pks.size())
+ {
+ M = pks.size();
+ }
+
+ CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
+ CC *Sig = CCNewThreshold(M, pks);
+ return CCNewThreshold(2, {condCC, Sig});
+}
+
+CC *MakeCCcondOneSig(const CTxDestination &dest)
+{
+ //printf("making condition with ID: %s\n", GetDestinationID(dest).GetHex().c_str());
+
+ CPubKey pk = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest);
+ if (pk.IsValid())
+ {
+ return CCNewSecp256k1(pk);
}
else
{
- p = COptCCParams(vParams[0]);
+ return CCNewHashedSecp256k1(CKeyID(GetDestinationID(dest)));
+ }
+}
+
+CC *MakeCCcondMofN(const std::vector<CTxDestination> &dests, int M)
+{
+ std::vector<CC*> pks;
+ for (auto dest : dests)
+ {
+ pks.push_back(MakeCCcondOneSig(dest));
+ if (!pks.back())
+ {
+ pks.pop_back();
+ }
+ }
+
+ if (M > pks.size())
+ {
+ M = pks.size();
+ }
+ return CCNewThreshold(M, pks);
+}
+
+CC *MakeCCcondMofN(const std::vector<CC*> &conditions, int M)
+{
+ if (M > conditions.size())
+ {
+ M = conditions.size();
+ }
+
+ return CCNewThreshold(M, conditions);
+}
+
+CC *MakeCCcondMofN(uint8_t evalcode, const std::vector<CC*> &conditions, int M)
+{
+ if (evalcode == EVAL_NONE)
+ {
+ return MakeCCcondMofN(conditions, M);
+ }
+
+ if (M > conditions.size())
+ {
+ M = conditions.size();
}
- if (p.IsValid() && p.vKeys.size() >= p.n)
+ CC *condCC = CCNewEval(E_MARSHAL(ss << evalcode));
+ CC *Sig = CCNewThreshold(M, conditions);
+ return CCNewThreshold(2, {condCC, Sig});
+}
+
+// TOBJ is CConditionObj of a CC output type
+template <typename TOBJ>
+CC *MakeMofNCC(TOBJ &conditionObj)
+{
+ return MakeCCcondMofN(conditionObj.evalCode, conditionObj.dests, conditionObj.m);
+}
+
+template <typename TOBJ1, typename TOBJ2>
+CC *MakeMofNCC(int M, TOBJ1 &condition1, TOBJ2 &condition2)
+{
+ if (M > 2) M = 2;
+ std::vector<CC*> conditions({MakeCCcondMofN(condition1.evalCode, condition1.dests, condition1.m), MakeCCcondMofN(condition2.evalCode, condition2.dests, condition2.m)});
+ return CCNewThreshold(M, conditions);
+}
+
+template <typename TOBJ1, typename TOBJ2, typename TOBJ3>
+CC *MakeMofNCC(int M, TOBJ1 &condition1, TOBJ2 &condition2, TOBJ3 &condition3)
+{
+ if (M > 3) M = 3;
+ std::vector<CC*> conditions({MakeCCcondMofN(condition1.evalCode, condition1.dests, condition1.m), MakeCCcondMofN(condition2.evalCode, condition2.dests, condition2.m), MakeCCcondMofN(condition3.evalCode, condition3.dests, condition3.m)});
+ return CCNewThreshold(M, conditions);
+}
+
+template <typename TOBJ1, typename TOBJ2, typename TOBJ3, typename TOBJ4>
+CC *MakeMofNCC(int M, TOBJ1 &condition1, TOBJ2 &condition2, TOBJ3 &condition3, TOBJ4 &condition4)
+{
+ if (M > 4) M = 4;
+ std::vector<CC*> conditions({MakeCCcondMofN(condition1.evalCode, condition1.dests, condition1.m),
+ MakeCCcondMofN(condition2.evalCode, condition2.dests, condition2.m),
+ MakeCCcondMofN(condition3.evalCode, condition3.dests, condition3.m),
+ MakeCCcondMofN(condition4.evalCode, condition4.dests, condition4.m)});
+ return CCNewThreshold(M, conditions);
+}
+
+CScript _CCPubKey(const CC *cond)
+{
+ unsigned char buf[2000];
+ size_t len = cc_conditionBinary(cond, buf, 2000);
+ return CScript() << std::vector<unsigned char>(buf, buf+len) << OP_CHECKCRYPTOCONDITION;
+}
+
+CIdentity LookupIdentity(const BaseSignatureCreator& creator, const CIdentityID &idID)
+{
+ std::pair<CIdentityMapKey, CIdentityMapValue> identity;
+ COptCCParams p;
+ //printf("Looking up %s identity\n", EncodeDestination(CTxDestination(idID)).c_str());
+ if (creator.IsKeystoreValid() &&
+ creator.KeyStore().GetIdentity(idID, identity) &&
+ identity.second.IsValidUnrevoked())
{
- bool is1of2 = (p.m == 1 && p.n == 2);
- CKey privKey;
+ return identity.second;
+ }
+ return CIdentity();
+}
- // must be a valid cc eval code
- if (CCinit(&C, p.evalCode))
+static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scriptPubKey, vector<valtype> &vSolutions,
+ vector<valtype>& ret, uint32_t consensusBranchId)
+{
+ CScript subScript;
+ std::vector<CTxDestination> vPK;
+ std::vector<valtype> vParams = std::vector<valtype>();
+ COptCCParams p;
+
+ // get information to sign with
+ CCcontract_info C;
+
+ if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.n >= 1 && p.vKeys.size() >= p.n)
+ {
+ if (p.version >= p.VERSION_V3 && p.vData.size())
{
- // pay to cc address is a valid tx
- if (!is1of2)
+ // decode the entire crypto-condition
+ COptCCParams master = COptCCParams(p.vData.back());
+ bool ccValid = master.IsValid();
+ std::vector<CConditionObj<COptCCParams>> conditions;
+ std::map<uint160, CTxDestination> destMap; // all destinations
+ std::map<uint160, CKey> privKeyMap; // private keys located for each id
+ std::vector<CC*> ccs;
+
+ CIdentity identity;
+ bool identitySpend = false;
+ uint160 idID;
+ if (p.evalCode == EVAL_IDENTITY_PRIMARY)
{
- uint160 keyID = GetDestinationID(p.vKeys[0]);
- bool havePriv = creator.KeyStore().GetKey(keyID, privKey);
- CPubKey pubk;
+ identity = CIdentity(p.vData[0]);
+ identitySpend = identity.IsValid();
+ idID = identity.GetID();
+ }
- // if we don't have the private key, it must be the unspendable address
- if (havePriv)
+ // if we are sign-only, "p" will have no data object of its own, so we do not have to subtract 1
+ int loopMax = p.evalCode ? p.vData.size() - 1 : p.vData.size();
+
+ for (int i = 0; ccValid && i < loopMax; i++)
+ {
+ // "p", our first COptCCParams object will be considered first, then nested objects after
+ COptCCParams oneP = i ? COptCCParams(p.vData[i]) : p;
+ ccValid = oneP.IsValid();
+ std::vector<CC*> vCC;
+ if (ccValid)
{
- std::vector<unsigned char> vkch = GetDestinationBytes(p.vKeys[0]);
- if (vkch.size() == 33)
+ conditions.push_back(CConditionObj<COptCCParams>(oneP.evalCode, oneP.vKeys, oneP.m));
+
+ CCcontract_info C;
+ if (p.evalCode && CCinit(&C, p.evalCode))
{
- pubk = CPubKey(vkch);
+ CPubKey evalPK(ParseHex(C.CChexstr));
+ CKey priv;
+ std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
+ priv.Set(vch.begin(), vch.end(), true);
+ privKeyMap[evalPK.GetID()] = priv;
}
else
{
- creator.KeyStore().GetPubKey(keyID, pubk);
+ if (p.evalCode)
+ {
+ return false;
+ }
+ }
+
+ for (auto &dest : oneP.vKeys)
+ {
+ uint160 destId = GetDestinationID(dest);
+ if (dest.which() == COptCCParams::ADDRTYPE_ID)
+ {
+ // lookup identity, we must have all registered target identity scripts in our keystore, or we try as if they are a keyID, which will be the same
+ // if revoked or undefined
+ CIdentity id;
+
+ // if this is an identity self spend, we always use the absolute latest version to control it ,mcf
+ if (destId == idID)
+ {
+ id = identity;
+ }
+
+ if ((!id.IsValid() && !(id = LookupIdentity(creator, CIdentityID(destId))).IsValid()) || id.IsRevoked())
+ {
+ destMap[destId] = dest;
+ vCC.push_back(MakeCCcondOneSig(CKeyID(GetDestinationID(dest))));
+ }
+ else
+ {
+ for (auto oneKey : id.primaryAddresses)
+ {
+ destMap[GetDestinationID(oneKey)] = oneKey;
+ }
+ if (id.primaryAddresses.size() == 1)
+ {
+ vCC.push_back(MakeCCcondOneSig(CKeyID(GetDestinationID(id.primaryAddresses[0]))));
+ }
+ else
+ {
+ vCC.push_back(MakeCCcondMofN(id.primaryAddresses, id.minSigs));
+ }
+ }
+ }
+ else
+ {
+ destMap[destId] = dest;
+ vCC.push_back(MakeCCcondOneSig(dest));
+ }
}
- }
- else
- {
- privKey = CKey();
- std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
- privKey.Set(vch.begin(), vch.end(), true);
- pubk = CPubKey(ParseHex(C.CChexstr));
+ if (oneP.evalCode != EVAL_NONE)
+ {
+ ccs.push_back(MakeCCcondMofN(oneP.evalCode, vCC, oneP.m ? oneP.m : 1));
+ }
+ else
+ {
+ if (vCC.size() == 1)
+ {
+ ccs.push_back(vCC[0]);
+ }
+ else
+ {
+ ccs.push_back(MakeCCcondMofN(vCC, oneP.m));
+ }
+ }
}
+ }
- CC *cc = CCcond1(p.evalCode, pubk);
+ CC *outputCC = nullptr;
- if (cc)
+ if (ccValid)
+ {
+ assert(ccs.size() == conditions.size());
+ if (ccs.size() == 1)
{
- vector<unsigned char> vch;
- if (creator.CreateSig(vch, GetDestinationID(p.vKeys[0]), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
+ if (master.evalCode)
{
- ret.push_back(vch);
+ outputCC = MakeCCcondMofN(master.evalCode, ccs, master.m);
}
else
{
- fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", keyID.ToString().c_str());
+ outputCC = ccs[0];
+ }
+ }
+ else
+ {
+ if (master.evalCode)
+ {
+ outputCC = MakeCCcondMofN(master.evalCode, ccs, master.m);
+ }
+ else
+ {
+ outputCC = MakeCCcondMofN(ccs, master.m);
}
-
- cc_free(cc);
- return ret.size() != 0;
}
}
- else
+
+ // loop through all private keys we have and sign with each of them
+ if (outputCC)
{
- // first of priv key in our key store or contract address is what we sign with if we have it
- std::vector<CPubKey> keys;
- for (auto pk : p.vKeys)
+ // loop through keys and sign with all that we have
+ std::map<CKeyID, CKey> privKeys;
+ for (auto destPair : destMap)
{
- uint160 keyID = GetDestinationID(pk);
- std::vector<unsigned char> vkch = GetDestinationBytes(pk);
- if (vkch.size() == 33)
+ //printf("Checking for private key of destination: %s ", EncodeDestination(destPair.second).c_str());
+
+ CKey privKey;
+ auto dit = privKeyMap.find(destPair.first);
+ if (dit != privKeyMap.end())
{
- keys.push_back(CPubKey(vkch));
+ privKeys[dit->first] = dit->second;
+ //printf("...using key for crypto condition\n");
}
- else
+ else if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(destPair.first, privKey))
{
- return false;
+ privKeys[destPair.first] = privKey;
+ //printf("...using key from wallet\n");
}
}
- // if we only have one key, and this is version 2, add the cc pub key
- if (keys.size() == 1 && p.version == p.VERSION_V2)
+ vector<unsigned char> vch = ret.size() ? ret[0] : vector<unsigned char>();
+ bool error = false;
+ CScript signScript = _CCPubKey(outputCC);
+ // loop and sign
+ for (auto privKey : privKeys)
{
- keys.push_back(CPubKey(ParseHex(C.CChexstr)));
+ // if we have an error or can't sign and it isn't fulfilled, fail, if we have no error, can't sign again, and we have a fulfilled sig, it must be optimized and OK
+ if (error || (!creator.CreateSig(vch, privKey.first, scriptPubKey, consensusBranchId, &privKey.second, (void *)outputCC)))
+ {
+ error = true;
+ //CPubKey errKey = privKey.second.GetPubKey();
+ //fprintf(stderr,"vin has MofN CC signing error with pubkey: %s, ID: %s\n", HexBytes(&(std::vector<unsigned char>(errKey.begin(), errKey.end())[0]), errKey.size()).c_str(), errKey.GetID().GetHex().c_str());
+ }
}
- // we need two keys
- if (keys.size() < 2)
+ if (!error && vch.size())
{
- return false;
+ ret.push_back(vch);
}
- for (auto pk : keys)
+ cc_free(outputCC);
+ return !error && ret.size() != 0;
+ }
+ }
+ else
+ {
+ bool is0ofAny = (p.m == 0 && p.n >= 1);
+ bool is1ofn = (p.m == 1 && p.n >= 2);
+ CKey privKey;
+
+ // must be a valid cc eval code
+ if (CCinit(&C, p.evalCode))
+ {
+ // pay to cc address is a valid tx
+ if (is0ofAny)
{
- if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(pk.GetID(), privKey) && privKey.IsValid())
+ CPubKey pubk = CPubKey(ParseHex(C.CChexstr));
+ CKeyID keyID = pubk.GetID();
+ bool havePriv = false;
+
+ // loop through and sign with the first of either the private key or a match on the CCs private key, otherwise, fail
+ for (auto dest : p.vKeys)
+ {
+ uint160 keyID = GetDestinationID(dest);
+ if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(keyID, privKey))
+ {
+ havePriv = true;
+ break;
+ }
+ CPubKey tempPub = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest);
+ if ((tempPub.IsValid() && tempPub == pubk) || (keyID == tempPub.GetID()))
+ {
+ // found the pub key for this crypto condition, so use the private key
+ std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
+ privKey.Set(vch.begin(), vch.end(), true);
+ havePriv = true;
+ break;
+ }
+ }
+
+ if (!havePriv)
+ {
+ fprintf(stderr,"Do not have or cannot locate private key for %s\n", EncodeDestination(p.vKeys[0]).c_str());
+ return false;
+ }
+
+ CC *cc = CCcondAny(p.evalCode, p.vKeys);
+
+ if (cc)
{
- break;
+ vector<unsigned char> vch;
+ if (creator.CreateSig(vch, GetDestinationID(p.vKeys[0]), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
+ {
+ ret.push_back(vch);
+ }
+ else
+ {
+ fprintf(stderr,"vin has 1ofAny CC signing error with address.(%s)\n", EncodeDestination(p.vKeys[0]).c_str());
+ }
+
+ cc_free(cc);
+ return ret.size() != 0;
}
+ }
+ else if (!is1ofn)
+ {
+ uint160 keyID = GetDestinationID(p.vKeys[0]);
+ bool havePriv = creator.IsKeystoreValid() && creator.KeyStore().GetKey(keyID, privKey);
+ CPubKey pubk;
- if (pk == CPubKey(ParseHex(C.CChexstr)))
+ // if we don't have the private key, it must be the unspendable address
+ if (havePriv)
+ {
+ std::vector<unsigned char> vkch = GetDestinationBytes(p.vKeys[0]);
+ if (vkch.size() == 33)
+ {
+ pubk = CPubKey(vkch);
+ }
+ else
+ {
+ creator.KeyStore().GetPubKey(keyID, pubk);
+ }
+ }
+ else
{
privKey = CKey();
std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
+
privKey.Set(vch.begin(), vch.end(), true);
- break;
+ pubk = CPubKey(ParseHex(C.CChexstr));
+ }
+
+ CC *cc = CCcond1(p.evalCode, pubk);
+
+ if (cc)
+ {
+ vector<unsigned char> vch;
+ if (creator.CreateSig(vch, GetDestinationID(p.vKeys[0]), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
+ {
+ ret.push_back(vch);
+ }
+ else
+ {
+ fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", keyID.ToString().c_str());
+ }
+
+ cc_free(cc);
+ return ret.size() != 0;
}
}
+ else
+ {
+ // first of priv key in our key store or contract address is what we sign with if we have it
+ std::vector<CPubKey> keys;
+ for (auto pk : p.vKeys)
+ {
+ uint160 keyID = GetDestinationID(pk);
+ CPubKey foundKey;
+ if (!(creator.IsKeystoreValid() && creator.KeyStore().GetPubKey(keyID, foundKey)))
+ {
+ std::vector<unsigned char> vkch = GetDestinationBytes(pk);
+ if (vkch.size() == 33)
+ {
+ foundKey = CPubKey(vkch);
+ }
+ }
+
+ if (foundKey.IsFullyValid())
+ {
+ keys.push_back(foundKey);
+ }
+ }
- if (!privKey.IsValid())
- return false;
+ // if we only have one key, and this is version 2, add the cc pub key
+ if (keys.size() <= 1 && p.version == p.VERSION_V2)
+ {
+ keys.push_back(CPubKey(ParseHex(C.CChexstr)));
+ }
+
+ // we need something to sign with
+ if (!keys.size())
+ {
+ return false;
+ }
- CC *cc = CCcond1of2(p.evalCode, keys[0], keys[1]);
+ for (auto pk : keys)
+ {
+ if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(pk.GetID(), privKey) && privKey.IsValid())
+ {
+ break;
+ }
+
+ if (pk == CPubKey(ParseHex(C.CChexstr)))
+ {
+ privKey = CKey();
+ std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
+ privKey.Set(vch.begin(), vch.end(), true);
+ break;
+ }
+ }
- if (cc)
- {
- vector<unsigned char> vch;
- if (creator.CreateSig(vch, keys[0].GetID(), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
+ if (!privKey.IsValid())
+ return false;
+
+ CC *cc;
+ if (keys.size() > 1)
{
- ret.push_back(vch);
+ cc = CCcond1of2(p.evalCode, keys[0], keys[1]);
}
else
{
- fprintf(stderr,"vin has 1of2 CC signing error with addresses.(%s)\n(%s)\n", keys[0].GetID().ToString().c_str(), keys[1].GetID().ToString().c_str());
+ cc = CCcond1(p.evalCode, keys[0]);
}
- cc_free(cc);
- return ret.size() != 0;
+ if (cc)
+ {
+ vector<unsigned char> vch;
+ if (creator.CreateSig(vch, keys[0].GetID(), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
+ {
+ ret.push_back(vch);
+ }
+ else
+ {
+ fprintf(stderr,"vin has 1ofn CC signing error with addresses.(%s)\n(%s)\n", keys[0].GetID().ToString().c_str(), keys[1].GetID().ToString().c_str());
+ }
+
+ cc_free(cc);
+ return ret.size() != 0;
+ }
}
}
}
return false;
}
+ COptCCParams p;
+ if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
+ {
+ return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId);
+ }
+
CKeyID keyID;
switch (whichTypeRet)
}
return false;
- case TX_CRYPTOCONDITION:
- return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId);
-
case TX_MULTISIG:
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
{
return true;
}
+
+ int CheckCryptoCondition(
+ const std::vector<unsigned char>& condBin,
+ const std::vector<unsigned char>& ffillBin,
+ const CScript& scriptCode,
+ uint32_t consensusBranchId) const
+ {
+ return true;
+ }
};
const DummySignatureChecker dummyChecker;
}
CKey *key,
void *extraData) const
{
- // Create a dummy signature that is a valid DER-encoding
- vchSig.assign(72, '\000');
- vchSig[0] = 0x30;
- vchSig[1] = 69;
- vchSig[2] = 0x02;
- vchSig[3] = 33;
- vchSig[4] = 0x01;
- vchSig[4 + 33] = 0x02;
- vchSig[5 + 33] = 32;
- vchSig[6 + 33] = 0x01;
- vchSig[6 + 33 + 32] = SIGHASH_ALL;
+ if (scriptCode.IsPayToCryptoCondition())
+ {
+ vchSig = CCPartialSigVec(MakeCCcondOneSig(keyid));
+ }
+ else
+ {
+ // Create a dummy signature that is a valid DER-encoding
+ vchSig.assign(72, '\000');
+ vchSig[0] = 0x30;
+ vchSig[1] = 69;
+ vchSig[2] = 0x02;
+ vchSig[3] = 33;
+ vchSig[4] = 0x01;
+ vchSig[4 + 33] = 0x02;
+ vchSig[5 + 33] = 32;
+ vchSig[6 + 33] = 0x01;
+ vchSig[6 + 33 + 32] = SIGHASH_ALL;
+ }
return true;
}