diff --git a/src/cc/CCassetsCore.cpp b/src/cc/CCassetsCore.cpp index 837c4361e..f0afd2b84 100644 --- a/src/cc/CCassetsCore.cpp +++ b/src/cc/CCassetsCore.cpp @@ -432,6 +432,8 @@ int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmppr return(0); else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("invalid normal vout0 for buyvin"); + else if ( vinTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("invalid normal vout1 for buyvin"); else { //fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr); diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index fe86d58de..a1ec8a816 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -371,7 +371,7 @@ std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, in mypk = pubkey2pk(Mypubkey()); - if ((inputs = AddNormalinputs(mtx, mypk, bidamount+txfee, 64)) > 0) + if ((inputs = AddNormalinputs(mtx, mypk, bidamount+(2*txfee), 64)) > 0) { std::cerr << "CreateBuyOffer() inputs=" << inputs << std::endl; if (inputs < bidamount+txfee) { @@ -382,7 +382,7 @@ std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, in CPubKey unspendablePubkey = GetUnspendable(cpAssets, 0); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendablePubkey)); - + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); std::vector voutTokenPubkeys; // should be empty - no token vouts return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, EncodeAssetOpRet('b', assetid, zeroid, pricetotal, voutTokenPubkeys, Mypubkey()))); @@ -409,12 +409,12 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p } cpTokens = CCinit(&C, EVAL_TOKENS); // NOTE: tokens is here - + if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) + if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60)) > 0) @@ -428,13 +428,14 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p CPubKey unspendablePubkey = GetUnspendable(cpTokens, 0); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, unspendablePubkey)); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); if (inputs > askamount) CCchange = (inputs - askamount); if (CCchange != 0) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); std::vector voutTokenPubkeys; - voutTokenPubkeys.push_back(unspendablePubkey); + voutTokenPubkeys.push_back(unspendablePubkey); opret = EncodeAssetOpRet('s',assetid, zeroid, pricetotal, voutTokenPubkeys, Mypubkey()); return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee,opret)); @@ -539,7 +540,9 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) { bidamount = vintx.vout[0].nValue; mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets + mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); std::vector voutTokenPubkeys; // should be empty, no tokens vout @@ -554,27 +557,36 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; - struct CCcontract_info *cpTokens, C; + struct CCcontract_info *cpTokens,*cpAssets,C,assetsC; cpTokens = CCinit(&C, EVAL_TOKENS); + cpAssets = CCinit(&assetsC, EVAL_ASSETS); if (txfee == 0) txfee = 10000; mypk = pubkey2pk(Mypubkey()); - if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) + if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); if (GetTransaction(asktxid, vintx, hashBlock, false) != 0) { askamount = vintx.vout[0].nValue; mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); + mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); - + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + std::vector voutTokenPubkeys; voutTokenPubkeys.push_back(mypk); + char myCCaddr[65]; + uint8_t myPrivkey[32]; + Myprivkey(myPrivkey); + GetCCaddress(cpAssets, myCCaddr, mypk); + CCaddr2set(cpTokens, EVAL_ASSETS, mypk, myPrivkey, myCCaddr); + return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee, EncodeAssetOpRet('x', assetid, zeroid, 0, voutTokenPubkeys, Mypubkey()))); } } diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 3d95d0f17..971ba160d 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -175,7 +175,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran else { fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); - continue; + return(""); } uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata); if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 ) @@ -192,6 +192,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran else { fprintf(stderr,"vini.%d has CC signing error address.(%s)\n",i,destaddr); + return(""); } } } else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString().c_str()); diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 3a62a526a..127a0e50a 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -45,32 +45,20 @@ valid CC output: create or transfer or buyoffer or selloffer or exchange or cancel or fill - create - vin.0: normal input - vout.0: issuance assetoshis to CC - vout.1: tag sent to normal address of AssetsCCaddress - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['c'] [origpubkey] "" "" - - transfer - vin.0: normal input - vin.1 .. vin.n-1: valid CC outputs - vout.0 to n-2: assetoshis output to CC - vout.n-2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['t'] [assetid] buyoffer: vins.*: normal inputs (bid + change) vout.0: amount of bid to unspendable - vout.1: normal output for change (if any) + vout.1: CC output for marker + vout.2: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] cancelbuy: - vin.0: normal input - vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + vin.0: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + vin.1: CC marker from buyoffer for txfee vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] vout.1: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] + vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] 0 0 [origpubkey] fillbuy: vin.0: normal input @@ -87,8 +75,9 @@ vin.0: normal input vin.1+: valid CC output for sale vout.0: vin.1 assetoshis output to CC to unspendable - vout.1: CC output for change (if any) - vout.2: normal output for change (if any) + vout.1: CC output for marker + vout.2: CC output for change (if any) + vout.3: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] exchange: @@ -100,8 +89,8 @@ vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] cancel: - vin.0: normal input - vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + vin.0: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + vin.1: CC marker from selloffer for txfee vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] vout.1: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] @@ -213,7 +202,8 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti case 'b': // buyoffer //vins.*: normal inputs (bid + change) //vout.0: amount of bid to unspendable - //vout.1: normal output for change (if any) + //vout.1: CC output for marker + //vout.2: normal output for change (if any) // vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] if( remaining_price == 0 ) return eval->Invalid("illegal null amount for buyoffer"); @@ -225,8 +215,8 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti break; case 'o': // cancelbuy - //vin.0: normal input - //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + //vin.0: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + //vin.1: CC marker from buyoffer for txfee //vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] //vout.1: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['o'] @@ -234,7 +224,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti return(false); else if( ConstrainVout(tx.vout[0],0, origaddr, nValue) == 0 ) return eval->Invalid("invalid refund for cancelbuy"); - preventCCvins = 2; + preventCCvins = 3; preventCCvouts = 0; fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origaddr); break; @@ -288,29 +278,32 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti //vin.0: normal input //vin.1+: valid CC output for sale //vout.0: vin.1 assetoshis output to CC to unspendable - //vout.1: CC output for change (if any) - //vout.2: normal output for change (if any) + //vout.1: CC output for marker + //vout.2: CC output for change (if any) + //vout.3: normal output for change (if any) //'s'.vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] //'e'.vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] - preventCCvouts = 1; + preventCCvouts = 2; if( remaining_price == 0 ) return eval->Invalid("illegal null remaining_price for selloffer"); - if( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 ) // is cc change present? + if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("invalid normal vout1 for sellvin"); + if( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) { preventCCvouts++; if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // check also vout[0] return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); - else if( tx.vout[0].nValue + tx.vout[1].nValue != inputs ) - return eval->Invalid("mismatched vout0+vout1 total for selloffer"); + else if( tx.vout[0].nValue + tx.vout[2].nValue != inputs ) + return eval->Invalid("mismatched vout0+vout2 total for selloffer"); } else if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, inputs) == 0 ) // no cc change, just vout[0] return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); //fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price); break; - case 'x': // cancel - //vin.0: normal input - //vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + case 'x': // cancel + //vin.0: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + //vin.1: CC marker from selloffer for txfee //vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] //vout.1: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] @@ -318,7 +311,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti return(false); else if( ConstrainVout(tx.vout[0], 1, tokensCCaddr, assetoshis) == 0 ) return eval->Invalid("invalid vout for cancel"); - preventCCvins = 2; + preventCCvins = 3; preventCCvouts = 1; break;