]> Git Repo - VerusCoin.git/blobdiff - src/script/sign.cpp
Enable identity to modify itself, except lock time, when locked
[VerusCoin.git] / src / script / sign.cpp
index 48b43e022340b06fc1c4e64431b39b61470327ac..2963f4ce7259aaeafc5e87da93f281988c8c53c9 100644 (file)
@@ -1,7 +1,7 @@
 // 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"
 
@@ -13,6 +13,7 @@
 #include "cc/CCinclude.h"
 #include "cc/eval.h"
 #include "key_io.h"
+#include "pbaas/identity.h"
 
 #include <boost/foreach.hpp>
 
@@ -20,9 +21,13 @@ using namespace std;
 
 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)
@@ -37,13 +42,52 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
         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
@@ -97,162 +141,571 @@ CC *CCcond1(uint8_t evalcode,CPubKey pk)
     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;
+                    }
                 }
             }
         }
@@ -294,6 +747,12 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
             return false;
     }
 
+    COptCCParams p;
+    if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
+    {
+        return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId);
+    }
+
     CKeyID keyID;
 
     switch (whichTypeRet)
@@ -322,9 +781,6 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
         }
         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));
@@ -575,6 +1031,15 @@ public:
     {
         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;
 }
@@ -592,16 +1057,23 @@ bool DummySignatureCreator::CreateSig(
     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;
 }
This page took 0.042887 seconds and 4 git commands to generate.