diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 2c96907bb..028437ddb 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -206,7 +206,7 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, uint256 blockHash; bool isValid = false; - if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > nIn) + if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > tx.vin[nIn].prevout.n) { CBlockIndex index; if (eval->GetBlock(blockHash, index)) @@ -221,6 +221,15 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, if (tx.vout.size() > 0 && tx.vout[tx.vout.size() - 1].scriptPubKey.IsOpReturn()) { tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params); + if (params.size() == 1) + { + CScript scr = CScript(params[0]); + if (scr.IsOpReturn()) + { + params.clear(); + scr.GetOpretData(params); + } + } } isValid = true; } diff --git a/src/cc/CoinbaseGuard.cpp b/src/cc/CoinbaseGuard.cpp index 7227207ae..2b1917959 100644 --- a/src/cc/CoinbaseGuard.cpp +++ b/src/cc/CoinbaseGuard.cpp @@ -305,31 +305,51 @@ bool MakeCheatEvidence(CMutableTransaction &mtx, const CTransaction &ccTx, uint3 } typedef struct ccFulfillmentCheck { - int32_t childCount; - uint64_t fulfillmentMask; + std::vector &vPK; + std::vector &vCount; } ccFulfillmentCheck; -int IsCCFulfilled(CC *cc, ccFulfillmentCheck *ctx); - // to figure out which node is signed int CCFulfillmentVisitor(CC *cc, struct CCVisitor visitor) { - ccFulfillmentCheck *pfc = (ccFulfillmentCheck *)(visitor.context); - int fulfilled = cc_isFulfilled(cc); - pfc->fulfillmentMask |= (fulfilled == 0) ? 0 : ((uint64_t)1) << (uint64_t)pfc->childCount; - printf("fullfilled: %x, pfc->fulfillmentMask: %x, pfc->childCount: %d\n", fulfilled, pfc->fulfillmentMask, pfc->childCount); - pfc->childCount++; - return fulfilled; + //printf("cc_typeName: %s, cc_isFulfilled: %x, cc_isAnon: %x, cc_typeMask: %x, cc_condToJSONString:\n%s\n", + // cc_typeName(cc), cc_isFulfilled(cc), cc_isAnon(cc), cc_typeMask(cc), cc_conditionToJSONString(cc)); + + if (strcmp(cc_typeName(cc), "secp256k1-sha-256") == 0) + { + cJSON *json = cc_conditionToJSON(cc); + if (json) + { + cJSON *pubKeyNode = json->child->next; + if (strcmp(pubKeyNode->string, "publicKey") == 0) + { + ccFulfillmentCheck *pfc = (ccFulfillmentCheck *)(visitor.context); + + printf("public key: %s\n", pubKeyNode->valuestring); + CPubKey pubKey = CPubKey(ParseHex(pubKeyNode->valuestring)); + + for (int i = 0; i < pfc->vPK.size(); i++) + { + if (i < pfc->vCount.size() && (pfc->vPK[i] == pubKey)) + { + pfc->vCount[i]++; + } + } + } + cJSON_free(json); + } + } + + return 1; } int IsCCFulfilled(CC *cc, ccFulfillmentCheck *ctx) { - int fulfilled = cc_isFulfilled(cc); - // printf("Root IsFulfilled: %x\n", fulfilled); - struct CCVisitor visitor = {&CCFulfillmentVisitor, NULL, 0, (void *)ctx}; cc_visit(cc, visitor); - return fulfilled; + + printf("count key 1: %d, count key 2: %d\n", ctx->vCount[0], ctx->vCount[1]); + return ctx->vCount[0]; } bool CoinbaseGuardValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) @@ -355,44 +375,53 @@ bool CoinbaseGuardValidate(struct CCcontract_info *cp, Eval* eval, const CTransa if (cc) { - ccFulfillmentCheck fc = {0, 0}; - IsCCFulfilled(cc, &fc); - - // this should reflect the truth of whether the first key did sign the fulfillment - signedByFirstKey = ((fc.fulfillmentMask & (uint64_t)4) != 0); + COptCCParams ccp; + signedByFirstKey = false; validCheat = false; // tx is the spending tx, the cc transaction comes back in txOut if (GetCCParams(eval, tx, nIn, txOut, preConditions, params)) { - if (preConditions.size() > 0 && params.size() > 0) + if (preConditions.size() > 0) { - COptCCParams ccp = COptCCParams(preConditions[1]); + ccp = COptCCParams(preConditions[0]); } - // if we've been passed a cheat transaction - if (!signedByFirstKey && params.size() > 1 && params[0][0] == OPRETTYPE_STAKECHEAT) + if (ccp.IsValid() && ccp.m == 1 && ccp.n == 2 && ccp.vKeys.size() == 2) { - CDataStream s = CDataStream(params[1], SER_DISK, CLIENT_VERSION); - CTransaction cheatTx; - try + std::vector vc = {0, 0}; + ccFulfillmentCheck fc = {ccp.vKeys, vc}; + + signedByFirstKey = (IsCCFulfilled(cc, &fc) != 0); + + if (!(signedByFirstKey = (vc[0] != 0)) && params.size() == 2 && params[0].size() > 0 && params[0][0] == OPRETTYPE_STAKECHEAT) { - cheatTx.Unserialize(s); - validCheat = true; - } - catch (...) - { - } - if (validCheat && !(ValidateMatchingStake(txOut, tx.vin[0].prevout.n, tx, validCheat))) - { - validCheat = false; + CDataStream s = CDataStream(std::vector(params[1].begin(), params[1].end()), SER_DISK, CLIENT_VERSION); + bool checkOK = false; + CTransaction cheatTx; + try + { + cheatTx.Unserialize(s); + checkOK = true; + } + catch (...) + { + } + if (checkOK && !ValidateMatchingStake(txOut, tx.vin[0].prevout.n, tx, validCheat)) + { + validCheat = false; + } } } } - cc_free(cc); } - return signedByFirstKey || validCheat; + if (!(signedByFirstKey || validCheat)) + { + eval->Error("error reading coinbase or spending proof invalid\n"); + return false; + } + else return true; } UniValue CoinbaseGuardInfo() diff --git a/src/script/sign.cpp b/src/script/sign.cpp index d28e16ea6..8bcb00401 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -218,10 +218,9 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr)))) { privKey = CKey(); - CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); - privKey.SetPrivKey(vch, false); + std::vector vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); + privKey.Set(vch.begin(), vch.end(), false); } - else return false; CC *cc = CCcond1(p.evalCode, p.vKeys[0]); @@ -246,14 +245,14 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip // first of priv key in our key store or contract address is what we sign with for (auto pk : p.vKeys) { - if (creator.KeyStore().GetKey(p.vKeys[0].GetID(), privKey) && privKey.IsValid()) + if (creator.KeyStore().GetKey(pk.GetID(), privKey) && privKey.IsValid()) break; - if (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr))) + if (pk == CPubKey(ParseHex(C.CChexstr))) { privKey = CKey(); - CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); - privKey.SetPrivKey(vch, false); + std::vector vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); + privKey.Set(vch.begin(), vch.end(), false); break; } }