From c3a9d0fa0cd5fd7939b68162db8b50a8505471d7 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 16 Apr 2019 12:28:27 +0800 Subject: [PATCH 1/4] test --- src/rpc/rawtransaction.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 6e90c4db5..41ed8ff66 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -721,7 +721,7 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) UniValue createrawtransaction(const UniValue& params, bool fHelp) { - if (fHelp || params.size() < 2 || params.size() > 4) + if (fHelp ) || //params.size() < 2 || params.size() > 4) throw runtime_error( "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...} ( locktime ) ( expiryheight )\n" "\nCreate a transaction spending the given inputs and sending to the given addresses.\n" @@ -754,6 +754,32 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"") ); + int nextBlockHeight = chainActive.Height() + 1; + CMutableTransaction rawTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); + CCcontract_info *cp, C; + + cp = CCinit(&C,EVAL_ORACLES); + CPubKey ccAddress = CPubKey(ParseHex(cp->CChexstr)); + CPubKey mypk = Mypubkey(); + + CTxOut vout = MakeCC1of2vout(EVAL_ORACLES, 1000000, mypk, ccAddress); + + std::vector vPubKeys = std::vector(); + vPubKeys.push_back(mypk); + vPubKeys.push_back(ccAddress); + + std::vector> vData = std::vector>(); + std::string test = "thisisatest"; + vData.push_back(std::vector(test.begin(), test.end())); + test = "anothertest"; + vData.push_back(std::vector(test.begin(), test.end())); + COptCCParams ccp = COptCCParams(COptCCParams::VERSION, EVAL_ORACLES, 1, 2, vPubKeys, vData); + + vout.scriptPubKey << ccp.AsVector() << OP_DROP; + rawTx.vout.push_back(vout); + + return EncodeHexTx(rawTx); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM)(UniValue::VNUM), true); if (params[0].isNull() || params[1].isNull()) From 997f9ce5fcfb600cc6832a431c11912c8b94b65e Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 16 Apr 2019 20:59:15 +0800 Subject: [PATCH 2/4] initial commit to use CCopt for custom CC --- src/cc/CCinclude.h | 4 ++-- src/cc/CCutils.cpp | 21 +++++++++++++++++++-- src/cc/customcc.cpp | 45 +++++++++++++++++++++++++++++++++++++-------- src/main.cpp | 2 +- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 5b6d575f3..6ca6fa3bc 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -226,8 +226,8 @@ bool priv2addr(char *coinaddr,uint8_t buf33[33],uint8_t priv32[32]); CPubKey buf2pk(uint8_t *buf33); void endiancpy(uint8_t *dest,uint8_t *src,int32_t len); uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t entropyvout,int32_t usevout); -CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk); -CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2); +CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, const std::vector>* vData = NULL); +CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, const std::vector>* vData = NULL); CC *MakeCCcond1(uint8_t evalcode,CPubKey pk); CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2); CC* GetCryptoCondition(CScript const& scriptSig); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 55c93d7b3..a34bf1a81 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -58,20 +58,37 @@ CC *MakeCCcond1(uint8_t evalcode,CPubKey pk) return CCNewThreshold(2, {condCC, Sig}); } -CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk) +CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue, CPubKey pk, const std::vector>* vData) { CTxOut vout; CC *payoutCond = MakeCCcond1(evalcode,pk); vout = CTxOut(nValue,CCPubKey(payoutCond)); + if ( vData ) + { + std::vector> vtmpData = std::vector>(vData->begin(), vData->end()); + std::vector vPubKeys = std::vector(); + vPubKeys.push_back(pk); + COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 1, vPubKeys, vtmpData); + vout.scriptPubKey << ccp.AsVector() << OP_DROP; + } cc_free(payoutCond); return(vout); } -CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2) +CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2, const std::vector>* vData) { CTxOut vout; CC *payoutCond = MakeCCcond1of2(evalcode,pk1,pk2); vout = CTxOut(nValue,CCPubKey(payoutCond)); + if ( vData ) + { + std::vector> vtmpData = std::vector>(vData->begin(), vData->end()); + std::vector vPubKeys = std::vector(); + vPubKeys.push_back(pk1); + vPubKeys.push_back(pk2); + COptCCParams ccp = COptCCParams(COptCCParams::VERSION, evalcode, 1, 2, vPubKeys, vtmpData); + vout.scriptPubKey << ccp.AsVector() << OP_DROP; + } cc_free(payoutCond); return(vout); } diff --git a/src/cc/customcc.cpp b/src/cc/customcc.cpp index 9f58c5c8b..34144fedc 100644 --- a/src/cc/customcc.cpp +++ b/src/cc/customcc.cpp @@ -11,7 +11,7 @@ */ 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); @@ -64,25 +64,54 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) 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)); + // make op_return payload as normal. + CScript opret = custom_opret('1',mypk); + std::vector> vData = std::vector>(); + vData.push_back(std::vector(opret.begin(), opret.end())); + // make vout0 with op_return included as payload. + mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk,&vData)); + fprintf(stderr, "vout size2.%li\n", mtx.vout.size()); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript()); return(custom_rawtxresult(result,rawtx,broadcastflag)); } return(result); } +bool has_opret(const CTransaction &tx, uint8_t evalcode) +{ + for ( auto vout : tx.vout ) + { + if ( vout.scriptPubKey[1] == evalcode ) + return true; + } + return false; +} + 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 + CScript opret; int32_t numvout; + if ( !has_opret(tx, EVAL_CUSTOM) ) + { + std::vector> vParams = std::vector>(); + CScript dummy; + if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && vParams.size() == 1 ) + { + opret << E_MARSHAL(ss << vParams[0]); + } + numvout = 1; + } + else + { + opret = tx.vout[1].scriptPubKey; + numvout = 2; + } + if ( tx.vout.size() != numvout ) // make sure the tx only has appropriate outputs return eval->Invalid("invalid number of vouts"); - else if ( custom_opretdecode(pk,tx.vout[1].scriptPubKey) != '1' ) // verify has opreturn + else if ( custom_opretdecode(pk,opret) != '1' ) // verify opreturn payload 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/main.cpp b/src/main.cpp index e0e40c9a5..304ff52a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -796,7 +796,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight) else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { reason = "bare-multisig"; return false; - } else if (txout.scriptPubKey.IsPayToCryptoCondition() == 0 && txout.IsDust(::minRelayTxFee)) { + } else if (whichType != TX_CRYPTOCONDITION && txout.IsDust(::minRelayTxFee)) { reason = "dust"; return false; } From 660c8dc26c92c39e1077f072f56ba936acafc0ce Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 16 Apr 2019 21:08:39 +0800 Subject: [PATCH 3/4] fix has_opret function --- src/cc/customcc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/customcc.cpp b/src/cc/customcc.cpp index 34144fedc..2e174f510 100644 --- a/src/cc/customcc.cpp +++ b/src/cc/customcc.cpp @@ -81,7 +81,7 @@ bool has_opret(const CTransaction &tx, uint8_t evalcode) { for ( auto vout : tx.vout ) { - if ( vout.scriptPubKey[1] == evalcode ) + if ( vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[1] == evalcode ) return true; } return false; From 87ebcc3b2b21998761a101851bb8fab16081980f Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 16 Apr 2019 21:11:06 +0800 Subject: [PATCH 4/4] revert createrawtransaction --- src/rpc/rawtransaction.cpp | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 41ed8ff66..6e90c4db5 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -721,7 +721,7 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) UniValue createrawtransaction(const UniValue& params, bool fHelp) { - if (fHelp ) || //params.size() < 2 || params.size() > 4) + if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...} ( locktime ) ( expiryheight )\n" "\nCreate a transaction spending the given inputs and sending to the given addresses.\n" @@ -754,32 +754,6 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"") ); - int nextBlockHeight = chainActive.Height() + 1; - CMutableTransaction rawTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); - CCcontract_info *cp, C; - - cp = CCinit(&C,EVAL_ORACLES); - CPubKey ccAddress = CPubKey(ParseHex(cp->CChexstr)); - CPubKey mypk = Mypubkey(); - - CTxOut vout = MakeCC1of2vout(EVAL_ORACLES, 1000000, mypk, ccAddress); - - std::vector vPubKeys = std::vector(); - vPubKeys.push_back(mypk); - vPubKeys.push_back(ccAddress); - - std::vector> vData = std::vector>(); - std::string test = "thisisatest"; - vData.push_back(std::vector(test.begin(), test.end())); - test = "anothertest"; - vData.push_back(std::vector(test.begin(), test.end())); - COptCCParams ccp = COptCCParams(COptCCParams::VERSION, EVAL_ORACLES, 1, 2, vPubKeys, vData); - - vout.scriptPubKey << ccp.AsVector() << OP_DROP; - rawTx.vout.push_back(vout); - - return EncodeHexTx(rawTx); - LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM)(UniValue::VNUM), true); if (params[0].isNull() || params[1].isNull())