diff --git a/src/cc/CCPrices.h b/src/cc/CCPrices.h index 8b09e9267..f375ee10a 100644 --- a/src/cc/CCPrices.h +++ b/src/cc/CCPrices.h @@ -22,6 +22,13 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); // CCcustom -UniValue PricesInfo(); +UniValue PricesList(); +UniValue PricesInfo(uint256 fundingtxid); +UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid); +std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector pubkeys); +std::string PricesAddFunding(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount); +std::string PricesBet(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount,int32_t leverage); +std::string PricesFinish(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,uint256 bettxid); + #endif diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 9a0f2a0ea..4d4f30b3b 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -54,6 +54,8 @@ UniValue AssetInfo(uint256 tokenid); UniValue AssetList(); std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description); std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total); +std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode); + std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal); std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid); std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount); diff --git a/src/cc/CCassetsCore.cpp b/src/cc/CCassetsCore.cpp index 55a4ccdcb..c9b975c3c 100644 --- a/src/cc/CCassetsCore.cpp +++ b/src/cc/CCassetsCore.cpp @@ -367,7 +367,10 @@ int64_t IsAssetvout(int64_t &price,std::vector &origpubkey,const CTrans else if ( funcid != 'E' ) { if ( assetid == refassetid ) + { + //fprintf(stderr,"returning %.8f\n",(double)nValue/COIN); return(nValue); + } } else if ( funcid == 'E' ) { @@ -447,7 +450,7 @@ int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpp bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid) { - CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t assetoshis; std::vector tmporigpubkey; int64_t tmpprice; + CTransaction vinTx; uint256 hashBlock,id,id2; int32_t i,flag,numvins,numvouts; int64_t assetoshis; std::vector tmporigpubkey; int64_t tmpprice; numvins = tx.vin.size(); numvouts = tx.vout.size(); inputs = outputs = 0; @@ -465,8 +468,20 @@ bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti fprintf(stderr,"vin%d %llu, ",i,(long long)assetoshis); inputs += assetoshis; } + else + { + if ( vinTx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 && DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) + { + assetoshis = vinTx.vout[i].nValue; + fprintf(stderr,"vin%d %llu special case, ",i,(long long)assetoshis); + inputs += assetoshis; + } + } } } + if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) + flag = 1; + else flag = 0; for (i=0; i des return(""); } +std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode) +{ + CMutableTransaction mtx; CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; + if ( total < 0 ) + { + fprintf(stderr,"negative total %lld\n",(long long)total); + return(""); + } + cp = CCinit(&C,EVAL_ASSETS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + { + if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 ) + { + if ( inputs > total ) + CCchange = (inputs - total); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); + mtx.vout.push_back(MakeCC1vout(evalcode,total,pubkey2pk(destpubkey))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); + } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN); + } + return(""); +} + std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal) { CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; uint256 hashBlock; CTransaction vintx; std::vector origpubkey; std::string name,description; diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 50bb9616f..d651537cf 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -250,7 +250,8 @@ int64_t CCfullsupply(uint256 tokenid) int64_t CCtoken_balance(char *coinaddr,uint256 tokenid) { - int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock; std::vector origpubkey; std::vector > unspentOutputs; + int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock; std::vector origpubkey; + std::vector > unspentOutputs; SetCCunspents(unspentOutputs,coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index a91d6ffdd..01e9d35ab 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -63,6 +63,7 @@ CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2) CTxOut vout; CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2); vout = CTxOut(nValue,CCPubKey(payoutCond)); + fprintf(stderr,"payoutCond: %s\n",cc_conditionToJSONString(payoutCond)); cc_free(payoutCond); return(vout); } diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index e5a5af4e0..1ddbdc4f8 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -167,7 +167,6 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //vout.n-1: opreturn [EVAL_ASSETS] ['c'] [{"":""}] return eval->Invalid("unexpected AssetValidate for createasset"); break; - case 't': // transfer //vin.0: normal input //vin.1 .. vin.n-1: valid CC outputs diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 6a4f60413..976cd1971 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -21,7 +21,7 @@ debug multisig and do partial signing validation -string oracles + string oracles */ /* @@ -58,7 +58,7 @@ string oracles 5. Now a gatewaysbind can bind an external coin to an asset, along with the oracle for the merkleroots. the txid from the bind is used in most of the other gateways CC calls usage: - ./c tokencreate KMD 1000000 KMD_equivalent_token_for_gatewaysCC + ./c tokencreate KMD 1000000 KMD_equivalent_token_for_gatewaysCC a7398a8748354dd0a3f8d07d70e65294928ecc3674674bb2d9483011ccaa9a7a transfer to gateways pubkey: 03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40 RDMqGyREkP1Gwub1Nr5Ye8a325LGZsWBCb @@ -94,7 +94,7 @@ string oracles "remaining": "1000000.00000000", "issued": "0.00000000" } - + To make a gateway deposit, send the funds to the "deposit" address, along with any amount to the same pubkey address you want to get the assetized KMD to appear in. 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 pubkey for RFpxgqff7FDHFuHa3jSX5NzqqWCcELz8ha @@ -106,16 +106,16 @@ string oracles ./komodo-cli getrawtransaction bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009 010000000149964cdcd17fe9b1cae4d0f3b5f5db301d9b4f54099fdf4d34498df281757094010000006a4730440220594f3a630dd73c123f44621aa8bb9968ab86734833453dd479af6d79ae6f584202207bb5e35f13b337ccc8a88d9a006c8c5ddb016c0a6f4f2dc44357a8128623d85d01210223154bf53cd3a75e64d86697070d6437c8f0010a09c1df35b659e31ce3d79b5dffffffff0310270000000000001976a91447d2e323a14b0c3be08698aa46a9b91489b189d688ac701de52d000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688acb0a86a00000000001976a914f9a9daf5519dae38b8b61d945f075da895df441d88ace18d965b - + gatewaysdeposit bindtxid height coin cointxid claimvout deposithex proof destpub amount -./komodo-cli -ac_name=AT5 gatewaysdeposit e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e 1003776 KMD bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009 0 010000000149964cdcd17fe9b1cae4d0f3b5f5db301d9b4f54099fdf4d34498df281757094010000006a4730440220594f3a630dd73c123f44621aa8bb9968ab86734833453dd479af6d79ae6f584202207bb5e35f13b337ccc8a88d9a006c8c5ddb016c0a6f4f2dc44357a8128623d85d01210223154bf53cd3a75e64d86697070d6437c8f0010a09c1df35b659e31ce3d79b5dffffffff0310270000000000001976a91447d2e323a14b0c3be08698aa46a9b91489b189d688ac701de52d000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688acb0a86a00000000001976a914f9a9daf5519dae38b8b61d945f075da895df441d88ace18d965b 04000000232524ea04b54489eb222f8b3f566ed35504e3050488a63f0ab7b1c2030000007f91615f04835822bf6984a56482aeeb11d03814352eca9afc0a20192fdcae900000000000000000000000000000000000000000000000000000000000000000268e965ba608071d0800038e16762900000000000000000000000000000000000000000042008dd6fd4005016b4292b05df6dfd316c458c53e28fb2befb96e4870a40c6c04e733d75d8a7a18cce34fe326005efdc403bfa4644e30eeafdaeff34419edc591299e6cc5933cb2eeecbab5c4dfe97cd413b75215999a3dd02b540373581e81d8512bff1640590a6b4da4aaa9b8adc0102c38ca0022daed997b53ed192ba326e212fba5e505ce29e3ad149cef7f48d0e00948a1acd81731d84008760759211eb4abbc7b037939a7964182edb59cf9065357e864188ee5fc7316e8796963036bb99eeb9f06c95d64f78749ecec7181c12eb5d83a3b9b1c1e8a0aae9a20ce04a250b28216620bfc99bb81a6de4db80b93a5aea916de97c1a272e26644abdd683f19c5e3174a2e4513ed767d8f11a4c3074295f697839c5d9139676a813451cc7da38f68cbae5d990a79075f98903233ca04fe1b4b099e433585e5adcc45d41d54a9c648179297359c75950a5e574f13f70b728bbbf552770256315cd0a00139d6ab6934cb5ed70a4fc01a92611b096dd0028f17f4cc687b75f37dca530aa47a18321c50528dbd9272eabb3e13a87021a05918a6d2627e2caba6d7cf1a9f0b831ea3337b9a6af92746d83140078d60c72b6beacf91c9e68a34cee209e08670be1d17ff8d80b7a2285b1325461a2e33f2ee675593f1900e066a5d212615cd8da18749b0e684eee73edcc9031709be715b889c6d015cf4bd4ad5ab7e21bd3492c208930a54d353ef36a437f507ead38855633c1b88d060d9e4221ca8ce2f698e8a6ae0d41e9ace3cbd401f1e0f07650e9c126d4ef20278c8be6e85c7637513643f8d02d7ad64c09da11c16429d60e5160c345844b8158ece62794e8ad280d4e4664150e74978609ece431e51a9f9e1ce8aa49c16f36c7fd12b71acc42d893e18476b8b1e144a8175519612efc93e0aecc61f3b21212c958b0e2331d76aaa62faf11a58fe2bd91ab9ab01b906406c9bbc02df2a106e67182aae0a20b538bf19f09c57f9de5e198ba254580fb1b11e22ad526550093420cb7c68628d4c3ad329c8acc6e219093d277810ed016b6099b7e3781de412a22dacedaa2acf29e8062debcd85c7b9529a20b2782a2470763ac27cf89611a527d43ac89b8063ffb93b6ed993425194f8ee821a8493a563072c896f9584f95db28e3f2fc5fb4a6f3c39d615cd563641717cd50afb73ed3989cbf504b2043882993ce9575f56402534173b1396fbc13df80920b46788ae340ad5a91f25177cc74aa69024d76f56166199d2e4d50a053555256c4e3137ea1cee1130e916a88b6ee5cf2c85652fb8824d5dacfa485e3ef6190591ac0c2fcacc4fc7deb65aca4b0b89b76e35a46b0627e2e967cc63a5d606a984c8e63eabb98fde3e69114340ae524c974cb936e57690e98a7a74533f6f7d1d0496976496b54d14a8163efb32b70dfbb79d80a3022c4f53571c08bf044270565716b435084376714b224ab23e9817c05af8223723afc0577af5c8fc28f71036ca82528aaa4ca9bcd18a50e25d2a528f183d3a2074d968d170876d8dce434c5937261b55173ab87e03d5632ca0834fdc5387c15ab3a17d75c0f274004f289ff1bf7d14e97fdf4172eb49adfb418cc2f4794806ae7c0111c97df4d65d38679ec93fea3ef738ed565e8906a8fe1861cafe3938c772fedcfab40159938e06ef414fd299f2355c6d3369bc1bd3c4db64ce205f0a1b70a40030f505b736e28230de82e97776b5ee7b10708bb3020d28cec7a8e124549ec80c547ac4e7b52bf397c72bcfce30820554ab8fb4d1f73b209bc32a0e7e878843cdbf5f01222728ccea7e6ab7cb5e3fee3234f5b85d1985f91492f6ceaa6454a658dab5074f163ce26ed753137fa61c940679de13bd7b212cd3cf2b334f5201cecbc7473342bd7a239e09169bccd56d03000000037a9068df0625e548e71263c8361b4e904c998378f6b9e32729c3f19b10ad752e093013788222f5c26bfc5da4eeb7d32f01486a54179f19c341b79d420ea041bc8878d22fad4692b2d609c3cf190903874d3682a714c7483518c9392e07c25035010b 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999 + ./komodo-cli -ac_name=AT5 gatewaysdeposit e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e 1003776 KMD bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009 0 010000000149964cdcd17fe9b1cae4d0f3b5f5db301d9b4f54099fdf4d34498df281757094010000006a4730440220594f3a630dd73c123f44621aa8bb9968ab86734833453dd479af6d79ae6f584202207bb5e35f13b337ccc8a88d9a006c8c5ddb016c0a6f4f2dc44357a8128623d85d01210223154bf53cd3a75e64d86697070d6437c8f0010a09c1df35b659e31ce3d79b5dffffffff0310270000000000001976a91447d2e323a14b0c3be08698aa46a9b91489b189d688ac701de52d000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688acb0a86a00000000001976a914f9a9daf5519dae38b8b61d945f075da895df441d88ace18d965b 04000000232524ea04b54489eb222f8b3f566ed35504e3050488a63f0ab7b1c2030000007f91615f04835822bf6984a56482aeeb11d03814352eca9afc0a20192fdcae900000000000000000000000000000000000000000000000000000000000000000268e965ba608071d0800038e16762900000000000000000000000000000000000000000042008dd6fd4005016b4292b05df6dfd316c458c53e28fb2befb96e4870a40c6c04e733d75d8a7a18cce34fe326005efdc403bfa4644e30eeafdaeff34419edc591299e6cc5933cb2eeecbab5c4dfe97cd413b75215999a3dd02b540373581e81d8512bff1640590a6b4da4aaa9b8adc0102c38ca0022daed997b53ed192ba326e212fba5e505ce29e3ad149cef7f48d0e00948a1acd81731d84008760759211eb4abbc7b037939a7964182edb59cf9065357e864188ee5fc7316e8796963036bb99eeb9f06c95d64f78749ecec7181c12eb5d83a3b9b1c1e8a0aae9a20ce04a250b28216620bfc99bb81a6de4db80b93a5aea916de97c1a272e26644abdd683f19c5e3174a2e4513ed767d8f11a4c3074295f697839c5d9139676a813451cc7da38f68cbae5d990a79075f98903233ca04fe1b4b099e433585e5adcc45d41d54a9c648179297359c75950a5e574f13f70b728bbbf552770256315cd0a00139d6ab6934cb5ed70a4fc01a92611b096dd0028f17f4cc687b75f37dca530aa47a18321c50528dbd9272eabb3e13a87021a05918a6d2627e2caba6d7cf1a9f0b831ea3337b9a6af92746d83140078d60c72b6beacf91c9e68a34cee209e08670be1d17ff8d80b7a2285b1325461a2e33f2ee675593f1900e066a5d212615cd8da18749b0e684eee73edcc9031709be715b889c6d015cf4bd4ad5ab7e21bd3492c208930a54d353ef36a437f507ead38855633c1b88d060d9e4221ca8ce2f698e8a6ae0d41e9ace3cbd401f1e0f07650e9c126d4ef20278c8be6e85c7637513643f8d02d7ad64c09da11c16429d60e5160c345844b8158ece62794e8ad280d4e4664150e74978609ece431e51a9f9e1ce8aa49c16f36c7fd12b71acc42d893e18476b8b1e144a8175519612efc93e0aecc61f3b21212c958b0e2331d76aaa62faf11a58fe2bd91ab9ab01b906406c9bbc02df2a106e67182aae0a20b538bf19f09c57f9de5e198ba254580fb1b11e22ad526550093420cb7c68628d4c3ad329c8acc6e219093d277810ed016b6099b7e3781de412a22dacedaa2acf29e8062debcd85c7b9529a20b2782a2470763ac27cf89611a527d43ac89b8063ffb93b6ed993425194f8ee821a8493a563072c896f9584f95db28e3f2fc5fb4a6f3c39d615cd563641717cd50afb73ed3989cbf504b2043882993ce9575f56402534173b1396fbc13df80920b46788ae340ad5a91f25177cc74aa69024d76f56166199d2e4d50a053555256c4e3137ea1cee1130e916a88b6ee5cf2c85652fb8824d5dacfa485e3ef6190591ac0c2fcacc4fc7deb65aca4b0b89b76e35a46b0627e2e967cc63a5d606a984c8e63eabb98fde3e69114340ae524c974cb936e57690e98a7a74533f6f7d1d0496976496b54d14a8163efb32b70dfbb79d80a3022c4f53571c08bf044270565716b435084376714b224ab23e9817c05af8223723afc0577af5c8fc28f71036ca82528aaa4ca9bcd18a50e25d2a528f183d3a2074d968d170876d8dce434c5937261b55173ab87e03d5632ca0834fdc5387c15ab3a17d75c0f274004f289ff1bf7d14e97fdf4172eb49adfb418cc2f4794806ae7c0111c97df4d65d38679ec93fea3ef738ed565e8906a8fe1861cafe3938c772fedcfab40159938e06ef414fd299f2355c6d3369bc1bd3c4db64ce205f0a1b70a40030f505b736e28230de82e97776b5ee7b10708bb3020d28cec7a8e124549ec80c547ac4e7b52bf397c72bcfce30820554ab8fb4d1f73b209bc32a0e7e878843cdbf5f01222728ccea7e6ab7cb5e3fee3234f5b85d1985f91492f6ceaa6454a658dab5074f163ce26ed753137fa61c940679de13bd7b212cd3cf2b334f5201cecbc7473342bd7a239e09169bccd56d03000000037a9068df0625e548e71263c8361b4e904c998378f6b9e32729c3f19b10ad752e093013788222f5c26bfc5da4eeb7d32f01486a54179f19c341b79d420ea041bc8878d22fad4692b2d609c3cf190903874d3682a714c7483518c9392e07c25035010b 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999 -> 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6 to get the merkleroots onchain, from the multisig signers nodes run the oraclefeed program with acname oracletxid pubkey Ihh ./oraclefeed AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh gatewaysclaim bindtxid coin deposittxid destpub amount -./c gatewaysclaim e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999 + ./c gatewaysclaim e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999 now the asset is in the pubkey's asset address! it can be used, traded freely and any node who has the asset can do a gatewayswithdraw @@ -126,11 +126,21 @@ string oracles Now there is a withdraw pending, so it needs to be processed by the signing nodes on the KMD side - gatewayspending bindtxid coin + gatewayspending bindtxid coin gatewayspending will display all pending withdraws and if it is done on one of the msigpubkeys, then it will queue it for processing ./c gatewayspending e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD -*/ + + Implementation Issues: + When thinking about validation, it is clear that we cant use EVAL_ASSETS for the locked coins as there wont be any enforcement of the gateways locking. This means we need a way to transfer assets into gateways outputs and back. It seems a tokenconvert rpc will be needed and hopefully that will be enough to make it all work properly. + + Care must be taken so that tokens are not lost and can be converted back. + + This changes the usage to require tokenconvert before doing the bind and also tokenconvert before doing a withdraw. EVAL_GATEWAYS has evalcode of 251 + + The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS. + + */ int32_t GatewaysAddQueue(std::string coin,uint256 txid,CScript scriptPubKey,int64_t nValue) @@ -282,9 +292,9 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & // helper functions for rpc calls in rpcwallet.cpp -/*int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 refassetid,int64_t total,int32_t maxinputs) { - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + char coinaddr[64],destaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 assetid,txid,hashBlock; std::vector origpubkey; std::vector vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -292,23 +302,35 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & { txid = it->first.txhash; vout = (int32_t)it->first.index; - // no need to prevent dup + for (j=0; j 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey); + if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) + continue; + GetOpReturnData(vintx.vout[vintx.vout.size()-1].scriptPubKey, vopret); + if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> assetid) != 0 ) { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; + assetid = revuint256(assetid); + if ( evalcode == cp->evalcode && assetid == refassetid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( total != 0 && maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + n++; + if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + break; + } } } } return(totalinputs); -}*/ +} int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256 reftokenid) // dont forget to check mempool! { @@ -377,7 +399,7 @@ UniValue GatewaysInfo(uint256 bindtxid) result.push_back(Pair("name","Gateways")); cp = CCinit(&C,EVAL_GATEWAYS); Gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(gatewaysassets,EVAL_ASSETS,Gatewayspk); + _GetCCaddress(gatewaysassets,EVAL_GATEWAYS,Gatewayspk); if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 ) { depositaddr[0] = 0; @@ -433,19 +455,24 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t { CMutableTransaction mtx; CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char destaddr[64],coinaddr[64],str[65],*fstr; cp = CCinit(&C,EVAL_GATEWAYS); + if ( strcmp((char *)"KMD",coin.c_str()) == 0 ) + { + taddr = 0; + prefix = 60; + prefix2 = 85; + } + else + { + fprintf(stderr,"set taddr, prefix, prefix2 for %s\n",coin.c_str()); + taddr = 0; + prefix = 60; + prefix2 = 85; + } if ( N == 0 || N > 15 || M > N ) { fprintf(stderr,"illegal M.%d or N.%d\n",M,N); return(""); } - if ( strcmp((char *)"KMD",coin.c_str()) != 0 ) - { - fprintf(stderr,"only KMD supported for now\n"); - return(""); - } - taddr = 0; - prefix = 60; - prefix2 = 85; if ( pubkeys.size() != N ) { fprintf(stderr,"M.%d N.%d but pubkeys[%d]\n",M,N,(int32_t)pubkeys.size()); @@ -464,7 +491,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t txfee = 10000; mypk = pubkey2pk(Mypubkey()); gatewayspk = GetUnspendable(cp,0); - if ( _GetCCaddress(destaddr,EVAL_ASSETS,gatewayspk) == 0 ) + if ( _GetCCaddress(destaddr,EVAL_GATEWAYS,gatewayspk) == 0 ) { fprintf(stderr,"Gateway bind.%s (%s) cant create globaladdr\n",coin.c_str(),uint256_str(str,tokenid)); return(""); @@ -521,7 +548,7 @@ uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,u if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height ) { if ( oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size()) == sizeof(hash) && - oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()) == sizeof(hash) && mhash != zeroid ) + oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()) == sizeof(hash) && mhash != zeroid ) { txid = batontxid; return(mhash); @@ -671,18 +698,12 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std:: std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount) { - CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64]; + CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); - assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk); - CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr); - Myprivkey(mypriv); - _GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk); - CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr); if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); @@ -706,15 +727,15 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui //fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2); if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) { - if ( (inputs= AddAssetInputs(assetscp,mtx,gatewayspk,assetid,amount,60)) > 0 ) + if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,assetid,amount,60)) > 0 ) { if ( inputs > amount ) CCchange = (inputs - amount); mtx.vin.push_back(CTxIn(deposittxid,0,CScript())); // triggers EVAL_GATEWAYS validation - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk)); // transfer back to normal token if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,gatewayspk)); - return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); } } fprintf(stderr,"cant find enough inputs or mismatched total\n"); @@ -723,18 +744,12 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector withdrawpub,int64_t amount) { - CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; + CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; cp = CCinit(&C,EVAL_GATEWAYS); - assetscp = CCinit(&C2,EVAL_ASSETS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk); - CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr); - Myprivkey(mypriv); - _GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk); - CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr); if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); @@ -747,16 +762,16 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin } if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 0 ) { - if ( (inputs= AddAssetInputs(assetscp,mtx,mypk,assetid,amount,60)) > 0 ) + if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,assetid,amount,60)) > 0 ) { if ( inputs > amount ) CCchange = (inputs - amount); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,gatewayspk)); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,amount,gatewayspk)); mtx.vout.push_back(CTxOut(txfee,CScript() << withdrawpub << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG)); if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); } } fprintf(stderr,"cant find enough inputs or mismatched total\n"); @@ -783,7 +798,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) cp = CCinit(&C,EVAL_GATEWAYS); mypk = pubkey2pk(Mypubkey()); gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk); + _GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk); if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); @@ -846,7 +861,7 @@ std::string GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid complete = partialtx = 0; mypk = pubkey2pk(Mypubkey()); Gatewayspk = GetUnspendable(cp,0); - _GetCCaddress(gatewaysassets,EVAL_ASSETS,Gatewayspk); + _GetCCaddress(gatewaysassets,EVAL_GATEWAYS,Gatewayspk); if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 ) { depositaddr[0] = 0; diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 1465c6ee6..ca945d02f 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -28,67 +28,60 @@ Funds work like with dice, ie. there is a Prices plan that traders bet against. - PricesOpen -> oracletxid start with 'L' price, leverage, amount - funds are locked into global CC address + PricesFunding oracletxid, margin, priceaveraging, maxleverage, funding, longtoken, shorttoken, N [pubkeys] + + PricesBet -> oracletxid start with 'L', leverage, funding, direction + funds are locked into global CC address it can be closed at anytime by the trader for cash settlement the house account can close it if rekt Implementation Notes: In order to eliminate the need for worrying about sybil attacks, each prices plan would be able to specific pubkey(s?) for whitelisted publishers. It would be possible to have a non-whitelisted plan that would use 50% correlation between publishers. - delta neutral balancing of risk exposure + delta neutral balancing of riskexposure: fabs(long exposure - short exposure) + bet +B at leverage L + absval(sum(+BLi) - sum(-Bli)) + + validate: update riskexposure and it needs to be <= funds + + PricesProfits: limit withdraw to funds in excess of riskexposure + PricesFinish: payout (if winning) and update riskexposure + need long/short exposure assets + + funding -> 1of2 CC global CC address and dealer address, exposure tokens to global 1of2 assets CC address + pricebet -> user funds and exposure token to 1of2 address. + pricewin -> winnings from dealer funds, exposure token back to global address + priceloss -> exposuretoken back to global address + + exposure address, funds address */ // start of consensus code -int64_t IsPricesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t PricesOraclePrice(int64_t &rektprice,uint64_t mode,uint256 oracletxid,std::vectorpubkeys,int32_t dir,int64_t amount,int32_t leverage) { - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); - } - return(0); + int64_t price; + // howto ensure price when block it confirms it not known + // get price from oracle + current chaintip + // normalize leveraged amount + if ( dir > 0 ) + rektprice = price * leverage / (leverage-1); + else rektprice = price * (leverage-1) / leverage; + return(price); } -bool PricesExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) +CScript EncodePricesFundingOpRet(uint8_t funcid,CPubKey planpk,uint256 oracletxid,uint256 longtoken,uint256 shorttoken,int32_t millimargin,uint64_t mode,int32_t maxleverage,std::vector pubkeys,uint256 bettoken) { - static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Prices from mempool"); - if ( (assetoshis= IsPricesvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } - } - } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); + CScript opret; + fprintf(stderr,"implement EncodePricesFundingOpRet\n"); + return(opret); +} + +uint8_t DecodePricesFundingOpRet(CScript scriptPubKey,CPubKey &planpk,uint256 &oracletxid,uint256 &longtoken,uint256 &shorttoken,int32_t &millimargin,uint64_t &mode,int32_t &maxleverage,std::vector &pubkeys,uint256 &bettoken) +{ + fprintf(stderr,"implement DecodePricesFundingOpRet\n"); + return(0); } bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) @@ -111,12 +104,12 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx } } //fprintf(stderr,"check amounts\n"); - if ( PricesExactAmounts(cp,eval,tx,1,10000) == false ) + //if ( PricesExactAmounts(cp,eval,tx,1,10000) == false ) { fprintf(stderr,"Pricesget invalid amount\n"); return false; } - else + //else { txid = tx.GetHash(); memcpy(hash,&txid,sizeof(hash)); @@ -132,20 +125,20 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx // helper functions for rpc calls in rpcwallet.cpp -int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char *destaddr,uint256 tolenid,int64_t total,int32_t maxinputs) { - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; - GetCCaddress(cp,coinaddr,pk); - SetCCunspents(unspentOutputs,coinaddr); + SetCCunspents(unspentOutputs,destaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; - // no need to prevent dup - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + // need to prevent dup + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && vout < vintx.vout.size() ) { - if ( (nValue= IsPricesvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + // need to verify assetid + if ( (nValue= vintx.vout[vout].nValue) > 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) { if ( total != 0 && maxinputs != 0 ) mtx.vin.push_back(CTxIn(txid,vout,CScript())); @@ -160,49 +153,18 @@ int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub return(totalinputs); } -#ifdef later -UniValue PricesInfo(uint256 pricesid) -{ - UniValue result(UniValue::VOBJ); CPubKey pricepk; uint256 hashBlock,oracletxid; CTransaction vintx; int64_t minbet,maxbet,maxodds; uint64_t funding; char numstr[65]; struct CCcontract_info *cp,C; - if ( GetTransaction(pricesid,vintx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find fundingtxid\n"); - ERR_RESULT("cant find fundingtxid"); - return(result); - } - if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,oracletxid,minbet,maxbet,maxodds) == 0 ) - { - fprintf(stderr,"fundingtxid isnt price creation txid\n"); - ERR_RESULT("fundingtxid isnt price creation txid"); - return(result); - } - result.push_back(Pair("result","success")); - result.push_back(Pair("pricesid",uint256_str(str,pricesid))); - result.push_back(Pair("oracletxid",uint256_str(str,oracletxid))); - sprintf(numstr,"%.8f",(double)minbet/COIN); - result.push_back(Pair("minbet",numstr)); - sprintf(numstr,"%.8f",(double)maxbet/COIN); - result.push_back(Pair("maxbet",numstr)); - result.push_back(Pair("maxodds",maxodds)); - cp = CCinit(&C,EVAL_PRICES); - pricepk = GetUnspendable(cp,0); - funding = PricePlanFunds(cp,pricepk,pricesid); - sprintf(numstr,"%.8f",(double)funding/COIN); - result.push_back(Pair("funding",numstr)); - return(result); -} - UniValue PricesList() { - UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid; CTransaction vintx; int64_t minbet,maxbet,maxodds; char str[65]; + UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint64_t mode; int32_t margin,maxleverage; std::vectorpubkeys; uint256 txid,hashBlock,oracletxid,longtoken,shorttoken,bettoken; CPubKey planpk,pricespk; char str[65]; CTransaction vintx; cp = CCinit(&C,EVAL_PRICES); + pricespk = GetUnspendable(cp,0); SetCCtxids(addressIndex,cp->normaladdr); for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { txid = it->first.txhash; if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { - if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,oracletxid,minbet,maxbet,maxodds) != 0 ) + if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' ) { result.push_back(uint256_str(str,txid)); } @@ -211,59 +173,164 @@ UniValue PricesList() return(result); } -std::string PricesCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks) +// longtoken satoshis limits long exposure +// shorttoken satoshis limits short exposure +// both must be in the 1of2 CC address with its total supply +// bettoken +std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector pubkeys) { - CMutableTransaction mtx; uint256 zero; CScript fundingPubKey; CPubKey mypk,pricepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C; - if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 ) + CMutableTransaction mtx; CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C,*assetscp,C2; + if ( funding < 100*COIN || maxleverage <= 0 || maxleverage > 10000 ) { CCerror = "invalid parameter error"; fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } - if ( funds < 100*COIN ) + cp = CCinit(&C,EVAL_PRICES); + assetscp = CCinit(&C2,EVAL_ASSETS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + if ( (N= (int32_t)pubkeys.size()) || N > 15 ) { - CCerror = "price plan needs at least 100 coins"; - fprintf(stderr,"%s\n", CCerror.c_str() ); + fprintf(stderr,"too many pubkeys N.%d\n",N); return(""); } - memset(&zero,0,sizeof(zero)); - if ( (cp= Pricesinit(fundingPubKey,zero,&C,planstr,txfee,mypk,pricepk,sbits,a,b,c,d)) == 0 ) + for (i=0; i 0 ) + if ( CCtoken_balance(houseaddr,longtoken) != CCfullsupply(longtoken) ) + { + fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(longtoken)/COIN); + return(""); + } + if ( CCtoken_balance(houseaddr,shorttoken) != CCfullsupply(shorttoken) ) + { + fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(shorttoken)/COIN); + return(""); + } + if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= oracletx.vout.size()) <= 0 ) + { + fprintf(stderr,"cant find oracletxid %s\n",uint256_str(str,oracletxid)); + return(""); + } + fprintf(stderr,"error check bettoken\n"); + if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 0 ) { - mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,pricepk)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricepk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesFundingOpRet('F',sbits,minbet,maxbet,maxodds,timeoutblocks))); + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesFundingOpRet('F',mypk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken))); + } + else + { + CCerror = "cant find enough inputs"; + fprintf(stderr,"%s\n", CCerror.c_str() ); } - CCerror = "cant find enough inputs"; - fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } -std::string PricesAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount) +UniValue PricesInfo(uint256 fundingtxid) { - CMutableTransaction mtx; CScript fundingPubKey,scriptPubKey; CPubKey mypk,pricepk; struct CCcontract_info *cp,C; int64_t minbet,maxbet,maxodds; - if ( amount < 0 ) + UniValue result(UniValue::VOBJ),a(UniValue::VARR); CPubKey pricespk,planpk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction vintx; int64_t balance,supply,exposure; uint64_t funding,mode; int32_t i,margin,maxleverage; char numstr[65],houseaddr[64],exposureaddr[64],str[65]; std::vectorpubkeys; struct CCcontract_info *cp,C,*assetscp,C2; + cp = CCinit(&C,EVAL_PRICES); + assetscp = CCinit(&C2,EVAL_ASSETS); + pricespk = GetUnspendable(cp,0); + if ( GetTransaction(fundingtxid,vintx,hashBlock,false) == 0 ) + { + fprintf(stderr,"cant find fundingtxid\n"); + ERR_RESULT("cant find fundingtxid"); + return(result); + } + if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' ) + { + result.push_back(Pair("result","success")); + result.push_back(Pair("fundingtxid",uint256_str(str,fundingtxid))); + result.push_back(Pair("bettoken",uint256_str(str,bettoken))); + result.push_back(Pair("oracletxid",uint256_str(str,oracletxid))); + sprintf(numstr,"%.3f",(double)margin/1000); + result.push_back(Pair("profitmargin",numstr)); + result.push_back(Pair("maxleverage",maxleverage)); + result.push_back(Pair("mode",(int64_t)mode)); + for (i=0; ipubkeys; + if ( amount < 10000 ) { CCerror = "amount must be positive"; fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } - if ( (cp= Pricesinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,pricepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) - return(""); - scriptPubKey = CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG; - if ( scriptPubKey == fundingPubKey ) + cp = CCinit(&C,EVAL_PRICES); + assetscp = CCinit(&C2,EVAL_ASSETS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(assetscp,myaddr,mypk); + if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) { - if ( AddNormalinputs(mtx,mypk,amount+2*txfee,60) > 0 ) + fprintf(stderr,"cant find fundingtxid\n"); + return(""); + } + if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken ) + { + GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); + if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { - mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,pricepk)); - mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesOpRet('E',sbits,fundingtxid,hentropy,zeroid))); + if ( (inputs= AddTokensInputs(assetscp,mtx,myaddr,bettoken,amount,60)) >= amount ) + { + mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,amount,pricespk,planpk)); + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(planpk)) << OP_CHECKSIG)); + if ( inputs > amount+txfee ) + CCchange = (inputs - amount); + mtx.vout.push_back(MakeCC1vout(assetscp->evalcode,CCchange,mypk)); + // add addr2 + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',bettoken,zeroid,0,Mypubkey()))); + } + else + { + CCerror = "cant find enough bet inputs"; + fprintf(stderr,"%s\n", CCerror.c_str() ); + } } else { @@ -271,66 +338,107 @@ std::string PricesAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,in fprintf(stderr,"%s\n", CCerror.c_str() ); } } - else - { - CCerror = "only fund creator can add more funds (entropy)"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - } return(""); } -std::string PricesBet(uint64_t txfee,uint256 pricesid,int64_t bet,int32_t odds) +std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount,int32_t leverage) { - CMutableTransaction mtx; CScript fundingPubKey; CPubKey mypk,pricepk; int64_t funding,minbet,maxbet,maxodds; struct CCcontract_info *cp,C; - if ( bet < 0 ) + CMutableTransaction mtx; struct CCcontract_info *cp,C,*assetscp,C2; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vectorpubkeys; + if ( amount < 0 ) { - CCerror = "bet must be positive"; - fprintf(stderr,"%s\n", CCerror.c_str() ); + amount = -amount; + dir = -1; + } else dir = 1; + cp = CCinit(&C,EVAL_PRICES); + assetscp = CCinit(&C2,EVAL_ASSETS); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(assetscp,myaddr,mypk); + if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 ) + { + fprintf(stderr,"cant find fundingtxid\n"); return(""); } - if ( odds < 1 || odds > 9999 ) + if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken ) { - CCerror = "odds must be between 1 and 9999"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); - } - if ( (cp= Pricesinit(fundingPubKey,pricesid,&C,txfee,mypk,pricepk,minbet,maxbet,maxodds)) == 0 ) - return(""); - if ( bet < minbet || bet > maxbet || odds > maxodds ) - { - CCerror = strprintf("Price plan %s illegal bet %.8f: minbet %.8f maxbet %.8f or odds %d vs max.%d\n",planstr,(double)bet/COIN,(double)minbet/COIN,(double)maxbet/COIN,(int32_t)odds,(int32_t)maxodds); - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); - } - if ( (funding= PricesPlanFunds(cp,pricepk,pricesid)) >= 2*bet*odds+txfee ) - { - if ( myIsutxo_spentinmempool(entropytxid,0) != 0 ) + if ( leverage > maxleverage || leverage < 1 ) { - CCerror = "entropy txid is spent"; - fprintf(stderr,"%s\n", CCerror.c_str() ); + fprintf(stderr,"illegal leverage\n"); return(""); } - if ( AddNormalinputs(mtx,mypk,bet+2*txfee+odds,60) > 0 ) + GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); + GetCCaddress1of2(assetscp,exposureaddr,pricespk,pricespk); + if ( dir < 0 ) + tokenid = shorttoken; + else tokenid = longtoken; + exposure = leverage * amount; + longexposure = CCtoken_balance(exposureaddr,longtoken); + shortexposure = CCtoken_balance(exposureaddr,shorttoken); + netexposure = (longexposure - shortexposure + exposure*dir); + if ( netexposure < 0 ) + netexposure = -netexposure; + balance = CCtoken_balance(myaddr,bettoken) / COIN; + if ( balance < netexposure*9/10 ) // 10% extra room for dynamically closed bets in wrong direction { - mtx.vout.push_back(MakeCC1vout(cp->evalcode,entropyval,pricepk)); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,bet,pricepk)); - mtx.vout.push_back(CTxOut(txfee+odds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesOpRet('B',pricesid))); - } else fprintf(stderr,"cant find enough normal inputs for %.8f, plan funding %.8f\n",(double)bet/COIN,(double)funding/COIN); + fprintf(stderr,"balance %lld < 90%% netexposure %lld, refuse bet\n",(long long)balance,(long long)netexposure); + return(""); + } + if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + { + if ( (inputs= AddTokensInputs(assetscp,mtx,houseaddr,tokenid,exposure,30)) >= exposure ) + { + if ( (inputs2= AddTokensInputs(assetscp,mtx,myaddr,bettoken,amount,30)) >= amount ) + { + mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,amount,pricespk,planpk)); + mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,exposure,pricespk,pricespk)); + if ( inputs > exposure+txfee ) + CCchange = (inputs - exposure); + if ( inputs2 > amount+txfee ) + CCchange2 = (inputs2 - amount); + mtx.vout.push_back(MakeCC1of2vout(assetscp->evalcode,CCchange,pricespk,planpk)); + mtx.vout.push_back(MakeCC1vout(assetscp->evalcode,CCchange2,mypk)); + // add addr2 and addr3 + //return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodePricesExtra('T',tokenid,bettoken,zeroid,dir*leverage))); + CScript opret; + return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,opret)); + } + else + { + fprintf(stderr,"cant find enough bettoken inputs\n"); + return(""); + } + } + else + { + fprintf(stderr,"cant find enough exposure inputs\n"); + return(""); + } + } + else + { + CCerror = "cant find enough inputsB"; + fprintf(stderr,"%s\n", CCerror.c_str() ); + } } - if ( entropyval == 0 && funding != 0 ) - CCerror = "cant find price entropy inputs"; - else CCerror = "cant find price input"; - fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } -std::string PricesBetFinish(int32_t *resultp,uint64_t txfee,uint256 pricesid,uint256 bettxid) +UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid) +{ + UniValue result(UniValue::VOBJ); + // get height of bettxid + // get price and rekt + // get current height and price + // what about if rekt in the past? + return(result); +} + +std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid) { - *resultp = -1; - CCerror = "couldnt find bettx or entropytx"; - fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } -#endif + + diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 4711a9afc..942612465 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -198,6 +198,21 @@ const char *Notaries_elected1[][2] = {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, }; +int32_t komodo_isnotaryvout(uint8_t *script) // from ac_private chains only +{ + uint8_t pubkey33[33]; int32_t i; + if ( script[0] == 33 && script[34] == 0xac ) + { + for (i=0; i 0 && iscoinbase == 0) || tx.GetJoinSplitValueOut() > 0 ) - return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain"); + { + if ( txout.scriptPubKey.size() == 35 && komodo_isnotaryvout((uint8_t *)txout.scriptPubKey.data()) == 0 ) + return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain"); + } } if ( txout.scriptPubKey.size() > IGUANA_MAXSCRIPTSIZE ) return state.DoS(100, error("CheckTransaction(): txout.scriptPubKey.size() too big"),REJECT_INVALID, "bad-txns-vout-negative"); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 5d73e8f6b..e9cf54bb4 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1377,6 +1377,8 @@ struct CompareBlocksByHeight } }; +#include + UniValue getchaintips(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -1415,17 +1417,33 @@ UniValue getchaintips(const UniValue& params, bool fHelp) /* Build up a list of chain tips. We start with the list of all known blocks, and successively remove blocks that appear as pprev of another block. */ + /*static pthread_mutex_t mutex; static int32_t didinit; + if ( didinit == 0 ) + { + pthread_mutex_init(&mutex,NULL); + didinit = 1; + } + pthread_mutex_lock(&mutex);*/ std::set setTips; + int32_t n = 0; BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) + { + n++; setTips.insert(item.second); + } + fprintf(stderr,"iterations getchaintips %d\n",n); + n = 0; BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) { const CBlockIndex* pprev=0; + n++; if ( item.second != 0 ) pprev = item.second->pprev; if (pprev) setTips.erase(pprev); } + fprintf(stderr,"iterations getchaintips %d\n",n); + //pthread_mutex_unlock(&mutex); // Always report the currently active tip. setTips.insert(chainActive.LastTip()); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d268ed7fa..8934ae717 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -398,7 +398,14 @@ static const CRPCCommand vRPCCommands[] = { "oracles", "oraclessamples", &oraclessamples, true }, /* Prices */ - { "prices", "pricesaddress", &pricesaddress, true }, + { "prices", "pricesaddress", &pricesaddress, true }, + { "prices", "priceslist", &priceslist, true }, + { "prices", "pricesinfo", &pricesinfo, true }, + { "prices", "pricescreate", &pricescreate, true }, + { "prices", "pricesaddfunding", &pricesaddfunding, true }, + { "prices", "pricesbet", &pricesbet, true }, + { "prices", "pricesstatus", &pricesstatus, true }, + { "prices", "pricesfinish", &pricesfinish, true }, /* Pegs */ { "pegs", "pegsaddress", &pegsaddress, true }, @@ -447,6 +454,7 @@ static const CRPCCommand vRPCCommands[] = { "tokens", "tokencancelask", &tokencancelask, true }, { "tokens", "tokenfillask", &tokenfillask, true }, //{ "tokens", "tokenfillswap", &tokenfillswap, true }, + { "tokens", "tokenconvert", &tokenconvert, true }, /* Address index */ { "addressindex", "getaddressmempool", &getaddressmempool, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 1ebff82ef..f4c502d63 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -221,6 +221,7 @@ extern UniValue tokenfillbid(const UniValue& params, bool fHelp); extern UniValue tokenask(const UniValue& params, bool fHelp); extern UniValue tokencancelask(const UniValue& params, bool fHelp); extern UniValue tokenfillask(const UniValue& params, bool fHelp); +extern UniValue tokenconvert(const UniValue& params, bool fHelp); extern UniValue mofnaddress(const UniValue& params, bool fHelp); extern UniValue channelsaddress(const UniValue& params, bool fHelp); extern UniValue oraclesaddress(const UniValue& params, bool fHelp); @@ -232,6 +233,13 @@ extern UniValue oraclessubscribe(const UniValue& params, bool fHelp); extern UniValue oraclesdata(const UniValue& params, bool fHelp); extern UniValue oraclessamples(const UniValue& params, bool fHelp); extern UniValue pricesaddress(const UniValue& params, bool fHelp); +extern UniValue priceslist(const UniValue& params, bool fHelp); +extern UniValue pricesinfo(const UniValue& params, bool fHelp); +extern UniValue pricescreate(const UniValue& params, bool fHelp); +extern UniValue pricesaddfunding(const UniValue& params, bool fHelp); +extern UniValue pricesbet(const UniValue& params, bool fHelp); +extern UniValue pricesstatus(const UniValue& params, bool fHelp); +extern UniValue pricesfinish(const UniValue& params, bool fHelp); extern UniValue pegsaddress(const UniValue& params, bool fHelp); extern UniValue triggersaddress(const UniValue& params, bool fHelp); extern UniValue paymentsaddress(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 57c9fabc1..5a14370c4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4858,6 +4858,7 @@ int32_t ensure_CCrequirements() #include "../cc/CCchannels.h" #include "../cc/CCOracles.h" #include "../cc/CCGateways.h" +#include "../cc/CCPrices.h" UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector &pubkey) { @@ -4896,7 +4897,7 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector destpubkey; CPubKey pk,pk2; char destaddr[64]; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::vector destpubkey; CPubKey pk,pk2; char destaddr[64]; cp = CCinit(&C,EVAL_CHANNELS); if ( fHelp || params.size() != 1 ) throw runtime_error("channelsaddress destpubkey\n"); @@ -4909,6 +4910,15 @@ UniValue channelsaddress(const UniValue& params, bool fHelp) result.push_back(Pair("otherpubkey", params[0].get_str())); GetCCaddress1of2(cp,destaddr,pk,pk2); result.push_back(Pair("channeladdress",destaddr)); + if ( 0 ) + { + int32_t i; + for (i=0; i<100; i++) + { + GetCCaddress1of2(cp,destaddr,pk,pk2); + fprintf(stderr,"i.%d %s\n",i,destaddr); + } + } return(result); } @@ -4927,15 +4937,25 @@ UniValue oraclesaddress(const UniValue& params, bool fHelp) UniValue pricesaddress(const UniValue& params, bool fHelp) { - struct CCcontract_info *cp,C; std::vector pubkey; + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C,*assetscp,C2; std::vector pubkey; CPubKey mypk,planpk,pricespk; char myaddr[64],houseaddr[64],exposureaddr[64]; cp = CCinit(&C,EVAL_PRICES); + assetscp = CCinit(&C2,EVAL_PRICES); if ( fHelp || params.size() > 1 ) throw runtime_error("pricesaddress [pubkey]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); if ( params.size() == 1 ) pubkey = ParseHex(params[0].get_str().c_str()); - return(CCaddress(cp,(char *)"Prices",pubkey)); + result = CCaddress(cp,(char *)"Prices",pubkey); + mypk = pubkey2pk(Mypubkey()); + pricespk = GetUnspendable(cp,0); + GetCCaddress(assetscp,myaddr,mypk); + GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); + GetCCaddress1of2(assetscp,exposureaddr,pricespk,pricespk); + result.push_back(Pair("myaddr",myaddr)); // for holding my asssets + result.push_back(Pair("houseaddr",houseaddr)); // globally accessible house assets + result.push_back(Pair("exposureaddr",exposureaddr)); // tracking of exposure + return(result); } UniValue pegsaddress(const UniValue& params, bool fHelp) @@ -5113,7 +5133,8 @@ UniValue channelsopen(const UniValue& params, bool fHelp) throw runtime_error("channelsopen destpubkey numpayments payment\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); destpub = ParseHex(params[0].get_str().c_str()); numpayments = atoi(params[1].get_str().c_str()); payment = atol(params[2].get_str().c_str()); @@ -5134,7 +5155,8 @@ UniValue channelsstop(const UniValue& params, bool fHelp) throw runtime_error("channelsstop destpubkey origtxid\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); destpub = ParseHex(params[0].get_str().c_str()); origtxid = Parseuint256((char *)params[1].get_str().c_str()); hex = ChannelStop(0,pubkey2pk(destpub),origtxid); @@ -5154,7 +5176,8 @@ UniValue channelspayment(const UniValue& params, bool fHelp) throw runtime_error("channelspayment prevtxid origtxid n amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); prevtxid = Parseuint256((char *)params[0].get_str().c_str()); origtxid = Parseuint256((char *)params[1].get_str().c_str()); n = atoi((char *)params[2].get_str().c_str()); @@ -5176,7 +5199,8 @@ UniValue channelscollect(const UniValue& params, bool fHelp) throw runtime_error("channelscollect paytxid origtxid n amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); paytxid = Parseuint256((char *)params[0].get_str().c_str()); origtxid = Parseuint256((char *)params[1].get_str().c_str()); n = atoi((char *)params[2].get_str().c_str()); @@ -5198,7 +5222,8 @@ UniValue channelsrefund(const UniValue& params, bool fHelp) throw runtime_error("channelsrefund stoptxid origtxid\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); stoptxid = Parseuint256((char *)params[0].get_str().c_str()); origtxid = Parseuint256((char *)params[1].get_str().c_str()); hex = ChannelRefund(0,stoptxid,origtxid); @@ -5420,6 +5445,8 @@ UniValue gatewaysbind(const UniValue& params, bool fHelp) throw runtime_error("gatewaysbind tokenid oracletxid coin tokensupply M N pubkey(s)\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); tokenid = Parseuint256((char *)params[0].get_str().c_str()); oracletxid = Parseuint256((char *)params[1].get_str().c_str()); coin = params[2].get_str(); @@ -5451,6 +5478,8 @@ UniValue gatewaysdeposit(const UniValue& params, bool fHelp) throw runtime_error("gatewaysdeposit bindtxid height coin cointxid claimvout deposithex proof destpub amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); bindtxid = Parseuint256((char *)params[0].get_str().c_str()); height = atoi((char *)params[1].get_str().c_str()); coin = params[2].get_str(); @@ -5478,6 +5507,8 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp) throw runtime_error("gatewaysclaim bindtxid coin deposittxid destpub amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); bindtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); deposittxid = Parseuint256((char *)params[2].get_str().c_str()); @@ -5499,6 +5530,8 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp) throw runtime_error("gatewayswithdraw bindtxid coin withdrawpub amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); bindtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); withdrawpub = ParseHex(params[2].get_str()); @@ -5519,6 +5552,8 @@ UniValue gatewaysmarkdone(const UniValue& params, bool fHelp) throw runtime_error("gatewaysmarkdone withdrawtxid coin cointxid\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); withdrawtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); cointxid = Parseuint256((char *)params[2].get_str().c_str()); @@ -5550,6 +5585,8 @@ UniValue gatewaysmultisig(const UniValue& params, bool fHelp) throw runtime_error("gatewaysmultisig bindtxid coin withtxid txidaddr\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); bindtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); withtxid = Parseuint256((char *)params[2].get_str().c_str()); @@ -5590,6 +5627,8 @@ UniValue oraclesregister(const UniValue& params, bool fHelp) throw runtime_error("oraclesregister oracletxid datafee\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); txid = Parseuint256((char *)params[0].get_str().c_str()); datafee = atol((char *)params[1].get_str().c_str()); hex = OracleRegister(0,txid,datafee); @@ -5608,6 +5647,8 @@ UniValue oraclessubscribe(const UniValue& params, bool fHelp) throw runtime_error("oraclessubscribe oracletxid publisher amount\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); txid = Parseuint256((char *)params[0].get_str().c_str()); pubkey = ParseHex(params[1].get_str().c_str()); amount = atof((char *)params[2].get_str().c_str()) * COIN; @@ -5640,6 +5681,8 @@ UniValue oraclesdata(const UniValue& params, bool fHelp) throw runtime_error("oraclesdata oracletxid hexstr\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); txid = Parseuint256((char *)params[0].get_str().c_str()); data = ParseHex(params[1].get_str().c_str()); hex = OracleData(0,txid,data); @@ -5776,6 +5819,156 @@ UniValue faucetget(const UniValue& params, bool fHelp) return(result); } +UniValue priceslist(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() > 0 ) + throw runtime_error("priceslist\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + return(PricesList()); +} + +UniValue pricesinfo(const UniValue& params, bool fHelp) +{ + uint256 fundingtxid; + if ( fHelp || params.size() != 1 ) + throw runtime_error("pricesinfo fundingtxid\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + return(PricesInfo(fundingtxid)); +} + +UniValue pricescreate(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint64_t mode; int64_t funding; int32_t i,n,margin,maxleverage; std::string hex; uint256 oracletxid,longtoken,shorttoken,bettoken; std::vector pubkeys; std::vectorpubkey; + if ( fHelp || params.size() < 8 ) + throw runtime_error("pricescreate bettoken oracletxid margin mode longtoken shorttoken maxleverage funding N [pubkeys]\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + bettoken = Parseuint256((char *)params[0].get_str().c_str()); + oracletxid = Parseuint256((char *)params[1].get_str().c_str()); + margin = atof(params[2].get_str().c_str()) * 1000; + mode = atol(params[3].get_str().c_str()); + longtoken = Parseuint256((char *)params[4].get_str().c_str()); + shorttoken = Parseuint256((char *)params[5].get_str().c_str()); + maxleverage = atol(params[6].get_str().c_str()); + funding = atof(params[7].get_str().c_str()) * COIN; + n = atoi(params[8].get_str().c_str()); + if ( n > 0 ) + { + for (i=0; i 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } + else + { + ERR_RESULT("couldnt create prices funding transaction"); + } + return(result); +} + +UniValue pricesaddfunding(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid,bettoken; int64_t amount; + if ( fHelp || params.size() != 3 ) + throw runtime_error("pricesaddfunding fundingtxid bettoken amount\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + bettoken = Parseuint256((char *)params[1].get_str().c_str()); + amount = atof(params[2].get_str().c_str()) * COIN; + hex = PricesAddFunding(0,bettoken,fundingtxid,amount); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } + else + { + ERR_RESULT("couldnt create pricesaddfunding transaction"); + } + return(result); +} + +UniValue pricesbet(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid,bettoken; int64_t amount; int32_t leverage; + if ( fHelp || params.size() != 4 ) + throw runtime_error("pricesbet fundingtxid bettoken amount leverage\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + bettoken = Parseuint256((char *)params[1].get_str().c_str()); + amount = atof(params[2].get_str().c_str()) * COIN; + leverage = atoi(params[3].get_str().c_str()); + hex = PricesBet(0,bettoken,fundingtxid,amount,leverage); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } + else + { + ERR_RESULT("couldnt create pricesbet transaction"); + } + return(result); +} + +UniValue pricesstatus(const UniValue& params, bool fHelp) +{ + uint256 fundingtxid,bettxid,bettoken; + if ( fHelp || params.size() != 3 ) + throw runtime_error("pricesstatus fundingtxid bettoken bettxid\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + bettoken = Parseuint256((char *)params[1].get_str().c_str()); + bettxid = Parseuint256((char *)params[2].get_str().c_str()); + return(PricesStatus(0,bettoken,fundingtxid,bettxid)); +} + +UniValue pricesfinish(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 fundingtxid,bettxid,bettoken; std::string hex; + if ( fHelp || params.size() != 3 ) + throw runtime_error("pricesfinish fundingtxid bettoken bettxid\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + bettoken = Parseuint256((char *)params[1].get_str().c_str()); + bettxid = Parseuint256((char *)params[2].get_str().c_str()); + hex = PricesFinish(0,bettoken,fundingtxid,bettxid); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } + else + { + ERR_RESULT("couldnt create pricesfinish transaction"); + } + return(result); +} + UniValue dicefund(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); int64_t funds,minbet,maxbet,maxodds,timeoutblocks; std::string hex; char *name; @@ -5947,7 +6140,6 @@ UniValue dicestatus(const UniValue& params, bool fHelp) UniValue dicelist(const UniValue& params, bool fHelp) { - uint256 tokenid; if ( fHelp || params.size() > 0 ) throw runtime_error("dicelist\n"); if ( ensure_CCrequirements() < 0 ) @@ -6096,6 +6288,42 @@ UniValue tokentransfer(const UniValue& params, bool fHelp) return(result); } +UniValue tokenconvert(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); std::string hex; int32_t evalcode; int64_t amount; uint256 tokenid; + if ( fHelp || params.size() != 4 ) + throw runtime_error("tokenconvert evalcode tokenid pubkey amount\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + evalcode = atoi(params[0].get_str().c_str()); + tokenid = Parseuint256((char *)params[1].get_str().c_str()); + std::vector pubkey(ParseHex(params[2].get_str().c_str())); + amount = atol(params[3].get_str().c_str()); + if ( tokenid == zeroid ) + { + ERR_RESULT("invalid tokenid"); + return(result); + } + if ( amount <= 0 ) + { + ERR_RESULT("amount must be positive"); + return(result); + } + hex = AssetConvert(0,tokenid,pubkey,amount,evalcode); + if (amount > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt convert tokens"); + } else { + ERR_RESULT("amount must be positive"); + } + return(result); +} + UniValue tokenbid(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); int64_t bidamount,numtokens; std::string hex; double price; uint256 tokenid;