Skip to content

Commit

Permalink
tokens cc fixes:
Browse files Browse the repository at this point in the history
fix tokentransfermany vout pubkeys for change;
fix v0 opret compat by use 'C' 'T' funcids
  • Loading branch information
dimxy committed May 2, 2020
1 parent 6834c4c commit 474f1f8
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 44 deletions.
10 changes: 8 additions & 2 deletions src/cc/CCtokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, Eval* eval, c
if (mapinputs.size() > 0 && mapinputs.size() == mapoutputs.size())
{
for(auto const &m : mapinputs) {
LOGSTREAM(cctokens_log, CCLOG_DEBUG1, stream << indentStr << "TokensExactAmounts() inputs[" << m.first.GetHex() << "]=" << m.second << " outputs=" << mapoutputs[m.first] << std::endl);
if (m.second != mapoutputs[m.first]) {
errorStr = "inputs not equal outputs for tokenid=" + m.first.GetHex();
return false;
Expand Down Expand Up @@ -1310,8 +1311,13 @@ UniValue TokenAddTransferVout(CMutableTransaction &mtx, struct CCcontract_info *
CAmount CCchange = 0L;
if (inputs > amount)
CCchange = (inputs - amount);
if (CCchange != 0)
mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, CCchange, mypk));
if (CCchange != 0) {
CScript opret = EncodeTokenOpRetV1(tokenid, {mypk}, {});
vscript_t vopret;
GetOpReturnData(opret, vopret);
std::vector<vscript_t> vData { vopret };
mtx.vout.push_back(MakeTokensCC1vout(destEvalCode, CCchange, mypk, &vData));
}

// add probe pubkeys to detect token vouts in tx
//std::vector<CPubKey> voutTokenPubkeys;
Expand Down
47 changes: 12 additions & 35 deletions src/cc/CCtokenutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,6 @@
#define MAY2020_NNELECTION_HARDFORK 1590926400
#endif

/*
static int64_t get_chain_active_tip_timestamp()
{
if (chainActive.LastTip() != 0)
{
CBlockIndex *pIndex = chainActive.LastTip();
return pIndex->GetBlockTime();
}
return 0L;
}*/

// return true if new v1 version activation time is passed or chain is always works v1
// return false if v0 is still active
Expand Down Expand Up @@ -67,17 +57,6 @@ bool TokensIsVer1Active(const Eval *eval)
return isTimev1;
}

// NOTE: this inital tx won't be used by other contract
// for tokens to be used there should be at least one 't' tx with other contract's custom opret
/*CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible)
{
std::vector<vscript_t> oprets;
if(!vopretNonfungible.empty())
oprets.push_back(vopretNonfungible);
return EncodeTokenCreateOpRetV1(funcid, origpubkey, name, description, oprets);
}*/

// compatibility code
// adds old-style opretid
// for create oprets treat EVAL_IMPORTCOIN as import tx
Expand Down Expand Up @@ -151,7 +130,7 @@ CScript EncodeTokenCreateOpRetV1(const std::vector<uint8_t> &origpubkey, const s

CScript opret;
uint8_t evalcode = EVAL_TOKENS;
uint8_t funcid = 'c'; // override the param
uint8_t funcid = 'C'; // 'C' indicates v1
uint8_t version = 1;

opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << version << origpubkey << name << description;
Expand All @@ -178,7 +157,7 @@ CScript EncodeTokenOpRetV1(uint256 tokenid, const std::vector<CPubKey> &voutPubk
}

CScript opret;
uint8_t tokenFuncId = 't';
uint8_t tokenFuncId = 'T'; // 'T' indicates v1
uint8_t evalCodeInOpret = EVAL_TOKENS;
uint8_t version = 1;

Expand Down Expand Up @@ -221,7 +200,7 @@ uint8_t DecodeTokenCreateOpRetV1(const CScript &scriptPubKey, std::vector<uint8_

// try to decode old version:
std::vector<std::pair<uint8_t, vscript_t>> opretswithid;
if ((funcid = tokensv0::DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretswithid)) != 0 && origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) // check pubkey is parsed okay
if ((funcid = tokensv0::DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretswithid)) != 0) // check pubkey is parsed okay
{
for (auto const & oi : opretswithid)
oprets.push_back(oi.second);
Expand All @@ -231,18 +210,16 @@ uint8_t DecodeTokenCreateOpRetV1(const CScript &scriptPubKey, std::vector<uint8_


GetOpReturnData(scriptPubKey, vopret);

if (vopret.size() > 2 && vopret.begin()[0] == EVAL_TOKENS && IsTokenCreateFuncid(vopret.begin()[1]))
if (vopret.size() > 2 && vopret[0] == EVAL_TOKENS && vopret[1] == 'C')
{
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> version; ss >> origpubkey; ss >> name; ss >> description;
while (!ss.eof()) {
ss >> vblob;
oprets.push_back(vblob); // put oprets
}))
{
return(funcid);
}

return 'c'; // convert to old-style funcid
}
}
LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "incorrect token create opret" << std::endl);
return (uint8_t)0;
Expand All @@ -263,7 +240,7 @@ uint8_t DecodeTokenOpRetV1(const CScript scriptPubKey, uint256 &tokenid, std::ve

// try to decode old opreturn version (check tokenid is not null):
std::vector<std::pair<uint8_t, vscript_t>> opretswithid;
if ((funcId = tokensv0::DecodeTokenOpRet(scriptPubKey, evalCodeOld, tokenid, voutPubkeys, opretswithid)) != 0 && (funcId =='c' || !tokenid.IsNull())) // if 't' tokenid must be not null
if ((funcId = tokensv0::DecodeTokenOpRet(scriptPubKey, evalCodeOld, tokenid, voutPubkeys, opretswithid)) != 0)
{
for (auto const & oi : opretswithid)
oprets.push_back(oi.second);
Expand All @@ -276,6 +253,7 @@ uint8_t DecodeTokenOpRetV1(const CScript scriptPubKey, uint256 &tokenid, std::ve

if (vopret.size() > 2)
{
voutPubkeys.clear();
evalCode = vopret[0];
if (evalCode != EVAL_TOKENS) {
LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "incorrect evalcode in tokens opret" << std::endl);
Expand All @@ -287,15 +265,15 @@ uint8_t DecodeTokenOpRetV1(const CScript scriptPubKey, uint256 &tokenid, std::ve

switch (funcId)
{
case 'c':
case 'C':
funcId = DecodeTokenCreateOpRetV1(scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets);
if (funcId != 0) {
// add orig pubkey
voutPubkeys.push_back(pubkey2pk(vorigPubkey));
}
return funcId;
return funcId; // should be converted to old-style funcid

case 't':
case 'T':
if (E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> version; ss >> tokenid; ss >> pkCount;
if (pkCount >= 1) ss >> voutPubkey1;
if (pkCount >= 2) ss >> voutPubkey2; // pkCountshould not be > 2
Expand All @@ -305,12 +283,11 @@ uint8_t DecodeTokenOpRetV1(const CScript scriptPubKey, uint256 &tokenid, std::ve
}))
{
tokenid = revuint256(tokenid);
voutPubkeys.clear();
if (voutPubkey1.IsValid())
voutPubkeys.push_back(voutPubkey1);
if (voutPubkey2.IsValid())
voutPubkeys.push_back(voutPubkey2);
return funcId;
return 't'; // convert to old style funcid
}
LOGSTREAMFN(cctokens_log, CCLOG_INFO, stream << "bad opret format for 'T'," << " pkCount=" << (int)pkCount << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
Expand Down
12 changes: 6 additions & 6 deletions src/cc/old/CCtokenutils_v0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t>
return(funcid);
}
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenCreateOpRet() incorrect token create opret" << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenCreateOpRet() incorrect token create opret" << std::endl);
return (uint8_t)0;
}

Expand All @@ -200,7 +200,7 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
{
evalCodeTokens = script[0];
if (evalCodeTokens != EVAL_TOKENS) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect evalcode in tokens opret" << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() incorrect evalcode in tokens opret" << std::endl);
return (uint8_t)0;
}

Expand Down Expand Up @@ -238,7 +238,7 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
}))
{
if (!(ccType >= 0 && ccType <= 2)) { //incorrect ccType
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
}

Expand All @@ -264,16 +264,16 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui

return(funcId);
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() bad opret format," << " ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() bad opret format," << " ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;

default:
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl);
return (uint8_t)0;
}
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() empty opret, could not parse" << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() empty opret, could not parse" << std::endl);
}
return (uint8_t)0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/tokensrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ UniValue tokentransfermany(const UniValue& params, bool fHelp, const CPubKey& re
CCerror.clear();

if ( fHelp || params.size() < 3)
throw runtime_error("tokentransfermany tokenid1,tokenid2,... destpubkey amount \n");
throw runtime_error("tokentransfermany tokenid1 tokenid2 ... destpubkey amount \n");
if ( ensure_CCrequirements(EVAL_TOKENS) < 0 )
throw runtime_error(CC_REQUIREMENTS_MSG);

Expand Down

0 comments on commit 474f1f8

Please sign in to comment.