Complete nothing at stake solution, waiting for confirm of masks

This commit is contained in:
miketout
2018-10-06 21:28:51 -07:00
parent a1fd99cf34
commit 191f3bbddd
16 changed files with 227 additions and 139 deletions

View File

@@ -232,7 +232,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
strcpy(cp->normaladdr,AssetsNormaladdr);
strcpy(cp->CChexstr,AssetsCChexstr);
memcpy(cp->CCpriv,AssetsCCpriv,32);
cp->validate = AssetsValidate;
cp->validate = CoinbaseGuardValidate;
cp->ismyvin = IsAssetsInput;
break;

View File

@@ -196,7 +196,7 @@ bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
return(true);
}
fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString());
fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString().c_str());
return(false);
}
@@ -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))
if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash) && txOut.vout.size() > nIn)
{
CBlockIndex index;
if (eval->GetBlock(blockHash, index))
@@ -218,7 +218,10 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn,
{
// read any available parameters in the output transaction
params.clear();
tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params);
if (tx.vout.size() > 0 && tx.vout[tx.vout.size() - 1].scriptPubKey.IsOpReturn())
{
tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params);
}
isValid = true;
}
}
@@ -388,8 +391,8 @@ bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> param
cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0;
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
else if ( ctx.vout.size() == 0 )
return eval->Invalid("no-vouts");
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
// return eval->Invalid("no-vouts");
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
{
//fprintf(stderr,"done CC %02x\n",cp->evalcode);

View File

@@ -168,8 +168,7 @@ bool ValidateStakeTransaction(const CTransaction &stakeTx, CStakeParams &stakePa
if (!validateSig || VerifyScript(stakeTx.vin[0].scriptSig,
srcTx.vout[stakeTx.vin[0].prevout.n].scriptPubKey,
MANDATORY_SCRIPT_VERIFY_FLAGS,
TransactionSignatureChecker(&stakeTx, 0, srcTx.vout[stakeTx.vin[0].prevout.n].nValue,
PrecomputedTransactionData(stakeTx)),
ServerTransactionSignatureChecker(&stakeTx, (uint32_t)0, srcTx.vout[stakeTx.vin[0].prevout.n].nValue, false),
consensusBranchId))
{
return true;
@@ -305,6 +304,34 @@ bool MakeCheatEvidence(CMutableTransaction &mtx, const CTransaction &ccTx, uint3
}
}
typedef struct ccFulfillmentCheck {
int32_t childCount;
uint64_t fulfillmentMask;
} 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;
}
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;
}
bool CoinbaseGuardValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn)
{
// This also supports a variable blockstomaturity option for backward feature compatibility
@@ -321,15 +348,19 @@ bool CoinbaseGuardValidate(struct CCcontract_info *cp, Eval* eval, const CTransa
std::vector<std::vector<unsigned char>> params = std::vector<std::vector<unsigned char>>();
CTransaction txOut;
CC *cc = GetCryptoCondition(tx.vin[nIn].scriptSig);
// this should reflect the truth of whether the first key did sign the fulfillment
bool signedByFirstKey = true;
bool signedByFirstKey = false;
bool validCheat = false;
CC *cc = GetCryptoCondition(tx.vin[nIn].scriptSig);
if (cc)
{
printf("CryptoCondition code %x\n", *cc->code);
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);
validCheat = false;
// tx is the spending tx, the cc transaction comes back in txOut
if (GetCCParams(eval, tx, nIn, txOut, preConditions, params))

View File

@@ -266,12 +266,11 @@ void *chainparams_commandline(void *ptr)
mainParams.consensus.nLwmaPOSAjustedWeight = 46531;
}
mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = ASSETCHAINS_SAPLING;
mainParams.consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = ASSETCHAINS_OVERWINTER;
// only require coinbase protection on Verus from the Komodo family of coins
if (strcmp(ASSETCHAINS_SYMBOL,"VRSC") == 0)
{
mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 227520;
mainParams.consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 227520 - 120;
mainParams.consensus.fCoinbaseMustBeProtected = true;
checkpointData = //(Checkpoints::CCheckpointData)
{
@@ -291,6 +290,8 @@ void *chainparams_commandline(void *ptr)
}
else
{
mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = ASSETCHAINS_SAPLING;
mainParams.consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = ASSETCHAINS_OVERWINTER;
checkpointData = //(Checkpoints::CCheckpointData)
{
boost::assign::map_list_of

View File

@@ -9,7 +9,7 @@ include_HEADERS = include/cryptoconditions.h
libcryptoconditions_la_SOURCES = include/cryptoconditions.h
libcryptoconditions_la_LIBADD = $(CRYPTOCONDITIONS_CORE) $(LIBSECP256K1)
AM_CFLAGS = -I$(top_srcdir)/src/asn -I$(top_srcdir)/include -I$(top_srcdir)/src/include \
AM_CFLAGS = -I$(top_srcdir)/src/asn -I./cryptoconditions/src/asn -I$(top_srcdir)/include -I$(top_srcdir)/src/include \
-Wall -Wno-pointer-sign -Wno-discarded-qualifiers
LIBSECP256K1=src/include/secp256k1/libsecp256k1.la

View File

@@ -56,8 +56,6 @@ typedef struct CC {
};
} CC;
/*
* Crypto Condition Visitor
*/
@@ -87,6 +85,7 @@ struct CC* cc_conditionFromJSON(cJSON *params, char *err);
struct CC* cc_conditionFromJSONString(const char *json, char *err);
struct CC* cc_readConditionBinary(const uint8_t *cond_bin, size_t cond_bin_len);
struct CC* cc_readFulfillmentBinary(const uint8_t *ffill_bin, size_t ffill_bin_len);
int cc_readFulfillmentBinaryExt(const unsigned char *ffill_bin, size_t ffill_bin_len, CC **ppcc);
struct CC* cc_new(int typeId);
struct cJSON* cc_conditionToJSON(const CC *cond);
char* cc_conditionToJSONString(const CC *cond);

View File

@@ -55,7 +55,7 @@ static void anonToJSON(const CC *cond, cJSON *params) {
static unsigned char *anonFingerprint(const CC *cond) {
unsigned char *out = calloc(1, 32);
fprintf(stderr,"anon fingerprint %p %p\n",out,cond->fingerprint);
//fprintf(stderr,"anon fingerprint %p %p\n",out,cond->fingerprint);
memcpy(out, cond->fingerprint, 32);
return out;
}

View File

@@ -5,7 +5,7 @@
#ifndef ASN1_CONSTRAINTS_VALIDATOR_H
#define ASN1_CONSTRAINTS_VALIDATOR_H
#include <asn_system.h> /* Platform-dependent types */
#include "asn_system.h" /* Platform-dependent types */
#ifdef __cplusplus
extern "C" {

View File

@@ -6,7 +6,7 @@
#ifndef _PER_SUPPORT_H_
#define _PER_SUPPORT_H_
#include <asn_system.h> /* Platform-specific types */
#include "asn_system.h" /* Platform-specific types */
#ifdef __cplusplus
extern "C" {

View File

@@ -216,6 +216,35 @@ end:
return cond;
}
int cc_readFulfillmentBinaryExt(const unsigned char *ffill_bin, size_t ffill_bin_len, CC **ppcc) {
int error = 0;
unsigned char *buf = calloc(1,ffill_bin_len);
Fulfillment_t *ffill = 0;
asn_dec_rval_t rval = ber_decode(0, &asn_DEF_Fulfillment, (void **)&ffill, ffill_bin, ffill_bin_len);
if (rval.code != RC_OK) {
error = rval.code;
goto end;
}
// Do malleability check
asn_enc_rval_t rc = der_encode_to_buffer(&asn_DEF_Fulfillment, ffill, buf, ffill_bin_len);
if (rc.encoded == -1) {
fprintf(stderr, "FULFILLMENT NOT ENCODED\n");
error = -1;
goto end;
}
if (rc.encoded != ffill_bin_len || 0 != memcmp(ffill_bin, buf, rc.encoded)) {
error = (rc.encoded == ffill_bin_len) ? -3 : -2;
goto end;
}
*ppcc = fulfillmentToCC(ffill);
end:
free(buf);
if (ffill) ASN_STRUCT_FREE(asn_DEF_Fulfillment, ffill);
return error;
}
int cc_visit(CC *cond, CCVisitor visitor) {
int out = visitor.visit(cond, visitor);
@@ -225,7 +254,6 @@ int cc_visit(CC *cond, CCVisitor visitor) {
return out;
}
int cc_verify(const struct CC *cond, const unsigned char *msg, size_t msgLength, int doHashMsg,
const unsigned char *condBin, size_t condBinLength,
VerifyEval verifyEval, void *evalContext) {

View File

@@ -1502,9 +1502,12 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
{
if (pblock->GetRawVerusPOSHash(rawHash, height))
{
posHash = UintToArith256(rawHash) / value;
printf("PoS block\nblkHash: %s\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n",
pblock->GetHash().GetHex().c_str(), pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value);
if (posHash > target)
{
posHash = UintToArith256(rawHash) / value;
printf("PoS block\nblkHash: %s\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n",
pblock->GetHash().GetHex().c_str(), pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value);
}
}
else
{

View File

@@ -1765,8 +1765,15 @@ void komodo_args(char *argv0)
if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 )
ASSETCHAINS_LWMAPOS = 50;
ASSETCHAINS_SAPLING = GetArg("-ac_sapling", 227520);
ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", (ASSETCHAINS_SAPLING - 120) > 1 ? (ASSETCHAINS_SAPLING - 120) : 1);
ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1);
if (ASSETCHAINS_SAPLING == -1)
{
ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", -1);
}
else
{
ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", (ASSETCHAINS_SAPLING - 120) > 1 ? (ASSETCHAINS_SAPLING - 120) : 1);
}
if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 && ASSETCHAINS_COMMISSION > 0 && ASSETCHAINS_COMMISSION <= 100000000 )
decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str());

View File

@@ -1354,8 +1354,9 @@ int TransactionSignatureChecker::CheckCryptoCondition(
if (ffillBin.empty())
return false;
CC *cond = cc_readFulfillmentBinary((unsigned char*)ffillBin.data(), ffillBin.size()-1);
if (!cond) return -1;
CC *cond;
int error = cc_readFulfillmentBinaryExt((unsigned char*)ffillBin.data(), ffillBin.size()-1, &cond);
if (error || !cond) return -1;
if (!IsSupportedCryptoCondition(cond)) return 0;
if (!IsSignedCryptoCondition(cond)) return 0;
@@ -1363,7 +1364,7 @@ int TransactionSignatureChecker::CheckCryptoCondition(
uint256 sighash;
int nHashType = ffillBin.back();
try {
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
sighash = SignatureHash(CCPubKey(cond), *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
} catch (logic_error ex) {
return 0;
}
@@ -1391,8 +1392,8 @@ int TransactionSignatureChecker::CheckCryptoCondition(
int TransactionSignatureChecker::CheckEvalCondition(const CC *cond) const
{
fprintf(stderr, "Cannot check crypto-condition Eval outside of server\n");
return 0;
//fprintf(stderr, "Cannot check crypto-condition Eval outside of server, returning true in pre-checks\n");
return true;
}

View File

@@ -301,7 +301,7 @@ bool CScript::GetOpretData(std::vector<std::vector<unsigned char>>& vData) const
{
vector<unsigned char> data;
opcodetype opcode;
const_iterator pc = begin();
CScript::const_iterator pc = this->begin();
std::vector<unsigned char> vch1 = std::vector<unsigned char>(1);
vData.clear();

View File

@@ -18,7 +18,8 @@ private:
bool store;
public:
ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn) {}
ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, const PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn) {}
ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nIn, amount), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
int CheckEvalCondition(const CC *cond) const;

View File

@@ -43,6 +43,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
if (!cc || cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()) == 0)
return false;
vchSig = CCSigVec(cc);
return true;
}
else
{
@@ -95,20 +96,81 @@ CC *CCcond1(uint8_t evalcode,CPubKey pk)
return CCNewThreshold(2, {condCC, Sig});
}
std::vector<CCcontract_info> &GetCryptoConditions()
{
static bool initialized = false;
static std::vector<CCcontract_info> vCC = std::vector<CCcontract_info>();
CCcontract_info C;
if (!initialized)
{
C.evalcode = EVAL_COINBASEGUARD;
uint8_t privKey[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 };
strcpy(C.unspendableCCaddr,"RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6");
strcpy(C.normaladdr,"RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u");
strcpy(C.CChexstr,"02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702");
memcpy(C.CCpriv, privKey, 32);
vCC.push_back(C);
initialized = true;
}
return vCC;
}
bool GetCCByUnspendableAddress(struct CCcontract_info *cp, char *addrstr)
{
std::vector<CCcontract_info> &vCC = GetCryptoConditions();
bool found = false;
for (int i = 0; i < vCC.size(); i++)
{
if (strcmp(addrstr, vCC[i].unspendableCCaddr) == 0)
{
found = true;
*cp = vCC[i];
break;
}
}
return found;
}
bool CCinitLite(struct CCcontract_info *cp, uint8_t evalcode)
{
cp->evalcode = evalcode;
switch ( evalcode )
std::vector<CCcontract_info> &vCC = GetCryptoConditions();
bool found = false;
for (int i = 0; i < vCC.size(); i++)
{
case EVAL_COINBASEGUARD:
uint8_t privKey[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 };
strcpy(cp->unspendableCCaddr,"RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6");
strcpy(cp->normaladdr,"RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u");
strcpy(cp->CChexstr,"02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702");
memcpy(cp->CCpriv, privKey,32);
return true;
if (vCC[i].evalcode == evalcode)
{
found = true;
*cp = vCC[i];
break;
}
}
return false;
return found;
}
bool _Getscriptaddress(char *destaddr, const CScript &scriptPubKey)
{
CTxDestination address;
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());
return(true);
}
fprintf(stderr,"Solver for scriptPubKey failed\n%s\n", scriptPubKey.ToString().c_str());
return(false);
}
CScript _CCPubKey(const CC *cond)
{
unsigned char buf[1000];
size_t len = cc_conditionBinary(cond, buf);
return CScript() << std::vector<unsigned char>(buf, buf+len) << OP_CHECKCRYPTOCONDITION;
}
static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scriptPubKey, vector<valtype> &vSolutions,
@@ -116,150 +178,101 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
{
CScript subScript;
vector<CPubKey> vPK;
vector<CKeyID> vKeyID = vector<CKeyID>();
vector<valtype> vParams = vector<valtype>();
COptCCParams p;
// get information to sign with
CCcontract_info C;
scriptPubKey.IsPayToCryptoCondition(&subScript, vParams);
if (vParams.size() > 1 && (p = COptCCParams(vParams[0])).IsValid())
if (vParams.empty())
{
// get the keyID address of the cc and if it is an unspendable cc address, use its pubkey
// we have nothing else
char addr[64];
if (_Getscriptaddress(addr, subScript) && GetCCByUnspendableAddress(&C, addr))
{
vPK.push_back(CPubKey(ParseHex(C.CChexstr)));
p = COptCCParams(p.VERSION, C.evalcode, 1, 1, vPK, vParams);
}
}
else
{
p = COptCCParams(vParams[0]);
}
if (p.IsValid() && p.vKeys.size() >= p.n)
{
bool is1of2 = (p.m == 1 && p.n == 2);
uint32_t extraAddrs = p.n;
CKey privKey;
// get information to sign with
CCcontract_info C;
// must be a valid cc eval code
if (CCinitLite(&C, p.evalCode))
{
// pay to cc address is a valid tx
if (!is1of2)
{
try
{
if (!extraAddrs)
{
vKeyID.push_back(CKeyID(uint160(vSolutions[0])));
// if this isn't our main CC address, we can't do anything with it
if (strcmp(C.unspendableCCaddr, CBitcoinAddress(CTxDestination(vKeyID[0])).ToString().c_str()) != 0)
return false;
// otherwise, push back the corresponding pub key
vPK.push_back(CPubKey(ParseHex(C.CChexstr)));
}
else if (vParams.size() > extraAddrs)
{
bool havePriv;
vKeyID.push_back(CKeyID(uint160(vParams[1])));
// if this isn't the normal CC address and we also don't have it in our keystore, fail
CBitcoinAddress addr = CBitcoinAddress(CTxDestination(vKeyID[0]));
if (strcmp(C.normaladdr, addr.ToString().c_str()) == 0 &&
!(havePriv = creator.KeyStore().GetKey(vKeyID[0], privKey)))
return false;
bool havePriv = creator.KeyStore().GetKey(p.vKeys[0].GetID(), privKey);
vPK.push_back(CPubKey());
// if we don't have the private key, it is the unspendable address
if (!havePriv)
{
vPK[0] = CPubKey(ParseHex(C.CChexstr));
privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false);
}
else if (!creator.KeyStore().GetPubKey(vKeyID[0], vPK[0]))
return false;
}
} catch (...)
// if we don't have the private key, it must be the unspendable address
if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr))))
{
fprintf(stderr,"exception calculating 1of1 spend\n");
return false;
privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false);
}
else return false;
CC *cc = CCcond1(p.evalCode, vPK[0]);
CC *cc = CCcond1(p.evalCode, p.vKeys[0]);
if (cc)
{
vector<unsigned char> vch;
if (creator.CreateSig(vch, vKeyID[0], scriptPubKey, consensusBranchId, &privKey, (void *)cc))
if (creator.CreateSig(vch, p.vKeys[0].GetID(), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
{
ret.push_back(vch);
}
else
{
fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", vKeyID[0].ToString().c_str());
fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", p.vKeys[0].GetID().ToString().c_str());
}
cc_free(cc);
return ret.size() != 0;
}
}
else if (extraAddrs > 1 && vParams.size() > extraAddrs)
else
{
// we need to get 2 addresses, and we will need the private key for one
// to spend
bool pkValid = false;
for (int i = 0; i < extraAddrs; i++)
// first of priv key in our key store or contract address is what we sign with
for (auto pk : p.vKeys)
{
// loop through in order and choose the first key we have a priv key to for signing
try
if (creator.KeyStore().GetKey(p.vKeys[0].GetID(), privKey) && privKey.IsValid())
break;
if (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr)))
{
bool isCCAddr = false;
CPubKey pk;
vKeyID.push_back(CKeyID(uint160(vParams[i + 1])));
// if this isn't the CC address and we also don't have the pubkey in our keystore, fail, because we won't
// be able to make the condition to fulfill
if (!(isCCAddr = (strcmp(C.normaladdr, CBitcoinAddress(CTxDestination(vKeyID[0])).ToString().c_str()) == 0)) &&
!creator.KeyStore().GetPubKey(vKeyID[0], pk))
return false;
if (isCCAddr)
{
pk = CPubKey(ParseHex(C.CChexstr));
// only set the private key to this address if we don't have one yet
if (!pkValid)
{
privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false);
pkValid = true;
}
}
else
{
if (!pkValid)
{
if (creator.KeyStore().GetKey(vKeyID[0], privKey))
pkValid = true;
}
}
vPK.push_back(pk);
} catch (...)
{
fprintf(stderr,"exception calculating 1of2 spend\n");
return false;
privKey = CKey();
CPrivKey vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
privKey.SetPrivKey(vch, false);
break;
}
}
if (!pkValid)
if (!privKey.IsValid())
return false;
CC *cc = CCcond1of2(p.evalCode, vPK[0], vPK[1]);
CC *cc = CCcond1of2(p.evalCode, p.vKeys[0], p.vKeys[1]);
if (cc)
{
vector<unsigned char> vch;
if (creator.CreateSig(vch, vKeyID[0], scriptPubKey, consensusBranchId, &privKey, (void *)cc))
if (creator.CreateSig(vch, p.vKeys[0].GetID(), _CCPubKey(cc), consensusBranchId, &privKey, (void *)cc))
{
ret.push_back(vch);
}
else
{
fprintf(stderr,"vin has 1of2 CC signing error with address.(%s)\n", vKeyID[0].ToString().c_str());
fprintf(stderr,"vin has 1of2 CC signing error with addresses.(%s)\n(%s)\n", p.vKeys[0].GetID().ToString().c_str(), p.vKeys[1].GetID().ToString().c_str());
}
cc_free(cc);
@@ -524,6 +537,7 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature
return sigs2;
case TX_PUBKEY:
case TX_PUBKEYHASH:
case TX_CRYPTOCONDITION:
// Signatures are bigger than placeholders or empty scripts:
if (sigs1.script.empty() || sigs1.script[0].empty())
return sigs2;