diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 64a832c3a..d76a881fd 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -187,13 +187,16 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t * bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) { - CTxDestination address; txnouttype whichType; - if ( ExtractDestination(scriptPubKey,address) != 0 ) + CTxDestination address; + txnouttype whichType; + std::vector> vvch = std::vector>(); + if (Solver(scriptPubKey, whichType, vvch) && vvch[0].size() == 20) { + address = CKeyID(uint160(vvch[0])); strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); return(true); } - fprintf(stderr,"ExtractDestination failed\n"); + fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString()); return(false); } diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 89048c00d..fffc57ffa 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1630,7 +1630,37 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); - if ( !strcmp(destaddr,voutaddr) && ( !strcmp(destaddr,cbaddr) || (height < 17840)) ) + if (newPOSEnforcement) + { + if (!strcmp(destaddr,voutaddr)) + { + // allow delegation of stake, but require all ouputs to be + // crypto conditions + CStakeParams p; + if (GetStakeParams(pblock->vtx[txn_count-1], p)) + { + COptCCParams cpp; + // loop through all outputs to make sure they are sent to the proper pubkey + isPOS = true; + for (auto vout : pblock->vtx[0].vout) + { + txnouttype tp; + std::vector> vvch = std::vector>(); + // solve all outputs to check that destinations all go only to the pk + // specified in the stake params + if (!Solver(vout.scriptPubKey, tp, vvch) || + tp != TX_CRYPTOCONDITION || + vvch.size() < 2 || + p.pk != CPubKey(vvch[1])) + { + isPOS = false; + break; + } + } + } + } + } + else if ( !strcmp(destaddr,voutaddr) && ( !strcmp(destaddr,cbaddr) || (height < 17840)) ) { isPOS = true; } diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 091b37ec8..71fa0d629 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -400,7 +400,16 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) { - addressRet = CKeyID(uint160(vSolutions[0])); + if (vSolutions.size() > 1) + { + CPubKey pk = CPubKey((vSolutions[1])); + addressRet = pk; + return pk.IsValid(); + } + else + { + addressRet = CKeyID(uint160(vSolutions[0])); + } return true; } // Multisig txns have more than one address... @@ -454,7 +463,15 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto nRequiredRet = vSolutions.front()[0]; for (unsigned int i = 1; i < vSolutions.size()-1; i++) { - CTxDestination address = CKeyID(uint160(vSolutions[i])); + CTxDestination address; + if (vSolutions[i].size() == 20) + { + address = CKeyID(uint160(vSolutions[i])); + } + else + { + address = CPubKey(vSolutions[i]); + } addressRet.push_back(address); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 819a483d0..86180ada4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2085,6 +2085,17 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) case TX_NULL_DATA: break; + case TX_CRYPTOCONDITION: + // for now, default is that the first value returned will be the script, subsequent values will be + // pubkeys. if we have the first pub key in our wallet, we consider this spendable + if (vSolutions.size() > 1) + { + keyID = CPubKey(vSolutions[1]).GetID(); + if (this->HaveKey(keyID)) + return ISMINE_SPENDABLE; + } + break; + case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); if (this->HaveKey(keyID)) diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 75e93390f..3d8ccd0a8 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -62,6 +62,16 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) case TX_NONSTANDARD: case TX_NULL_DATA: break; + case TX_CRYPTOCONDITION: + // for now, default is that the first value returned will be the script, subsequent values will be + // pubkeys. if we have the first pub key in our wallet, we consider this spendable + if (vSolutions.size() > 1) + { + keyID = CPubKey(vSolutions[1]).GetID(); + if (keystore.HaveKey(keyID)) + return ISMINE_SPENDABLE; + } + break; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); if (keystore.HaveKey(keyID)) @@ -83,31 +93,6 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) } break; } - - case TX_CRYPTOCONDITION: - { - // some crypto conditions we consider "mine" if our address is the first specified - // extra address - CScript subScript; - vector vParams; - COptCCParams p; - if (scriptPubKey.IsPayToCryptoCondition(&subScript, vParams)) - { - if (vParams.size() > 1) - { - p = COptCCParams(vParams[0]); - // if we are the primary output on a coinbase guard, it is ours - if (p.IsValid() && p.evalCode == EVAL_COINBASEGUARD && vParams[1].size() == 20) - { - CKeyID adr = CKeyID(uint160(vParams[1])); - if (keystore.HaveKey(keyID)) - return ISMINE_SPENDABLE; - } - } - } - break; - } - case TX_MULTISIG: { // Only consider transactions "mine" if we own ALL the