From 24e27eb7eabd923ab45a26bb25e2e4ccee2f1b43 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 13 Mar 2019 00:24:08 -1100 Subject: [PATCH] customcc --- src/cc/cclib.cpp | 15 ++++++++- src/cc/customcc.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++ src/cc/customcc.h | 44 +++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/cc/customcc.cpp create mode 100644 src/cc/customcc.h diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 651723e44..c783eb4d0 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -33,8 +33,12 @@ #ifdef BUILD_ROGUE #define EVAL_ROGUE 17 std::string MYCCLIBNAME = (char *)"rogue"; -#else + +#elif BUILD_CUSTOMCC +#include "customcc.h" + +#else #define EVAL_SUDOKU 17 #define EVAL_MUSIG 18 #define EVAL_DILITHIUM 19 @@ -67,6 +71,8 @@ CClib_methods[] = { (char *)"rogue", (char *)"games", (char *)"", 0, 0, 'F', EVAL_ROGUE }, { (char *)"rogue", (char *)"setname", (char *)"pname", 1, 1, 'N', EVAL_ROGUE }, { (char *)"rogue", (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, 'X', EVAL_ROGUE }, +#elif BUILD_CUSTOMCC + RPC_FUNCS #else { (char *)"sudoku", (char *)"gen", (char *)"", 0, 0, 'G', EVAL_SUDOKU }, { (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU }, @@ -214,6 +220,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr) return(result); } } +#elif BUILD_CUSTOMCC + CUSTOM_DISPATCH #else if ( cp->evalcode == EVAL_SUDOKU ) { @@ -410,6 +418,8 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C { #ifdef BUILD_ROGUE return(rogue_validate(cp,height,eval,tx)); +#elif BUILD_CUSTOMCC + return(custom_validate(cp,height,eval,tx)); #else if ( cp->evalcode == EVAL_SUDOKU ) return(sudoku_validate(cp,height,eval,tx)); @@ -660,6 +670,9 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len) #include "rogue/weapons.c" #include "rogue/wizard.c" +#elif BUILD_CUSTOMCC +#include "customcc.cpp" + #else #include "sudoku.cpp" #include "musig.cpp" diff --git a/src/cc/customcc.cpp b/src/cc/customcc.cpp new file mode 100644 index 000000000..d79c255f4 --- /dev/null +++ b/src/cc/customcc.cpp @@ -0,0 +1,80 @@ +/* + simple stub custom cc + */ + +CScript custom_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 custom_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 custom_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 custom_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 custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CPubKey mypk; int64_t amount = COIN; int32_t broadcastflag=0; + if ( txfee == 0 ) + txfee = CUSTOM_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,custom_opret('1',mypk)); + return(custom_rawtxresult(result,rawtx,broadcastflag)); + } + return(result); +} + +bool custom_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 ( custom_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/customcc.h b/src/cc/customcc.h new file mode 100644 index 000000000..87ebb6142 --- /dev/null +++ b/src/cc/customcc.h @@ -0,0 +1,44 @@ +/* + to create a custom libcc.so: + + 1. change "func0" and "func1" to method names that fit your custom cc. Of course, you can create more functions by adding another entry to RPC_FUNCS. there is not any practical limit to the number of methods. + + 2. For each method make sure there is a UniValue function declaration and CUSTOM_DISPATCH has an if statement checking for it that calls the custom_func + + 3. write the actual custom_func0, custom_func1 and custom_validate in customcc.cpp + + 4. build cclib.cpp with -DBUILD_CUSTOMCC and put the libcc.so in ~/komodo/src and rebuild komodod + + 5. launch your chain with -ac_cclib=customcc -ac_cc=2 + + */ + +std::string MYCCLIBNAME = (char *)"customcc"; + +#define EVAL_CUSTOM (EVAL_FAUCET2+1) + +#define MYCCNAME "custom" + +#define RPC_FUNCS \ + { (char *)MYCCNAME, (char *)"func0", (char *)"", 1, 1, '0', EVAL_CUSTOM }, \ + { (char *)MYCCNAME, (char *)"func1", (char *)"", 0, 0, '1', EVAL_CUSTOM }, + +bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx); +UniValue custom_func0(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); +UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); + +#define CUSTOM_DISPATCH \ +if ( cp->evalcode == EVAL_SUDOKU ) \ +{ \ + if ( strcmp(method,"func0") == 0 ) \ + return(custom_func0(txfee,cp,params)); \ + else if ( strcmp(method,"func1") == 0 ) \ + return(custom_func1(txfee,cp,params)); \ + else \ + { \ + result.push_back(Pair("result","error")); \ + result.push_back(Pair("error","invalid customcc method")); \ + result.push_back(Pair("method",method)); \ + return(result); \ + } \ +}