heir modified for two eval Tokens
changed to new 2-opret format
This commit is contained in:
@@ -191,6 +191,8 @@ CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubK
|
||||
CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk);
|
||||
CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2);
|
||||
CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk);
|
||||
|
||||
bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk);
|
||||
bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2);
|
||||
void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr);
|
||||
|
||||
|
||||
@@ -201,10 +201,10 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
|
||||
//vout.0: issuance tokenoshis to CC
|
||||
//vout.1: normal output for change (if any)
|
||||
//vout.n-1: opreturn EVAL_TOKENS 'c' <tokenname> <description>
|
||||
if (evalCodeInOpret != EVAL_TOKENS)
|
||||
return eval->Invalid("unexpected TokenValidate for createtoken");
|
||||
else
|
||||
return true;
|
||||
//if (evalCodeInOpret != EVAL_TOKENS)
|
||||
// return eval->Invalid("unexpected TokenValidate for createtoken");
|
||||
//else
|
||||
return true;
|
||||
|
||||
case 't': // transfer
|
||||
//vin.0: normal input
|
||||
@@ -225,15 +225,15 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
|
||||
|
||||
// forward validation if evalcode in opret is not EVAL_TOKENS
|
||||
// init for forwarding validation call
|
||||
if (evalCodeInOpret != EVAL_TOKENS) { // TODO: should we check also only allowed for tokens evalcodes, like EVAL_ASSETS, EVAL_GATEWAYS?
|
||||
struct CCcontract_info *cpOther = NULL, C;
|
||||
//if (evalCodeInOpret != EVAL_TOKENS) { // TODO: should we check also only allowed for tokens evalcodes, like EVAL_ASSETS, EVAL_GATEWAYS?
|
||||
// struct CCcontract_info *cpOther = NULL, C;
|
||||
|
||||
cpOther = CCinit(&C, evalCodeInOpret);
|
||||
if (cpOther)
|
||||
return cpOther->validate(cpOther, eval, tx, nIn);
|
||||
else
|
||||
return eval->Invalid("unsupported evalcode in opret");
|
||||
}
|
||||
// cpOther = CCinit(&C, evalCodeInOpret);
|
||||
// if (cpOther)
|
||||
// return cpOther->validate(cpOther, eval, tx, nIn);
|
||||
// else
|
||||
// return eval->Invalid("unsupported evalcode in opret");
|
||||
//}
|
||||
return true;
|
||||
// what does this do?
|
||||
// return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts));
|
||||
@@ -285,17 +285,18 @@ bool ExtractVinPubkeys(struct CCcontract_info *cp, CTransaction tx, std::vector<
|
||||
thread_local uint32_t tokenValIndentSize = 0;
|
||||
|
||||
// validates opret for token tx:
|
||||
bool ValidateTokenOpret(CTransaction tx, int32_t v, uint256 tokenid, uint8_t &evalCodeInOpret, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra) {
|
||||
bool ValidateTokenOpret(CTransaction tx, int32_t v, uint256 tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra) {
|
||||
|
||||
uint256 tokenidOpret, tokenidOpret2;
|
||||
uint8_t funcid;
|
||||
uint8_t dummyEvalCode;
|
||||
|
||||
// this is just for log messages indentation fur debugging recursive calls:
|
||||
std::string indentStr = std::string().append(tokenValIndentSize, '.');
|
||||
|
||||
int32_t n = tx.vout.size();
|
||||
|
||||
if ((funcid = DecodeTokenOpRet(tx.vout[n - 1].scriptPubKey, evalCodeInOpret, tokenidOpret, voutPubkeys, vopretExtra)) == 0)
|
||||
if ((funcid = DecodeTokenOpRet(tx.vout[n - 1].scriptPubKey, dummyEvalCode, tokenidOpret, voutPubkeys, vopretExtra)) == 0)
|
||||
{
|
||||
std::cerr << indentStr << "ValidateTokenOpret() DecodeTokenOpret could not parse opret for txid=" << tx.GetHash().GetHex() << std::endl;
|
||||
return(false);
|
||||
@@ -364,14 +365,24 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c
|
||||
|
||||
// moved opret checking to this new reusable func (dimxy):
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
uint8_t evalCodeInOpret = 0;
|
||||
const bool valOpret = ValidateTokenOpret(tx, v, reftokenid, evalCodeInOpret, voutPubkeys, vopretExtra);
|
||||
const bool valOpret = ValidateTokenOpret(tx, v, reftokenid, voutPubkeys, vopretExtra);
|
||||
//std::cerr << indentStr << "IsTokensvout() ValidateTokenOpret returned=" << std::boolalpha << valOpret << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl;
|
||||
if (valOpret) {
|
||||
//std::cerr << indentStr << "IsTokensvout() ValidateTokenOpret returned true" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl;
|
||||
|
||||
if (checkPubkeys) { // verify that the vout is within EVAL_TOKENS:
|
||||
|
||||
CScript contractScript = CScript(vopretExtra);
|
||||
std::vector<uint8_t> vcontractOpret;
|
||||
|
||||
GetOpReturnData(contractScript, vcontractOpret);
|
||||
if (vcontractOpret.size() == 0) {
|
||||
std::cerr << "IsTokensvout() empty contract opret" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t evalCodeInOpret = vcontractOpret.begin()[0];
|
||||
|
||||
if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) {
|
||||
CTxOut testVout;
|
||||
if (voutPubkeys.size() == 1)
|
||||
|
||||
@@ -43,9 +43,9 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0;
|
||||
int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0;
|
||||
int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64];
|
||||
int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64],mytokensaddr[64];
|
||||
uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0;
|
||||
CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond;
|
||||
CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond, *mytokenscond = NULL;
|
||||
CPubKey unspendablepk;
|
||||
|
||||
n = mtx.vout.size();
|
||||
@@ -61,11 +61,17 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
return("0");
|
||||
}
|
||||
Myprivkey(myprivkey);
|
||||
unspendablepk = GetUnspendable(cp,unspendablepriv);
|
||||
|
||||
GetCCaddress(cp,myaddr,mypk);
|
||||
mycond = MakeCCcond1(cp->evalcode,mypk);
|
||||
|
||||
GetTokensCCaddress(cp, myaddr, mypk);
|
||||
mytokenscond = MakeTokensCCcond1(cp->evalcode, mypk);
|
||||
|
||||
unspendablepk = GetUnspendable(cp,unspendablepriv);
|
||||
GetCCaddress(cp,unspendable,unspendablepk);
|
||||
othercond = MakeCCcond1(cp->evalcode,unspendablepk);
|
||||
othercond = MakeCCcond1(cp->evalcode,unspendablepk);
|
||||
|
||||
//Reorder vins so that for multiple normal vins all other except vin0 goes to the end
|
||||
//This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation.
|
||||
for (i=0; i<n; i++)
|
||||
@@ -137,6 +143,12 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
privkey = myprivkey;
|
||||
cond = mycond;
|
||||
}
|
||||
if (strcmp(destaddr, mytokensaddr) == 0) // if this is TokensCC1vout
|
||||
{
|
||||
privkey = myprivkey;
|
||||
cond = mytokenscond;
|
||||
//fprintf(stderr,"FinalizeCCTx() matched TokensCC1vout CC addr.(%s)\n",mytokensaddr);
|
||||
}
|
||||
else if ( strcmp(destaddr,unspendable) == 0 )
|
||||
{
|
||||
privkey = unspendablepriv;
|
||||
@@ -162,7 +174,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
cond = othercond3;
|
||||
}
|
||||
// check if this is spending from 1of2 cc coins addr:
|
||||
else if (strcmp(cp->coins1of2addr, destaddr) == 0)
|
||||
else if (strcmp(cp->coins1of2addr, destaddr) == 0)
|
||||
{
|
||||
fprintf(stderr,"FinalizeCCTx() matched %s unspendable1of2!\n",cp->coins1of2addr);
|
||||
privkey = myprivkey;
|
||||
|
||||
@@ -94,8 +94,8 @@ CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk)
|
||||
{
|
||||
std::vector<CC*> pks;
|
||||
pks.push_back(CCNewSecp256k1(pk));
|
||||
CC *condEvalCC = CCNewEval(E_MARSHAL(ss << evalcode));
|
||||
CC *condEvalTokensCC = CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS)); // this is eval token cc
|
||||
CC *condEvalCC = CCNewEval(E_MARSHAL(ss << evalcode)); // add eval cc
|
||||
CC *condEvalTokensCC = CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS)); // add also eval token cc
|
||||
CC *Sig = CCNewThreshold(1, pks);
|
||||
return CCNewThreshold(3, { condEvalCC, condEvalTokensCC, Sig });
|
||||
}
|
||||
@@ -345,6 +345,27 @@ bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk)
|
||||
return(_GetCCaddress(destaddr,cp->evalcode,pk));
|
||||
}
|
||||
|
||||
bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode, CPubKey pk)
|
||||
{
|
||||
CC *payoutCond;
|
||||
destaddr[0] = 0;
|
||||
if ((payoutCond = MakeTokensCCcond1(evalcode, pk)) != 0)
|
||||
{
|
||||
Getscriptaddress(destaddr, CCPubKey(payoutCond));
|
||||
cc_free(payoutCond);
|
||||
}
|
||||
return(destaddr[0] != 0);
|
||||
}
|
||||
|
||||
bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk)
|
||||
{
|
||||
destaddr[0] = 0;
|
||||
if (pk.size() == 0)
|
||||
pk = GetUnspendable(cp, 0);
|
||||
return(_GetTokensCCaddress(destaddr, cp->evalcode, pk));
|
||||
}
|
||||
|
||||
|
||||
bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2)
|
||||
{
|
||||
CC *payoutCond;
|
||||
|
||||
250
src/cc/heir.cpp
250
src/cc/heir.cpp
@@ -122,23 +122,27 @@ bool HeirValidate(struct CCcontract_info* cpHeir, Eval* eval, const CTransaction
|
||||
//if (chainActive.Height() < 741)
|
||||
// return true;
|
||||
|
||||
uint8_t funcId;
|
||||
uint256 fundingTxidInOpret = zeroid, latestTxid = zeroid, dummyTokenid, tokenid = zeroid;
|
||||
|
||||
CScript fundingTxOpRetScript;
|
||||
uint8_t hasHeirSpendingBegun = 0, dummyHasHeirSpendingBegun;
|
||||
|
||||
int32_t heirType = NOT_HEIR;
|
||||
funcId = DecodeHeirOpRet<CoinHelper>(tx.vout[numvouts - 1].scriptPubKey, dummyTokenid, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
if(funcId != 0)
|
||||
heirType = HEIR_COINS;
|
||||
else {
|
||||
funcId = DecodeHeirOpRet<TokenHelper>(tx.vout[numvouts - 1].scriptPubKey, tokenid, fundingTxidInOpret, dummyHasHeirSpendingBegun, false);
|
||||
if (funcId != 0)
|
||||
heirType = HEIR_TOKENS;
|
||||
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
|
||||
CScript heirScript = tx.vout[tx.vout.size() - 1].scriptPubKey;
|
||||
int32_t heirType = HEIR_COINS;
|
||||
|
||||
uint8_t funcId = DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, voutPubkeys, vopretExtra);
|
||||
if (funcId != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
heirType = HEIR_TOKENS;
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
|
||||
if (heirType == NOT_HEIR)
|
||||
if (funcId == 0)
|
||||
return eval->Invalid("invalid opreturn format");
|
||||
|
||||
if (funcId != 'F') {
|
||||
@@ -248,11 +252,11 @@ bool HeirValidate(struct CCcontract_info* cpHeir, Eval* eval, const CTransaction
|
||||
* Checks if vout is to cryptocondition address
|
||||
* @return vout value in satoshis
|
||||
*/
|
||||
int64_t IsHeirFundingVout(struct CCcontract_info* cp, const CTransaction& tx, int32_t voutIndex, CPubKey ownerPubkey, CPubKey heirPubkey)
|
||||
template <class Helper> int64_t IsHeirFundingVout(struct CCcontract_info* cp, const CTransaction& tx, int32_t voutIndex, CPubKey ownerPubkey, CPubKey heirPubkey)
|
||||
{
|
||||
char destaddr[65], heirFundingAddr[65];
|
||||
|
||||
GetTokensCCaddress1of2(cp, heirFundingAddr, ownerPubkey, heirPubkey);
|
||||
Helper::GetCoinsOrTokensCCaddress1of2(cp, heirFundingAddr, ownerPubkey, heirPubkey);
|
||||
if (tx.vout[voutIndex].scriptPubKey.IsPayToCryptoCondition() != 0) {
|
||||
// NOTE: dimxy it was unsafe 'Getscriptaddress(destaddr,tx.vout[voutIndex].scriptPubKey) > 0' here:
|
||||
if (Getscriptaddress(destaddr, tx.vout[voutIndex].scriptPubKey) && strcmp(destaddr, heirFundingAddr) == 0)
|
||||
@@ -317,6 +321,8 @@ CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t hasHeirSpe
|
||||
fundingtxid = revuint256(fundingtxid);
|
||||
return CScript() << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << fundingtxid << hasHeirSpendingBegun);
|
||||
}
|
||||
|
||||
/*
|
||||
// makes opret for tokens while they are inside Heir contract address space - initial funding
|
||||
CScript EncodeHeirTokensCreateOpRet(uint8_t heirFuncId, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string hearName)
|
||||
{
|
||||
@@ -348,10 +354,11 @@ CScript EncodeHeirTokensOpRet(uint8_t heirFuncId, uint256 tokenid, std::vector<C
|
||||
if (ccType == 2) ss << voutPubkeys[1]; \
|
||||
ss << heirFuncId << fundingtxid << hasHeirSpendingBegun);
|
||||
}
|
||||
*/
|
||||
|
||||
// helper for decode heir opret payload
|
||||
// NOTE: Heir for coins has the same opret as Heir for tokens
|
||||
uint8_t _UnmarshalOpret(std::vector<uint8_t> vopretExtra, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun) {
|
||||
/*uint8_t _UnmarshalOpret(std::vector<uint8_t> vopretExtra, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun) {
|
||||
uint8_t heirFuncId = 0;
|
||||
hasHeirSpendingBegun = 0;
|
||||
|
||||
@@ -363,70 +370,66 @@ uint8_t _UnmarshalOpret(std::vector<uint8_t> vopretExtra, CPubKey& ownerPubkey,
|
||||
} \
|
||||
});
|
||||
|
||||
if (!result /*|| assetFuncId != 't' -- any tx is ok*/)
|
||||
if (!result )// || assetFuncId != 't' -- any tx is ok)
|
||||
return (uint8_t)0;
|
||||
|
||||
return heirFuncId;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* decode opret vout for Heir contract
|
||||
*/
|
||||
template <class Helper> uint8_t _DecodeHeirOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
|
||||
uint8_t _DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
|
||||
{
|
||||
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<uint8_t> vopret;
|
||||
uint8_t evalCodeInOpret = 0;
|
||||
uint256 dummyTokenid;
|
||||
std::vector<CPubKey> voutPubkeysDummy;
|
||||
uint8_t heirFuncId = 0;
|
||||
|
||||
fundingTxidInOpret = zeroid; //to init
|
||||
tokenid = zeroid;
|
||||
|
||||
|
||||
if (typeid(Helper) == typeid(TokenHelper)) { // if caller thinks it is a token
|
||||
|
||||
// First - decode token opret:
|
||||
uint8_t tokenFuncId = DecodeTokenOpRet(scriptPubKey, evalCodeInOpret, tokenid, voutPubkeysDummy, vopretExtra);
|
||||
if (tokenFuncId == 0) {
|
||||
if (!noLogging) std::cerr << "DecodeHeirOpRet() warning: not heir token opret, tokenFuncId=" << (int)tokenFuncId << std::endl;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
if (vopret.size() == 0) {
|
||||
if (!noLogging) std::cerr << "_DecodeHeirOpRet() warning: empty opret" << std::endl;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
else {
|
||||
std::vector<uint8_t> vopret;
|
||||
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
if (vopret.size() == 0) {
|
||||
if (!noLogging) std::cerr << "DecodeHeirOpRet() warning: empty opret" << std::endl;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
evalCodeInOpret = vopret.begin()[0];
|
||||
vopretExtra = std::vector<uint8_t>( vopret.begin()+1, vopret.end() ); // vopretExtra = vopret + 1, get it for futher parsing
|
||||
}
|
||||
|
||||
if (vopretExtra.size() > 1 && evalCodeInOpret == EVAL_HEIR) {
|
||||
evalCodeInOpret = vopret.begin()[0];
|
||||
|
||||
if (vopret.size() > 1 && evalCodeInOpret == EVAL_HEIR) {
|
||||
// NOTE: it unmarshals for all F, A and C
|
||||
uint8_t heirFuncId = _UnmarshalOpret(vopretExtra, ownerPubkey, heirPubkey, inactivityTime, heirName, fundingTxidInOpret, hasHeirSpendingBegun);
|
||||
|
||||
/*std::cerr << "DecodeHeirOpRet()"
|
||||
uint8_t heirFuncId = 0;
|
||||
hasHeirSpendingBegun = 0;
|
||||
|
||||
bool result = E_UNMARSHAL(vopret, { ss >> evalCodeInOpret; ss >> heirFuncId; \
|
||||
if (heirFuncId == 'F') { \
|
||||
ss >> ownerPubkey; ss >> heirPubkey; ss >> inactivityTime; ss >> heirName; \
|
||||
} \
|
||||
else { \
|
||||
ss >> fundingTxidInOpret >> hasHeirSpendingBegun; \
|
||||
} \
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
if (!noLogging) std::cerr << "_DecodeHeirOpRet() could not unmarshal opret, evalCode=" << (int)evalCodeInOpret << std::endl;
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
/* std::cerr << "DecodeHeirOpRet()"
|
||||
<< " heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ')
|
||||
<< " ownerPubkey=" << HexStr(ownerPubkey)
|
||||
<< " heirPubkey=" << HexStr(heirPubkey)
|
||||
<< " heirName=" << heirName << " inactivityTime=" << inactivityTime
|
||||
<< " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << std::endl;*/
|
||||
<< " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << std::endl; */
|
||||
|
||||
|
||||
//if (e == EVAL_HEIR && IS_CHARINSTR(funcId, "FAC"))
|
||||
if (Helper::isMyFuncId(heirFuncId)) {
|
||||
if (isMyFuncId(heirFuncId)) {
|
||||
fundingTxidInOpret = revuint256(fundingTxidInOpret);
|
||||
return heirFuncId;
|
||||
}
|
||||
else {
|
||||
if(!noLogging) std::cerr << "DecodeHeirOpRet() error: unexpected opret, heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ') << std::endl;
|
||||
if(!noLogging) std::cerr << "_DecodeHeirOpRet() unexpected opret type, heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ') << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!noLogging) std::cerr << "DecodeHeirOpRet() error: not a heir opret, vopretExtra.size() == 0 or not EVAL_HEIR evalcode=" << (int)evalCodeInOpret << std::endl;
|
||||
if (!noLogging) std::cerr << "_DecodeHeirOpRet() not a heir opret, vopretExtra.size() == 0 or not EVAL_HEIR evalcode=" << (int)evalCodeInOpret << std::endl;
|
||||
}
|
||||
return (uint8_t)0;
|
||||
}
|
||||
@@ -434,24 +437,24 @@ template <class Helper> uint8_t _DecodeHeirOpRet(CScript scriptPubKey, uint256 &
|
||||
/**
|
||||
* overload for 'F' opret
|
||||
*/
|
||||
template <class Helper> uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging)
|
||||
uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging)
|
||||
{
|
||||
uint256 dummytxid;
|
||||
uint8_t dummyHasHeirSpendingBegun;
|
||||
|
||||
return _DecodeHeirOpRet<Helper>(scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, dummytxid, dummyHasHeirSpendingBegun, noLogging);
|
||||
return _DecodeHeirOpRet(scriptPubKey, ownerPubkey, heirPubkey, inactivityTime, heirName, dummytxid, dummyHasHeirSpendingBegun, noLogging);
|
||||
}
|
||||
|
||||
/**
|
||||
* overload for A, C oprets and AddHeirContractInputs
|
||||
*/
|
||||
template <class Helper> uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256 &tokenid, uint256& fundingtxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
|
||||
uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
|
||||
{
|
||||
CPubKey dummyOwnerPubkey, dummyHeirPubkey;
|
||||
int64_t dummyInactivityTime;
|
||||
std::string dummyHeirName;
|
||||
|
||||
return _DecodeHeirOpRet<Helper>(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingtxidInOpret, hasHeirSpendingBegun, noLogging);
|
||||
return _DecodeHeirOpRet(scriptPubKey, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingtxidInOpret, hasHeirSpendingBegun, noLogging);
|
||||
}
|
||||
|
||||
|
||||
@@ -476,9 +479,22 @@ template <class Helper> uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_
|
||||
// get initial funding tx and set it as initial lasttx:
|
||||
if (myGetTransaction(fundingtxid, fundingtx, hashBlock) && fundingtx.vout.size()) {
|
||||
uint256 dummytxid;
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
// set ownerPubkey and heirPubkey:
|
||||
if ((funcId = DecodeHeirOpRet<Helper>(fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName)) != 0) {
|
||||
CScript heirScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
else {
|
||||
std::cerr << "FindLatestFundingTx() could not decode token opreturn for fundingtxid=" << fundingtxid.GetHex() << '\n';
|
||||
return zeroid;
|
||||
}
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTime, heirName);
|
||||
if (funcId != 0) {
|
||||
// found at least funding tx!
|
||||
//std::cerr << "FindLatestFundingTx() lasttx currently is fundingtx, txid=" << fundingtxid.GetHex() << " opreturn type=" << (char)funcId << '\n';
|
||||
fundingOpretScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey;
|
||||
@@ -493,7 +509,7 @@ template <class Helper> uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_
|
||||
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
|
||||
struct CCcontract_info *cp, C;
|
||||
cp = CCinit(&C, Helper::getMyEval());
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
char coinaddr[64];
|
||||
GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys'
|
||||
|
||||
@@ -531,9 +547,23 @@ template <class Helper> uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_
|
||||
uint8_t tmpFuncId;
|
||||
uint8_t tmphasHeirSpendingBegun;
|
||||
|
||||
if (regtx.vout.size() > 0 &&
|
||||
(tmpFuncId = DecodeHeirOpRet<Helper>(regtx.vout[regtx.vout.size() - 1].scriptPubKey, dummyTokenid, fundingTxidInOpret, tmphasHeirSpendingBegun, true)) != 0 &&
|
||||
fundingtxid == fundingTxidInOpret) {
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
CScript heirScript = regtx.vout[regtx.vout.size() - 1].scriptPubKey;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
else {
|
||||
std::cerr << "FindLatestFundingTx() could not decode token opreturn for fundingtxid=" << fundingtxid.GetHex() << '\n';
|
||||
return zeroid;
|
||||
}
|
||||
}
|
||||
tmpFuncId = DecodeHeirOpRet(heirScript, fundingTxidInOpret, tmphasHeirSpendingBegun, true);
|
||||
|
||||
if (regtx.vout.size() > 0 && tmpFuncId != 0 && fundingtxid == fundingTxidInOpret) {
|
||||
|
||||
if (blockHeight > maxBlockHeight) {
|
||||
maxBlockHeight = blockHeight;
|
||||
@@ -581,12 +611,13 @@ template <class Helper> int64_t Add1of2AddressInputs(struct CCcontract_info* cp,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
|
||||
|
||||
char coinaddr[64];
|
||||
GetTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get address of cryptocondition '1 pubkey of 2 pubkeys'
|
||||
Helper::GetCoinsOrTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get address of cryptocondition '1 of 2 pubkeys'
|
||||
SetCCunspents(unspentOutputs, coinaddr);
|
||||
|
||||
// char markeraddr[64];
|
||||
// CCtxidaddr(markeraddr, fundingtxid);
|
||||
// SetCCunspents(unspentOutputs, markeraddr);
|
||||
|
||||
std::cerr << "Add1of2AddressInputs() using 1of2addr=" << coinaddr << " unspentOutputs.size()=" << unspentOutputs.size() << std::endl;
|
||||
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
|
||||
@@ -602,13 +633,22 @@ template <class Helper> int64_t Add1of2AddressInputs(struct CCcontract_info* cp,
|
||||
uint256 tokenid;
|
||||
uint256 fundingTxidInOpret;
|
||||
uint8_t dummyHasHeirSpendingBegun;
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
|
||||
uint8_t funcId = DecodeHeirOpRet<Helper>(heirtx.vout[heirtx.vout.size() - 1].scriptPubKey, tokenid, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
CScript heirScript = heirtx.vout[heirtx.vout.size() - 1].scriptPubKey;
|
||||
uint8_t funcId = DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, voutPubkeys, vopretExtra);
|
||||
if (funcId != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
|
||||
if ((txid == fundingtxid || fundingTxidInOpret == fundingtxid) &&
|
||||
funcId != 0 &&
|
||||
Helper::isMyFuncId(funcId) &&
|
||||
isMyFuncId(funcId) &&
|
||||
// (typeid(Helper) == typeid(TokenHelper) && IsHeirvout(true, cp, nullptr, tokenid, vintx, voutIndex) > 0) && // deep validation for tokens - not used anymore
|
||||
(voutValue = IsHeirFundingVout(cp, heirtx, voutIndex, ownerPubkey, heirPubkey)) > 0 &&
|
||||
(voutValue = IsHeirFundingVout<Helper>(cp, heirtx, voutIndex, ownerPubkey, heirPubkey)) > 0 &&
|
||||
!myIsutxo_spentinmempool(txid, voutIndex))
|
||||
{
|
||||
std::cerr << "Add1of2AddressInputs() voutValue=" << voutValue << " satoshis=" << it->second.satoshis << '\n';
|
||||
@@ -631,7 +671,7 @@ template <class Helper> int64_t Add1of2AddressInputs(struct CCcontract_info* cp,
|
||||
template <class Helper> int64_t LifetimeHeirContractFunds(struct CCcontract_info* cp, uint256 fundingtxid, CPubKey ownerPubkey, CPubKey heirPubkey)
|
||||
{
|
||||
char coinaddr[64];
|
||||
GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys'
|
||||
Helper::GetCoinsOrTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys'
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount>> addressIndexes;
|
||||
SetCCtxids(addressIndexes, coinaddr);
|
||||
@@ -644,17 +684,24 @@ template <class Helper> int64_t LifetimeHeirContractFunds(struct CCcontract_info
|
||||
CTransaction tx;
|
||||
|
||||
if (GetTransaction(txid, tx, hashBlock, false) && tx.vout.size() > 0) {
|
||||
uint8_t funcId;
|
||||
uint8_t evalCodeTokens = 0;
|
||||
uint256 tokenid;
|
||||
uint256 fundingTxidInOpret;
|
||||
const int32_t ivout = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
uint8_t dummyHasHeirSpendingBegun;
|
||||
|
||||
funcId = DecodeHeirOpRet<Helper>(tx.vout[tx.vout.size() - 1].scriptPubKey, tokenid, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
const int32_t ivout = 0;
|
||||
|
||||
CScript heirScript = tx.vout[tx.vout.size() - 1].scriptPubKey;
|
||||
uint8_t funcId = DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, voutPubkeys, vopretExtra);
|
||||
if (funcId != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, fundingTxidInOpret, dummyHasHeirSpendingBegun, true);
|
||||
|
||||
//std::cerr << "LifetimeHeirContractFunds() found tx=" << txid.GetHex() << " vout[0].nValue=" << subtx.vout[ccVoutIdx].nValue << " opreturn=" << (char)funcId << '\n';
|
||||
|
||||
if (funcId != 0 && (txid == fundingtxid || fundingTxidInOpret == fundingtxid) && Helper::isMyFuncId(funcId) && !Helper::isSpendingTx(funcId)
|
||||
if (funcId != 0 && (txid == fundingtxid || fundingTxidInOpret == fundingtxid) && isMyFuncId(funcId) && !isSpendingTx(funcId)
|
||||
/* && !myIsutxo_spentinmempool(txid, ccVoutIdx) */) // include also tx in mempool
|
||||
{
|
||||
total += it->second; // dont do this: tx.vout[ivout].nValue; // in vin[0] always is the pay to 1of2 addr (funding or change)
|
||||
@@ -678,7 +725,7 @@ template <typename Helper> std::string HeirFund(uint64_t txfee, int64_t amount,
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
cp = CCinit(&C, Helper::getMyEval());
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
|
||||
@@ -719,7 +766,6 @@ template <typename Helper> std::string HeirFund(uint64_t txfee, int64_t amount,
|
||||
|
||||
// add change for txfee and opreturn vouts and sign tx:
|
||||
return (FinalizeCCTx(0, cp, mtx, myPubkey, txfee,
|
||||
// CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'F' << myPubkey << heirPubkey << inactivityTimeSec << heirName)));
|
||||
Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName)));
|
||||
}
|
||||
else // TODO: need result return unification with heiradd and claim
|
||||
@@ -759,7 +805,7 @@ template <class Helper> UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in
|
||||
uint8_t funcId;
|
||||
uint8_t hasHeirSpendingBegun = 0;
|
||||
|
||||
cp = CCinit(&C, Helper::getMyEval());
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
@@ -790,7 +836,7 @@ template <class Helper> UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in
|
||||
std::cerr << "HeirAdd() adding markeraddr=" << markeraddr << '\n'; */
|
||||
|
||||
// add cryptocondition to spend this funded amount for either pk
|
||||
mtx.vout.push_back(MakeCC1of2vout(Helper::getMyEval(), amount, ownerPubkey, heirPubkey)); // using always pubkeys from OP_RETURN in order to not mixing them up!
|
||||
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey)); // using always pubkeys from OP_RETURN in order to not mixing them up!
|
||||
|
||||
if (inputs > amount)
|
||||
change = (inputs - amount); // -txfee <-- txfee pays user
|
||||
@@ -801,7 +847,7 @@ template <class Helper> UniValue HeirAdd(uint256 fundingtxid, uint64_t txfee, in
|
||||
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
|
||||
}
|
||||
|
||||
// add 1of2 vout validation pubkeys:
|
||||
// add 1of2 vout validation pubkeys - needed only for tokens:
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(ownerPubkey);
|
||||
voutTokenPubkeys.push_back(heirPubkey);
|
||||
@@ -863,8 +909,6 @@ template <typename Helper>UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee
|
||||
std::string heirName;
|
||||
uint8_t hasHeirSpendingBegun = 0;
|
||||
|
||||
|
||||
//cp = CCinit(&C, Helper::getMyEval());
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
@@ -924,7 +968,7 @@ template <typename Helper>UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee
|
||||
|
||||
// change to 1of2 funding addr:
|
||||
if (change != 0) { // vout[1]
|
||||
mtx.vout.push_back(MakeCC1of2vout(Helper::getMyEval(), change, ownerPubkey, heirPubkey)); // using always pubkeys from OP_RETURN in order to not mixing them up!
|
||||
mtx.vout.push_back(Helper::make1of2Vout(change, ownerPubkey, heirPubkey)); // using always pubkeys from OP_RETURN in order to not mixing them up!
|
||||
}
|
||||
|
||||
// add marker vout:
|
||||
@@ -937,7 +981,7 @@ template <typename Helper>UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee
|
||||
uint8_t myprivkey[32];
|
||||
char coinaddr[64];
|
||||
// set priv key addresses in CC structure:
|
||||
GetTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey);
|
||||
Helper::GetCoinsOrTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey);
|
||||
Myprivkey(myprivkey);
|
||||
|
||||
////fprintf(stderr,"HeirClaim() before setting unspendable CC addr2= (%s) addr3= (%s)\n", cp->unspendableaddr2, cp->unspendableaddr3);
|
||||
@@ -945,9 +989,9 @@ template <typename Helper>UniValue HeirClaim(uint256 fundingtxid, uint64_t txfee
|
||||
//CCaddr3set(cp, Helper::getMyEval(), heirPubkey, myprivkey, coinaddr);
|
||||
////fprintf(stderr, "HeirClaim() after setting unspendable CC addr2=(%s) addr3=(%s)\n", cp->unspendableaddr2, cp->unspendableaddr3);
|
||||
|
||||
CCaddrTokens1of2set(cp, ownerPubkey, heirPubkey, coinaddr);
|
||||
Helper::CCaddrCoinsOrTokens1of2set(cp, ownerPubkey, heirPubkey, coinaddr);
|
||||
|
||||
// add 1of2 vout validation pubkeys:
|
||||
// add 1of2 vout validation pubkeys (this is for tokens):
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
voutTokenPubkeys.push_back(ownerPubkey);
|
||||
voutTokenPubkeys.push_back(heirPubkey);
|
||||
@@ -1017,15 +1061,22 @@ UniValue HeirInfo(uint256 fundingtxid)
|
||||
// get initial funding tx and set it as initial lasttx:
|
||||
if (myGetTransaction(fundingtxid, fundingtx, hashBlock) && fundingtx.vout.size()) {
|
||||
|
||||
int32_t heirType = NOT_HEIR;
|
||||
const bool noLogging = true;
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
|
||||
if (DecodeHeirOpRet<CoinHelper>(fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey, dummyTokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, noLogging) == 'F')
|
||||
heirType = HEIR_COINS;
|
||||
else if (DecodeHeirOpRet<TokenHelper>(fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, noLogging) == 'F')
|
||||
CScript heirScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey;
|
||||
int32_t heirType = HEIR_COINS;
|
||||
|
||||
uint8_t funcId = DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, voutPubkeys, vopretExtra);
|
||||
if (funcId != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
heirType = HEIR_TOKENS;
|
||||
else
|
||||
{
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, noLogging);
|
||||
|
||||
if( funcId == 0 ) {
|
||||
std::cerr << "HeirInfo() initial tx F not found for this fundingtx" << std::endl;
|
||||
result.push_back(Pair("result", "error"));
|
||||
result.push_back(Pair("error", "initial tx F not found"));
|
||||
@@ -1033,10 +1084,7 @@ UniValue HeirInfo(uint256 fundingtxid)
|
||||
}
|
||||
|
||||
struct CCcontract_info *cp, C;
|
||||
if (heirType == HEIR_COINS)
|
||||
cp = CCinit(&C, CoinHelper::getMyEval());
|
||||
else
|
||||
cp = CCinit(&C, TokenHelper::getMyEval());
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
|
||||
uint8_t hasHeirSpendingBegun = 0;
|
||||
|
||||
@@ -1174,14 +1222,24 @@ template <typename Helper>void _HeirList(struct CCcontract_info *cp, UniValue &r
|
||||
|
||||
//std::cerr << "HeirList() checking txid=" << txid.GetHex() << " vout=" << vout << '\n';
|
||||
|
||||
CTransaction inittx;
|
||||
if (GetTransaction(txid, inittx, hashBlock, false) != 0 && (inittx.vout.size() - 1) > 0) {
|
||||
CTransaction fundingtx;
|
||||
if (GetTransaction(txid, fundingtx, hashBlock, false) != 0 && (fundingtx.vout.size() - 1) > 0) {
|
||||
CPubKey ownerPubkey, heirPubkey;
|
||||
std::string heirName;
|
||||
int64_t inactivityTimeSec;
|
||||
const bool noLogging = true;
|
||||
|
||||
uint8_t funcId = DecodeHeirOpRet<Helper>(inittx.vout[inittx.vout.size() - 1].scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, noLogging);
|
||||
uint8_t evalCodeTokens = 0;
|
||||
uint256 tokenid;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
|
||||
CScript heirScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey;
|
||||
uint8_t funcId = DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, voutPubkeys, vopretExtra);
|
||||
if (funcId != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, noLogging);
|
||||
|
||||
// note: if it is not Heir token funcId would be equal to 0
|
||||
if (funcId == 'F') {
|
||||
|
||||
@@ -14,19 +14,21 @@
|
||||
CScript EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName);
|
||||
CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan);
|
||||
// makes token opret
|
||||
CScript EncodeHeirTokensCreateOpRet(uint8_t funcid, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string hearName);
|
||||
CScript EncodeHeirTokensOpRet(uint8_t funcid, uint256 tokenid, std::vector<CPubKey> voutPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan);
|
||||
//CScript EncodeHeirTokensCreateOpRet(uint8_t funcid, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string hearName);
|
||||
//CScript EncodeHeirTokensOpRet(uint8_t funcid, uint256 tokenid, std::vector<CPubKey> voutPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan);
|
||||
|
||||
template <class Helper> uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan);
|
||||
template <class Helper> uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256 &tokenid, uint256& fundingtxid, uint8_t &isHeirSpendingBegan, bool noLogging = false);
|
||||
template <class Helper> uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging = false);
|
||||
uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxid, uint8_t &isHeirSpendingBegan, bool noLogging = false);
|
||||
uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging = false);
|
||||
|
||||
inline static bool isMyFuncId(uint8_t funcid) { return IS_CHARINSTR(funcid, "FAC"); }
|
||||
inline static bool isSpendingTx(uint8_t funcid) { return (funcid == 'C'); }
|
||||
|
||||
|
||||
// helper class to allow polymorphic behaviour for HeirXXX() functions in case of coins
|
||||
class CoinHelper {
|
||||
public:
|
||||
|
||||
static bool isMyFuncId(uint8_t funcid) { return IS_CHARINSTR(funcid, "FAC"); }
|
||||
static uint8_t getMyEval() { return EVAL_HEIR; }
|
||||
static int64_t addOwnerInputs(struct CCcontract_info* cp, uint256 dummyid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) {
|
||||
return AddNormalinputs(mtx, ownerPubkey, total, maxinputs);
|
||||
}
|
||||
@@ -40,43 +42,58 @@ public:
|
||||
static CScript makeClaimOpRet(uint256 dummyid, std::vector<CPubKey> dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
|
||||
return EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan);
|
||||
}
|
||||
|
||||
static bool isSpendingTx(uint8_t funcid) { return (funcid == 'C'); }
|
||||
|
||||
static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) {
|
||||
return MakeCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey);
|
||||
}
|
||||
static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) {
|
||||
return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG);
|
||||
}
|
||||
static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) {
|
||||
return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG);
|
||||
}
|
||||
static bool GetCoinsOrTokensCCaddress1of2(struct CCcontract_info* cp, char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) {
|
||||
return GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey);
|
||||
}
|
||||
static void CCaddrCoinsOrTokens1of2set(struct CCcontract_info* cp, CPubKey ownerPubkey, CPubKey heirPubkey, char *coinaddr) {
|
||||
CCaddr1of2set(cp, ownerPubkey, heirPubkey, coinaddr);
|
||||
}
|
||||
};
|
||||
|
||||
// helper class to allow polymorphic behaviour for HeirXXX() functions in case of tokens
|
||||
class TokenHelper {
|
||||
public:
|
||||
static bool isMyFuncId(uint8_t funcid) { return IS_CHARINSTR(funcid, "FAC"); }
|
||||
static uint8_t getMyEval() { return EVAL_TOKENS; }
|
||||
static int64_t addOwnerInputs(struct CCcontract_info* cp, uint256 tokenid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) {
|
||||
return AddTokenCCInputs(cp, mtx, ownerPubkey, tokenid, total, maxinputs);
|
||||
}
|
||||
|
||||
static CScript makeCreateOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName) {
|
||||
return EncodeHeirTokensCreateOpRet((uint8_t)'F', tokenid, voutTokenPubkeys, ownerPubkey, heirPubkey, inactivityTimeSec, heirName);
|
||||
return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys,
|
||||
EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName));
|
||||
}
|
||||
static CScript makeAddOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
|
||||
return EncodeHeirTokensOpRet((uint8_t)'A', tokenid, voutTokenPubkeys, fundingtxid, isHeirSpendingBegan);
|
||||
return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys,
|
||||
EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan));
|
||||
}
|
||||
static CScript makeClaimOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
|
||||
return EncodeHeirTokensOpRet((uint8_t)'C', tokenid, voutTokenPubkeys, fundingtxid, isHeirSpendingBegan);
|
||||
return EncodeTokenOpRet((uint8_t)'t', EVAL_TOKENS, tokenid, voutTokenPubkeys,
|
||||
EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan));
|
||||
}
|
||||
|
||||
static bool isSpendingTx(uint8_t funcid) { return (funcid == 'C'); }
|
||||
|
||||
static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) {
|
||||
return MakeTokensCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey);
|
||||
}
|
||||
static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) {
|
||||
return MakeCC1vout(EVAL_TOKENS, amount, myPubkey);
|
||||
return MakeTokensCC1vout(EVAL_HEIR, amount, myPubkey);
|
||||
}
|
||||
static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) {
|
||||
return MakeCC1vout(EVAL_TOKENS, amount, myPubkey);
|
||||
return MakeTokensCC1vout(EVAL_HEIR, amount, myPubkey);
|
||||
}
|
||||
static bool GetCoinsOrTokensCCaddress1of2(struct CCcontract_info* cp, char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) {
|
||||
return GetTokensCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey);
|
||||
}
|
||||
|
||||
static void CCaddrCoinsOrTokens1of2set(struct CCcontract_info* cp, CPubKey ownerPubkey, CPubKey heirPubkey, char *coinaddr) {
|
||||
CCaddrTokens1of2set(cp, ownerPubkey, heirPubkey, coinaddr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -307,11 +324,8 @@ public:
|
||||
return eval->Invalid(stream.str().c_str()); // ... if not, return 'invalid'
|
||||
}
|
||||
}
|
||||
|
||||
ival++; // advance to the next vout
|
||||
|
||||
}
|
||||
|
||||
//std::cerr << "COutputValidationPlan::validate() returns with true" << std::endl;
|
||||
return true;
|
||||
}
|
||||
@@ -350,14 +364,12 @@ private:
|
||||
return true; // validation OK
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//std::map<int32_t, ValidatorsRow> m_mapValidators;
|
||||
std::vector< std::pair<int32_t, ValidatorsRow> > m_arrayValidators;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CNormalInputIdentifier : CInputIdentifierBase {
|
||||
public:
|
||||
CNormalInputIdentifier(CCcontract_info* cp) : CInputIdentifierBase(cp) {}
|
||||
@@ -390,13 +402,28 @@ public:
|
||||
virtual bool validateVout(CTxOut vout, std::string& message) const
|
||||
{
|
||||
//std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl;
|
||||
uint8_t funcId;
|
||||
CPubKey ownerPubkey, heirPubkey;
|
||||
int64_t inactivityTime;
|
||||
std::string heirName;
|
||||
uint256 tokenid;
|
||||
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
if ((funcId = DecodeHeirOpRet<Helper>(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName)) == 0) {
|
||||
CScript heirScript = m_fundingOpretScript;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
else {
|
||||
message = m_customMessage + std::string(" invalid token opreturn format");
|
||||
std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTime, heirName, false);
|
||||
if (funcId == 0) {
|
||||
message = m_customMessage + std::string(" invalid opreturn format");
|
||||
std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl;
|
||||
return false;
|
||||
@@ -443,21 +470,35 @@ public:
|
||||
{
|
||||
//std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl;
|
||||
|
||||
uint8_t funcId;
|
||||
CPubKey ownerPubkey, heirPubkey;
|
||||
int64_t inactivityTime;
|
||||
std::string heirName;
|
||||
uint256 tokenid;
|
||||
|
||||
///std::cerr << "CMyPubkeyVoutValidator::validateVout() m_opRetScript=" << m_opRetScript.ToString() << std::endl;
|
||||
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
CScript ownerScript;
|
||||
CScript heirScript = m_fundingOpretScript;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
}
|
||||
else {
|
||||
message = std::string("invalid token opreturn format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// get both pubkeys:
|
||||
if ((funcId = DecodeHeirOpRet<Helper>(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName)) == 0) {
|
||||
uint8_t funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTime, heirName, false);
|
||||
if (funcId == 0) {
|
||||
message = std::string("invalid opreturn format");
|
||||
return false;
|
||||
}
|
||||
|
||||
CScript ownerScript;
|
||||
CScript heirScript;
|
||||
if (m_checkNormals) {
|
||||
ownerScript = CoinHelper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey;
|
||||
heirScript = CoinHelper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey;
|
||||
@@ -474,7 +515,6 @@ public:
|
||||
// this is vout to owner or heir addr:
|
||||
//std::cerr << "CMyPubkeyVoutValidator::validateVout() exits with true" << std::endl;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
std::cerr << "CMyPubkeyVoutValidator::validateVout() exits with false (not the owner's or heir's addresses)" << std::endl;
|
||||
@@ -503,15 +543,28 @@ public:
|
||||
{
|
||||
//std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl;
|
||||
|
||||
uint8_t funcId;
|
||||
CPubKey ownerPubkey, heirPubkey;
|
||||
int64_t inactivityTime;
|
||||
std::string heirName;
|
||||
uint256 tokenid;
|
||||
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
CScript heirScript = m_fundingOpretScript;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
} else {
|
||||
message = std::string("invalid token opreturn format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// get heir pubkey:
|
||||
if ((funcId = DecodeHeirOpRet<Helper>(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, false)) == 0) {
|
||||
uint8_t funcId = DecodeHeirOpRet(heirScript, ownerPubkey, heirPubkey, inactivityTime, heirName, false);
|
||||
if (funcId == 0) {
|
||||
message = std::string("invalid opreturn format");
|
||||
return false;
|
||||
}
|
||||
@@ -560,28 +613,54 @@ public:
|
||||
{
|
||||
//std::cerr << "COpRetValidator::validateVout() entered" << std::endl;
|
||||
|
||||
uint8_t funcId, initialFuncId; // do not check heir name
|
||||
uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid, initialTokenid;
|
||||
uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid = zeroid, initialTokenid = zeroid;
|
||||
uint8_t dummyIsHeirSpendingBegan;
|
||||
|
||||
if ((funcId = DecodeHeirOpRet<Helper>(vout.scriptPubKey, tokenid, fundingTxidInOpret, dummyIsHeirSpendingBegan)) == 0) {
|
||||
uint8_t evalCodeTokens = 0;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> dummyVoutPubkeys;
|
||||
|
||||
CScript heirScript = vout.scriptPubKey;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, tokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
} else {
|
||||
message = std::string("invalid token opreturn format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t funcId = DecodeHeirOpRet(heirScript, fundingTxidInOpret, dummyIsHeirSpendingBegan);
|
||||
if (funcId == 0) {
|
||||
message = std::string("invalid opreturn format");
|
||||
return false;
|
||||
}
|
||||
if ((initialFuncId = DecodeHeirOpRet<Helper>(m_fundingOpretScript, initialTokenid, dummyTxid, dummyIsHeirSpendingBegan)) == 0) {
|
||||
|
||||
heirScript = m_fundingOpretScript;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (DecodeTokenOpRet(heirScript, evalCodeTokens, initialTokenid, dummyVoutPubkeys, vopretExtra) != 0) {
|
||||
heirScript = CScript(vopretExtra);
|
||||
} else {
|
||||
message = std::string("invalid initial token opreturn format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t initialFuncId = DecodeHeirOpRet(heirScript, dummyTxid, dummyIsHeirSpendingBegan);
|
||||
if (initialFuncId == 0) {
|
||||
message = std::string("invalid initial tx opreturn format");
|
||||
return false;
|
||||
}
|
||||
|
||||
// validation rules:
|
||||
if (!Helper::isMyFuncId(funcId)) {
|
||||
if (!isMyFuncId(funcId)) {
|
||||
message = std::string("invalid funcid in opret");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tokenid != initialTokenid ) {
|
||||
message = std::string("invalid tokenid in opret");
|
||||
return false;
|
||||
if (typeid(Helper) == typeid(TokenHelper)) {
|
||||
if (tokenid != initialTokenid) {
|
||||
message = std::string("invalid tokenid in opret");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user