diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 1330c6b3e..c8e714ba2 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -38,6 +38,9 @@ std::string MYCCLIBNAME = (char *)"rogue"; #elif BUILD_CUSTOMCC #include "customcc.h" +#elif BUILD_GAMESCC +#include "gamescc.h" + #else #define EVAL_SUDOKU 17 #define EVAL_MUSIG 18 @@ -73,6 +76,8 @@ CClib_methods[] = { (char *)"rogue", (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, 'X', EVAL_ROGUE }, #elif BUILD_CUSTOMCC RPC_FUNCS +#elif BUILD_GAMESCC + RPC_FUNCS #else { (char *)"sudoku", (char *)"gen", (char *)"", 0, 0, 'G', EVAL_SUDOKU }, { (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU }, @@ -222,6 +227,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr) } #elif BUILD_CUSTOMCC CUSTOM_DISPATCH +#elif BUILD_GAMESCC + CUSTOM_DISPATCH #else if ( cp->evalcode == EVAL_SUDOKU ) { @@ -420,6 +427,8 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C return(rogue_validate(cp,height,eval,tx)); #elif BUILD_CUSTOMCC return(custom_validate(cp,height,eval,tx)); +#elif BUILD_GAMESCC + return(games_validate(cp,height,eval,tx)); #else if ( cp->evalcode == EVAL_SUDOKU ) return(sudoku_validate(cp,height,eval,tx)); @@ -677,6 +686,9 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len) #elif BUILD_CUSTOMCC #include "customcc.cpp" +#elif BUILD_GAMESCC +#include "gamescc.cpp" + #else #include "sudoku.cpp" #include "musig.cpp" diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp new file mode 100644 index 000000000..f5f9dfba6 --- /dev/null +++ b/src/cc/gamescc.cpp @@ -0,0 +1,77 @@ + +CScript games_opret(uint8_t funcid,CPubKey pk) +{ + CScript opret; uint8_t evalcode = EVAL_CUSTOM; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk); + return(opret); +} + +uint8_t games_opretdecode(CPubKey &pk,CScript scriptPubKey) +{ + std::vector vopret; uint8_t e,f; + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk) != 0 && e == EVAL_CUSTOM ) + { + return(f); + } + return(0); +} + +UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag) +{ + CTransaction tx; + if ( rawtx.size() > 0 ) + { + result.push_back(Pair("hex",rawtx)); + if ( DecodeHexTx(tx,rawtx) != 0 ) + { + if ( broadcastflag != 0 && myAddtomempool(tx) != 0 ) + RelayTransaction(tx); + result.push_back(Pair("txid",tx.GetHash().ToString())); + result.push_back(Pair("result","success")); + } else result.push_back(Pair("error","decode hex")); + } else result.push_back(Pair("error","couldnt finalize CCtx")); + return(result); +} + +UniValue games_func0(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result","success")); + result.push_back(Pair("message","just an example of an information returning rpc")); + return(result); +} + +// send yourself 1 coin to your CC address using normal utxo from your -pubkey + +UniValue games_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string rawtx; + UniValue result(UniValue::VOBJ); CPubKey mypk; int64_t amount = COIN; int32_t broadcastflag=0; + if ( txfee == 0 ) + txfee = GAMES_TXFEE; + mypk = pubkey2pk(Mypubkey()); + if ( AddNormalinputs(mtx,mypk,COIN+txfee,64) >= COIN+txfee ) // add utxo to mtx + { + mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk)); // make vout0 + // add opreturn, change is automatically added and tx is properly signed + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,games_opret('1',mypk)); + return(games_rawtxresult(result,rawtx,broadcastflag)); + } + return(result); +} + +bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx) +{ + char expectedaddress[64]; CPubKey pk; + if ( tx.vout.size() != 2 ) // make sure the tx only has 2 outputs + return eval->Invalid("invalid number of vouts"); + else if ( games_opretdecode(pk,tx.vout[1].scriptPubKey) != '1' ) // verify has opreturn + return eval->Invalid("invalid opreturn"); + GetCCaddress(cp,expectedaddress,pk); + if ( IsCClibvout(cp,tx,0,expectedaddress) == COIN ) // make sure amount and destination matches + return(true); + else return eval->Invalid("invalid vout0 amount"); +} + + diff --git a/src/cc/gamescc.h b/src/cc/gamescc.h new file mode 100644 index 000000000..6b0bdc771 --- /dev/null +++ b/src/cc/gamescc.h @@ -0,0 +1,31 @@ + +std::string MYCCLIBNAME = (char *)"gamescc"; + +#define EVAL_GAMES (EVAL_FAUCET2+1) +#define GAMES_TXFEE 10000 + +#define MYCCNAME "games" + +#define RPC_FUNCS \ + { (char *)MYCCNAME, (char *)"func0", (char *)"", 1, 1, '0', EVAL_CUSTOM }, \ + { (char *)MYCCNAME, (char *)"func1", (char *)"", 0, 0, '1', EVAL_CUSTOM }, + +bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx); +UniValue games_func0(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); +UniValue games_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); + +#define CUSTOM_DISPATCH \ +if ( cp->evalcode == EVAL_GAMES ) \ +{ \ + if ( strcmp(method,"func0") == 0 ) \ + return(games_func0(txfee,cp,params)); \ + else if ( strcmp(method,"func1") == 0 ) \ + return(games_func1(txfee,cp,params)); \ + else \ + { \ + result.push_back(Pair("result","error")); \ + result.push_back(Pair("error","invalid gamescc method")); \ + result.push_back(Pair("method",method)); \ + return(result); \ + } \ +} diff --git a/src/cc/makegames b/src/cc/makegames new file mode 100755 index 000000000..b4b8cb803 --- /dev/null +++ b/src/cc/makegames @@ -0,0 +1,7 @@ +#!/bin/sh +gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp +cp gamescc.so ../libcc.so +cd .. +make +cd cc +