}
// validates if a stake transaction is both valid and cheating, defined by:
-// the same exact utxo source, a target block height of later than that of this tx that is also targeting a fork
-// of the chain. we know the transaction is a coinbase
+// the same exact utxo source, a target block height of later than that of the provided coinbase tx that is also targeting a fork
+// of the chain. the source transaction must be a coinbase
bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating)
{
// an invalid or non-matching stake transaction cannot cheat
CC *cc = GetCryptoCondition(tx.vin[nIn].scriptSig);
- if (cc)
+ // tx is the spending tx, the cc transaction comes back in txOut
+ bool validCCParams = GetCCParams(eval, tx, nIn, txOut, preConditions, params);
+ COptCCParams ccp;
+ if (preConditions.size() > 0)
+ {
+ ccp = COptCCParams(preConditions[0]);
+ }
+
+ if (validCCParams && ccp.IsValid() && ((cc && ccp.version < COptCCParams::VERSION_V3) || (!cc && ccp.version >= COptCCParams::VERSION_V3)))
{
- 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 (ccp.m == 1 && ccp.n == 2 && ccp.vKeys.size() == 2)
{
- if (preConditions.size() > 0)
- {
- ccp = COptCCParams(preConditions[0]);
- }
+ std::vector<uint32_t> vc = {0, 0};
+ std::vector<CPubKey> keys;
- if (ccp.IsValid() && ccp.m == 1 && ccp.n == 2 && ccp.vKeys.size() == 2)
+ for (auto pk : ccp.vKeys)
{
- std::vector<uint32_t> vc = {0, 0};
-
- std::vector<CPubKey> keys;
- for (auto pk : ccp.vKeys)
+ uint160 keyID = GetDestinationID(pk);
+ std::vector<unsigned char> vkch = GetDestinationBytes(pk);
+ if (vkch.size() == 33)
{
- uint160 keyID = GetDestinationID(pk);
- std::vector<unsigned char> vkch = GetDestinationBytes(pk);
- if (vkch.size() == 33)
- {
- keys.push_back(CPubKey(vkch));
- }
+ keys.push_back(CPubKey(vkch));
}
+ }
- if (keys.size() == 2)
+ if (keys.size() == 2)
+ {
+ if (cc && ccp.version < COptCCParams::VERSION_V3)
{
ccFulfillmentCheck fc = {keys, vc};
-
signedByFirstKey = (IsCCFulfilled(cc, &fc) != 0);
-
- if ((!signedByFirstKey && ccp.evalCode == EVAL_STAKEGUARD && ccp.vKeys.size() == 2 && ccp.version == COptCCParams::VERSION_V1) &&
- params.size() == 2 && params[0].size() > 0 && params[0][0] == OPRETTYPE_STAKECHEAT)
+ }
+ else if (ccp.version >= COptCCParams::VERSION_V3)
+ {
+ CSmartTransactionSignatures smartSigs;
+ if (!cc)
{
- CDataStream s = CDataStream(std::vector<unsigned char>(params[1].begin(), params[1].end()), SER_DISK, PROTOCOL_VERSION);
- bool checkOK = false;
- CTransaction cheatTx;
- try
+ std::vector<unsigned char> ffVec = GetFulfillmentVector(tx.vin[nIn].scriptSig);
+ smartSigs = CSmartTransactionSignatures(std::vector<unsigned char>(ffVec.begin(), ffVec.end()));
+ uint160 checkHash = GetDestinationID(keys[0]);
+ for (auto &keySig : smartSigs.signatures)
{
- cheatTx.Unserialize(s);
- checkOK = true;
- }
- catch (...)
- {
- }
- if (checkOK && !ValidateMatchingStake(txOut, tx.vin[0].prevout.n, cheatTx, validCheat))
- {
- validCheat = false;
+ CPubKey thisKey;
+ thisKey.Set(keySig.second.pubKeyData.begin(), keySig.second.pubKeyData.end());
+ if (thisKey.GetID() == checkHash)
+ {
+ signedByFirstKey = true;
+ break;
+ }
}
}
}
+
+ if ((!signedByFirstKey && ccp.evalCode == EVAL_STAKEGUARD && ccp.vKeys.size() == 2 && ccp.version == COptCCParams::VERSION_V1) &&
+ params.size() == 2 && params[0].size() > 0 && params[0][0] == OPRETTYPE_STAKECHEAT)
+ {
+ CDataStream s = CDataStream(std::vector<unsigned char>(params[1].begin(), params[1].end()), SER_DISK, PROTOCOL_VERSION);
+ bool checkOK = false;
+ CTransaction cheatTx;
+ try
+ {
+ cheatTx.Unserialize(s);
+ checkOK = true;
+ }
+ catch (...)
+ {
+ }
+ if (checkOK && !ValidateMatchingStake(txOut, tx.vin[0].prevout.n, cheatTx, validCheat))
+ {
+ validCheat = false;
+ }
+ }
}
}
+ }
+ if (cc)
+ {
cc_free(cc);
}
if (!(signedByFirstKey || validCheat))
#include <cryptoconditions.h>
-#include "interpreter.h"
#include "standard.h"
#include "consensus/upgrades.h"
#include "primitives/transaction.h"
+#include "pbaas/pbaas.h"
#include "cc/eval.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
-#include "pubkey.h"
-#include "script/script.h"
-#include "uint256.h"
-#include "pbaas/pbaas.h"
-#include "pbaas/identity.h"
-
using namespace std;
return true;
}
-
bool VerifyScript(
const CScript& scriptSig,
const CScript& scriptPubKey,
}
vector<vector<unsigned char> > stack, stackCopy;
- if (IsCryptoConditionsEnabled() && scriptPubKey.IsPayToCryptoCondition()) {
+ COptCCParams p;
+ if (IsCryptoConditionsEnabled() && scriptPubKey.IsPayToCryptoCondition(p)) {
+
+ //UniValue r;
+ //printf("eval code: %d, keys:\n", p.evalCode);
+ //for (auto &key : p.vKeys)
+ //{
+ // printf("%s\n", EncodeDestination(key).c_str());
+ //}
+
if (!EvalCryptoConditionSig(stack, scriptSig, serror))
// serror is set
return false;