Complete nothing at stake solution, waiting for confirm of masks
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user