Confirm positive and negative spends with and without priv keys

This commit is contained in:
miketout
2018-10-07 14:21:43 -07:00
parent ccc47c554c
commit 281a5e2eec
3 changed files with 82 additions and 45 deletions

View File

@@ -206,7 +206,7 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn,
uint256 blockHash; uint256 blockHash;
bool isValid = false; 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; CBlockIndex index;
if (eval->GetBlock(blockHash, 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()) if (tx.vout.size() > 0 && tx.vout[tx.vout.size() - 1].scriptPubKey.IsOpReturn())
{ {
tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params); 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; isValid = true;
} }

View File

@@ -305,31 +305,51 @@ bool MakeCheatEvidence(CMutableTransaction &mtx, const CTransaction &ccTx, uint3
} }
typedef struct ccFulfillmentCheck { typedef struct ccFulfillmentCheck {
int32_t childCount; std::vector<CPubKey> &vPK;
uint64_t fulfillmentMask; std::vector<uint32_t> &vCount;
} ccFulfillmentCheck; } ccFulfillmentCheck;
int IsCCFulfilled(CC *cc, ccFulfillmentCheck *ctx);
// to figure out which node is signed // to figure out which node is signed
int CCFulfillmentVisitor(CC *cc, struct CCVisitor visitor) int CCFulfillmentVisitor(CC *cc, struct CCVisitor visitor)
{ {
ccFulfillmentCheck *pfc = (ccFulfillmentCheck *)(visitor.context); //printf("cc_typeName: %s, cc_isFulfilled: %x, cc_isAnon: %x, cc_typeMask: %x, cc_condToJSONString:\n%s\n",
int fulfilled = cc_isFulfilled(cc); // cc_typeName(cc), cc_isFulfilled(cc), cc_isAnon(cc), cc_typeMask(cc), cc_conditionToJSONString(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); if (strcmp(cc_typeName(cc), "secp256k1-sha-256") == 0)
pfc->childCount++; {
return fulfilled; 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 IsCCFulfilled(CC *cc, ccFulfillmentCheck *ctx)
{ {
int fulfilled = cc_isFulfilled(cc);
// printf("Root IsFulfilled: %x\n", fulfilled);
struct CCVisitor visitor = {&CCFulfillmentVisitor, NULL, 0, (void *)ctx}; struct CCVisitor visitor = {&CCFulfillmentVisitor, NULL, 0, (void *)ctx};
cc_visit(cc, visitor); 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) 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) if (cc)
{ {
ccFulfillmentCheck fc = {0, 0}; COptCCParams ccp;
IsCCFulfilled(cc, &fc); signedByFirstKey = false;
// this should reflect the truth of whether the first key did sign the fulfillment
signedByFirstKey = ((fc.fulfillmentMask & (uint64_t)4) != 0);
validCheat = false; validCheat = false;
// tx is the spending tx, the cc transaction comes back in txOut // tx is the spending tx, the cc transaction comes back in txOut
if (GetCCParams(eval, tx, nIn, txOut, preConditions, params)) 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 (ccp.IsValid() && ccp.m == 1 && ccp.n == 2 && ccp.vKeys.size() == 2)
if (!signedByFirstKey && params.size() > 1 && params[0][0] == OPRETTYPE_STAKECHEAT)
{ {
CDataStream s = CDataStream(params[1], SER_DISK, CLIENT_VERSION); std::vector<uint32_t> vc = {0, 0};
CTransaction cheatTx; ccFulfillmentCheck fc = {ccp.vKeys, vc};
try
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); CDataStream s = CDataStream(std::vector<unsigned char>(params[1].begin(), params[1].end()), SER_DISK, CLIENT_VERSION);
validCheat = true; bool checkOK = false;
} CTransaction cheatTx;
catch (...) try
{ {
} cheatTx.Unserialize(s);
if (validCheat && !(ValidateMatchingStake(txOut, tx.vin[0].prevout.n, tx, validCheat))) checkOK = true;
{ }
validCheat = false; catch (...)
{
}
if (checkOK && !ValidateMatchingStake(txOut, tx.vin[0].prevout.n, tx, validCheat))
{
validCheat = false;
}
} }
} }
} }
cc_free(cc); 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() UniValue CoinbaseGuardInfo()

View File

@@ -218,10 +218,9 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr)))) if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr))))
{ {
privKey = CKey(); privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false); privKey.Set(vch.begin(), vch.end(), false);
} }
else return false;
CC *cc = CCcond1(p.evalCode, p.vKeys[0]); 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 // first of priv key in our key store or contract address is what we sign with
for (auto pk : p.vKeys) 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; break;
if (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr))) if (pk == CPubKey(ParseHex(C.CChexstr)))
{ {
privKey = CKey(); privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false); privKey.Set(vch.begin(), vch.end(), false);
break; break;
} }
} }