Change behavior of ExtractDestination, Solver, and GetscriptAddress for crypto conditions

This commit is contained in:
miketout
2018-10-06 00:36:21 -07:00
parent ef9a13b557
commit 68b9a352da
5 changed files with 77 additions and 31 deletions

View File

@@ -187,13 +187,16 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
{ {
CTxDestination address; txnouttype whichType; CTxDestination address;
if ( ExtractDestination(scriptPubKey,address) != 0 ) txnouttype whichType;
std::vector<std::vector<unsigned char>> vvch = std::vector<std::vector<unsigned char>>();
if (Solver(scriptPubKey, whichType, vvch) && vvch[0].size() == 20)
{ {
address = CKeyID(uint160(vvch[0]));
strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
return(true); return(true);
} }
fprintf(stderr,"ExtractDestination failed\n"); fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString());
return(false); return(false);
} }

View File

@@ -1630,7 +1630,37 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str());
strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str());
strcpy(cbaddr, CBitcoinAddress(cbaddress).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<std::vector<unsigned char>> vvch = std::vector<std::vector<unsigned char>>();
// 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; isPOS = true;
} }

View File

@@ -400,7 +400,16 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet
else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) 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; return true;
} }
// Multisig txns have more than one address... // Multisig txns have more than one address...
@@ -454,7 +463,15 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto
nRequiredRet = vSolutions.front()[0]; nRequiredRet = vSolutions.front()[0];
for (unsigned int i = 1; i < vSolutions.size()-1; i++) 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); addressRet.push_back(address);
} }

View File

@@ -2085,6 +2085,17 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum)
case TX_NULL_DATA: case TX_NULL_DATA:
break; 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: case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID(); keyID = CPubKey(vSolutions[0]).GetID();
if (this->HaveKey(keyID)) if (this->HaveKey(keyID))

View File

@@ -62,6 +62,16 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey)
case TX_NONSTANDARD: case TX_NONSTANDARD:
case TX_NULL_DATA: case TX_NULL_DATA:
break; 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: case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID(); keyID = CPubKey(vSolutions[0]).GetID();
if (keystore.HaveKey(keyID)) if (keystore.HaveKey(keyID))
@@ -83,31 +93,6 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey)
} }
break; break;
} }
case TX_CRYPTOCONDITION:
{
// some crypto conditions we consider "mine" if our address is the first specified
// extra address
CScript subScript;
vector<valtype> 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: case TX_MULTISIG:
{ {
// Only consider transactions "mine" if we own ALL the // Only consider transactions "mine" if we own ALL the