diff --git a/README.md b/README.md index f08c388114f..9a00be2da70 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To NFT and Beyond #### What Tokel offers: - The blockchain that facilitates the tokens and NFTs. -- An open-sourced all-in-one ]GUI application](https://github.com/TokelPlatform/tokel_dapp). +- An open-sourced all-in-one [GUI application](https://github.com/TokelPlatform/tokel_dapp). - DEX functionality for all tokens/NFTs created on Tokel. - A free-to-use test blockchain (TKLTEST). - Easy to use integrations (nSPV) @@ -60,6 +60,7 @@ https://github.com/TokelPlatform/tokel_dapp - Tokel Website: [https://tokel.io](https://tokel.io) - Tokel Block Explorer: [https://explorer.tokel.io](https://explorer.tokel.io) - Tokel Discord: [Tokel Discord Invitation](http://discord.tokel.io) +- Tokel Blog: [Tokel Blog](https://tokel.io/blog/) - Email: [contact@tokel.io](mailto:contact@tokel.io) - Whitepaper: [Tokel Paper](https://tokel.io/TokelPaper1stEdition.pdf) - Knowledgebase & How-to: [Tokel Documentation](https://docs.tokel.io) diff --git a/configure.ac b/configure.ac index 4177bee26da..71ae7c0a4ae 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ dnl komodo codebase version define(_KOMODO_VERSION, 60000) dnl tokel codebase version -define(_TOKEL_VERSION, 30100) +define(_TOKEL_VERSION, 30200) AC_DEFINE(KOMODO_VERSION, _KOMODO_VERSION, [Komodo Version]) AC_DEFINE(TOKEL_VERSION, _TOKEL_VERSION, [Tokel Version]) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index 27af5501ef0..453758e39da 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -80,7 +80,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more") + print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confs_req) time.sleep(5) else: print("\ntx confirmed") @@ -249,7 +249,7 @@ def validate_tx_pattern(txid): def validate_raddr_pattern(addr): if not isinstance(addr, str): return False - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") if address_pattern.match(addr): return True else: diff --git a/qa/pytest_komodo/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py index 4117421930a..99d0bfafa1f 100644 --- a/qa/pytest_komodo/basic/test_blocks.py +++ b/qa/pytest_komodo/basic/test_blocks.py @@ -342,6 +342,8 @@ def test_getrawmempool(self, test_params): res = rpc.getrawmempool(True) assert res.get(txid).get('height') == kvheight + ''' + # kv not supported def test_kvsearch(self, test_params): test_values = { 'key': 'search_key', @@ -358,6 +360,7 @@ def test_kvsearch(self, test_params): assert res.get('key') == test_values['key'] assert res.get('keylen') == keylen assert res.get('value') == test_values['value'] + ''' def test_notaries(self, test_params): rpc = test_params.get('node1').get('rpc') diff --git a/qa/pytest_komodo/cc_modules/test_faucet.py b/qa/pytest_komodo/cc_modules/test_faucet.py index 876c69bf89b..7169fb32cf2 100644 --- a/qa/pytest_komodo/cc_modules/test_faucet.py +++ b/qa/pytest_komodo/cc_modules/test_faucet.py @@ -100,7 +100,7 @@ class TestFaucetCCe2e: def test_faucet_addresses(self, test_params): rpc1 = test_params.get('node1').get('rpc') pubkey = test_params.get('node1').get('pubkey') - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") # normal R-addr res = rpc1.faucetaddress() for key in res.keys(): diff --git a/qa/pytest_komodo/cc_modules/test_heir.py b/qa/pytest_komodo/cc_modules/test_heir.py index a5659cf9a5f..bac1c33e9fa 100644 --- a/qa/pytest_komodo/cc_modules/test_heir.py +++ b/qa/pytest_komodo/cc_modules/test_heir.py @@ -189,7 +189,7 @@ class TestHeirFunc: def test_heir_addresses(self, test_params): rpc1 = test_params.get('node1').get('rpc') pubkey = test_params.get('node2').get('pubkey') - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + address_pattern = re.compile(r"[RC][a-zA-Z0-9]{33}\Z") # normal R-addr # verify all keys look like valid AC addrs res = rpc1.faucetaddress('') diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index 71c078ed7a9..8b7a5ce3da8 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -27,14 +27,14 @@ def test_oracles(test_params): for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' result = rpc.oraclesaddress(pubkey) assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' # there are no oracles created yet if is_fresh_chain: @@ -247,6 +247,7 @@ def test_oracles(test_params): # checking data for s type result = rpc.oraclessamples(globals()["oracle_{}".format("s")], batonaddr_s, "1") + print('result=', result) assert "['Anton']" == str(result["samples"][0]['data']) # checking data for S type diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 376247db756..462d3a34b23 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -30,29 +30,24 @@ def test_token(test_params): for v in ["", "v2"] : - result = call_token_rpc(rpc, "token"+v+"address") - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = call_token_rpc(rpc, "token"+v+"address", pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = call_token_rpc(rpc, "assetsaddress") - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = call_token_rpc(rpc, "assetsaddress", pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' + result = call_token_rpc(rpc, "token"+v+"indexkey", pubkey) + if v == '': # for v2 a diff result + assert_success(result) + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' or result[x][0] == 'C' + else : # v2 index keys: + for x in result: + assert x[0] == 'C' + + result = call_token_rpc(rpc, "assets"+v+"indexkey", pubkey) + if v == '': # for v2 a diff result + assert_success(result) + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' or result[x][0] == 'C' + else : # v2 index key + assert result[0] == 'C' # there are no tokens created yet # TODO: this test conflicts with heir test because token creating for heir diff --git a/qa/pytest_komodo/cc_modules/test_unspentccundex.py b/qa/pytest_komodo/cc_modules/test_unspentccundex.py index bf72dd61793..9e50074f724 100644 --- a/qa/pytest_komodo/cc_modules/test_unspentccundex.py +++ b/qa/pytest_komodo/cc_modules/test_unspentccundex.py @@ -28,7 +28,7 @@ def test_ccindex(test_params): assert_success(result) for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' # get token cc address for pubkey: result = rpc.tokenaddress(pubkey) @@ -36,7 +36,7 @@ def test_ccindex(test_params): pubkeyTokenCCAddress = "" for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' if x == 'pubkey Tokens CC Address': pubkeyTokenCCAddress = result[x] @@ -46,7 +46,7 @@ def test_ccindex(test_params): pubkey1TokenCCAddress = "" for x in result.keys(): if x.find('ddress') > 0: - assert result[x][0] == 'R' + assert result[x][0] == 'R' or result[x][0] == 'C' if x == 'pubkey Tokens CC Address': pubkey1TokenCCAddress = result[x] diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py index 001817b1cdf..92bfb960e0f 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/cc_modules/util.py @@ -34,7 +34,7 @@ def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more") + print("\ntx is not confirmed yet! Let's wait a little more", txid, 'confs=', confirmations_amount, 'required=', confs_req) time.sleep(5) else: print("\ntx confirmed") diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 3a33b5dba94..daa2597106e 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -378,7 +378,7 @@ bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk,bool mixed) if (payoutCond.get() != 0 ) { //if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } @@ -404,7 +404,7 @@ static bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode1, uint8_t evalc { //if (mixed) // CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } @@ -425,7 +425,7 @@ bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubK if ( payoutCond.get() != 0 ) { //if (mixed) CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr,CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } @@ -443,7 +443,7 @@ bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey { //if (mixed) // CCtoAnon(payoutCond.get()); - Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), CC_MIXED_MODE_SUBVER_0)); + Getscriptaddress(destaddr, CCPubKey(payoutCond.get(), mixed ? CC_MIXED_MODE_SUBVER_0 : CC_OLD_V1_SUBVER)); } return(destaddr[0] != 0); } diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp index 0724f2fea7c..bc2875adfcb 100644 --- a/src/cc/betprotocol.cpp +++ b/src/cc/betprotocol.cpp @@ -264,7 +264,7 @@ bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransact if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) return Error("couldnt-get-parent"); - if (GetCurrentHeight() < sessionBlock.GetHeight() + waitBlocks) + if (GetCurrentHeightCompat() < sessionBlock.GetHeight() + waitBlocks) return Invalid("dispute-too-soon"); // Not yet } diff --git a/src/cc/disputepayout.cpp b/src/cc/disputepayout.cpp index 60924b00bae..1d0f8f1f8d9 100644 --- a/src/cc/disputepayout.cpp +++ b/src/cc/disputepayout.cpp @@ -61,7 +61,7 @@ bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransact if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) return Error("couldnt-get-parent"); - if (GetCurrentHeight() < sessionBlock.GetHeight() + waitBlocks) + if (GetCurrentHeightCompat() < sessionBlock.GetHeight() + waitBlocks) return Invalid("dispute-too-soon"); // Not yet } diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 350647d5472..e0e78cf130a 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -164,6 +164,10 @@ unsigned int Eval::GetCurrentHeight() const { return nCurrentHeight; } +unsigned int Eval::GetCurrentHeightCompat() const +{ + return chainActive.Height(); +} bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const { diff --git a/src/cc/eval.h b/src/cc/eval.h index 6686c83fed5..224dc9f0e66 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -117,6 +117,7 @@ class Eval virtual int64_t GetCurrentTime() const; void SetCurrentTime(int64_t nTimeIn) { nCurrentTime = nTimeIn; } virtual unsigned int GetCurrentHeight() const; + virtual unsigned int GetCurrentHeightCompat() const; void SetCurrentHeight(int32_t nHeightIn) { nCurrentHeight = nHeightIn; } virtual bool GetSpendsConfirmed(uint256 hash, std::vector &spends) const; virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const; diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 18fe528e25f..4cca6ebb088 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -498,7 +498,7 @@ bool OraclesValidate(struct CCcontract_info* cp, Eval* eval, const CTransaction& // vout.2: marker from oraclesfund tx to normal pubkey address (activation on Jul 15th 2019 00:00) // vout.n-2: change, if any // vout.n-1: opreturn with createtxid, pubkey and price per data point - if (GetLatestTimestamp(eval->GetCurrentHeight()) > PUBKEY_SPOOFING_FIX_ACTIVATION) { + if (GetLatestTimestamp(eval->GetCurrentHeightCompat()) > PUBKEY_SPOOFING_FIX_ACTIVATION) { if (tx.vout.size() < 1 || DecodeOraclesOpRet(tx.vout.back().scriptPubKey, oracletxid, tmppk, amount) != 'R') return eval->Invalid("invalid oraclesregister OP_RETURN data!"); else if (!eval->GetTxUnconfirmed(oracletxid, tmptx, hashblock)) diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index 7fc86d1f2d4..3b498ff7185 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -297,7 +297,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) ) return eval->Invalid("txfee is too high"); amount = vinTx.vout[0].nValue; - reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeight())); + reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeightCompat())); if ( reward == 0 ) return eval->Invalid("no eligible rewards"); if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index fe27e0e9a01..451a938f693 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -179,7 +179,7 @@ void asnCondition(const CC *cond, Condition_t *asn) { default: return; }; choice->cost = cc_getCost(cond); - choice->fingerprint.buf = calloc(1, fingerprintSize); + choice->fingerprint.buf = calloc(1, 32); cond->type->fingerprint(cond, choice->fingerprint.buf); choice->fingerprint.size = fingerprintSize; } diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index a7bc78b6834..f29b614182a 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -140,6 +140,10 @@ static CC *thresholdFromFulfillmentMixed(const Fulfillment_t *ffill) { { // Get the real threshold from the first ffill CC *tc = fulfillmentToCC(arrFulfills[0], flags); + if (tc == NULL) { + free(cond); + return NULL; + } if (tc->type->typeId != CC_Preimage || tc->preimageLength != 1) { cc_free(tc); free(cond); diff --git a/src/main.cpp b/src/main.cpp index 08d4058e754..443097bba4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3897,6 +3897,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector vChecks; if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, pindex->GetBlockTime(), pindex->GetHeight(), evalcodeChecker, nScriptCheckThreads ? &vChecks : NULL)) return false; + control.Add(vChecks); } { // check tx outputs including coinbases diff --git a/src/rpc/tokensrpc.cpp b/src/rpc/tokensrpc.cpp index c68f2b57adf..919715e1bf6 100644 --- a/src/rpc/tokensrpc.cpp +++ b/src/rpc/tokensrpc.cpp @@ -564,9 +564,11 @@ static UniValue tokentransfer(const std::string& name, const UniValue& params, b return MakeResultError("destination as address not active yet"); if (dest.which() != TX_PUBKEYHASH && dest.which() != TX_PUBKEY) return MakeResultError("invalid destination pubkey or address"); + if (V::EvalCode() == EVAL_TOKENS && dest.which() != TX_PUBKEY) // address not supported for tokens 1 + return MakeResultError("invalid destination pubkey"); - // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses - if (dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) + // after subver_1 upgrade only addresses always will be used as destination, pubkeys are converted to addresses (for tokens v2) + if (V::EvalCode() == EVAL_TOKENSV2 && dest.which() == TX_PUBKEY && CCUpgrades::IsUpgradeActive(nTime, nHeight, CCUpgrades::GetUpgrades(), CCUpgrades::CCUPGID_MIXEDMODE_SUBVER_1)) dests.push_back(boost::get(dest).GetID()); else dests.push_back(dest); // address or pubkey @@ -643,12 +645,14 @@ UniValue tokentransfermany(const std::string& name, const UniValue& params, bool Myprivkey(mypriv); std::vector srctokenaddrs; std::vector> probes; - if (V::IsMixed() == EVAL_TOKENS) { + if (V::EvalCode() == EVAL_TOKENS) { CCwrapper probeCond; probeCond.reset( MakeCCcond1(V::EvalCode(), mypk) ); - char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; - GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); - srctokenaddrs.push_back(tokenaddr); + //char tokenaddr[KOMODO_ADDRESS_BUFSIZE]; + //GetTokensCCaddress(cpTokens, tokenaddr, mypk, V::IsMixed()); + //srctokenaddrs.push_back(tokenaddr); + srctokenaddrs = GetTokenV1IndexKeys(mypk); + probes.push_back({probeCond, mypriv}); } diff --git a/src/test-komodo-cc/test-assets.cpp b/src/test-komodo-cc/test-assets.cpp index b2eed97dd33..13df21a8c33 100644 --- a/src/test-komodo-cc/test-assets.cpp +++ b/src/test-komodo-cc/test-assets.cpp @@ -2873,15 +2873,24 @@ TEST_F(TestAssetsCC, tokenv2transfer_raddress) EXPECT_TRUE(eval.AddTx(mcreatetx)); uint256 tokenid = mcreatetx.GetHash(); - std::vector dests = { pk2 }; + std::vector dests = { pk2.GetID() }; // dest R-address - std::vector tokenaddrs = GetTokenV2IndexKeys(pk1); - CMutableTransaction mtransfertx = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs, {}, 1, dests, 1, false, false); - ASSERT_FALSE(CTransaction(mtransfertx).IsNull()); - EXPECT_TRUE(eval.AddTx(mtransfertx)); - CAmount bal = TokenV2Balance(pk2, tokenid); + std::vector tokenaddrs1 = GetTokenV2IndexKeys(pk1); + CMutableTransaction mtransfertx1 = MakeTokenV2TransferTx(pk1, 0, tokenid, tokenaddrs1, {}, 1, dests, 1, false, false); + ASSERT_FALSE(CTransaction(mtransfertx1).IsNull()); + EXPECT_TRUE(eval.AddTx(mtransfertx1)); + CAmount bal1 = TokenV2Balance(pk2, tokenid); // std::cerr << __func__ << " TokenV2Balance(pk2, tokenid)=" << bal << " mtransfertxid=" << mtransfertx.GetHash().GetHex() << " reason=" << eval.state.GetRejectReason() << std::endl; - EXPECT_TRUE(bal == 1); + EXPECT_TRUE(bal1 == 1); + + // try to spend + std::vector tokenaddrs2 = GetTokenV2IndexKeys(pk2); + CMutableTransaction mtransfertx2 = MakeTokenV2TransferTx(pk2, 0, tokenid, tokenaddrs2, {}, 1, dests, 1, false, false); + ASSERT_FALSE(CTransaction(mtransfertx2).IsNull()); + EXPECT_TRUE(eval.AddTx(mtransfertx2)); + CAmount bal2 = TokenV2Balance(pk2, tokenid); + EXPECT_TRUE(bal2 == 1); + } // test burn pk