From a34fc260986882b86830afd2919c705a68f7e2d1 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Mon, 21 Jan 2019 11:57:52 +0100 Subject: [PATCH] Fix canceling partially filled orders by anyone. (#11) * Fix * Fix --- src/cc/CCassetstx.cpp | 46 +++++++++++++++++++++---------------------- src/cc/CCutils.cpp | 1 - src/cc/assets.cpp | 15 +++++++++----- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 968775d38..9d83beb2c 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -477,14 +477,10 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; - uint64_t mask; - uint256 hashBlock; - int64_t bidamount; - CPubKey mypk; - struct CCcontract_info *cpAssets, C; - - uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; + CTransaction vintx; uint64_t mask; + uint256 hashBlock; int64_t bidamount; + CPubKey mypk; struct CCcontract_info *cpAssets, C; + uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; cpAssets = CCinit(&C, EVAL_ASSETS); @@ -501,9 +497,12 @@ 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 - if( DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey) == 'b') - mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' (not 'B') - // TODO: spend it also in FillBuyOffer? + if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) + { + + if (funcid == 's') mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' + else if (funcid=='S') mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' + } mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); @@ -523,12 +522,9 @@ 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, *cpAssets, tokensC, assetsC; - - uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; + uint256 hashBlock; int64_t askamount; + CPubKey mypk; struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC; + uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; cpAssets = CCinit(&assetsC, EVAL_ASSETS); @@ -545,9 +541,11 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) askamount = vintx.vout[0].nValue; mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); - if (DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey) == 's') - mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' (not 'S') - // TODO: spend it also in FillSell? + if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) + { + if (funcid == 's') mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' + else if (funcid=='S') mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // marker if funcid='S' + } mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); // one-eval token vout mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); @@ -607,7 +605,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f 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 (GetTransaction(bidtxid, vintx, hashBlock, false) != 0) @@ -637,9 +635,10 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the buyer + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); // vout3 marker to origpubkey if (CCchange != 0) - mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout3 change in single-eval tokens + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout4 change in single-eval tokens fprintf(stderr,"FillBuyOffer remaining %llu -> origpubkey\n", (long long)remaining_required); @@ -698,7 +697,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a 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 (GetTransaction(asktxid, vintx, hashBlock, false) != 0) @@ -747,6 +746,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a //std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr } + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); //vout.3 marker to origpubkey // not implemented if (CCchange != 0) { diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index e9c30acc1..07ce11154 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -602,7 +602,6 @@ bool komodo_txnotarizedconfirmed(uint256 txid) CPubKey check_signing_pubkey(CScript scriptSig) { - bool found = false; CPubKey pubkey; diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 3ccafa34f..2433473b9 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -153,8 +153,9 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti return eval->Invalid("AssetValidate: invalid opreturn payload"); // find dual-eval tokens unspendable addr: - char tokensUnspendableAddr[64]; + char tokensUnspendableAddr[64],origpubkeyCCaddr[64]; GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); + GetCCaddress(cpAssets, origpubkeyCCaddr, origpubkey); // we need this for validating single-eval tokens' vins/vous: struct CCcontract_info *cpTokens, tokensC; @@ -258,7 +259,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, assetsCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if( numvouts < 3 ) + else if( numvouts < 4 ) return eval->Invalid("not enough vouts for fillbuy"); else if( tmporigpubkey != origpubkey ) return eval->Invalid("mismatched origpubkeys for fillbuy"); @@ -266,17 +267,19 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti { if( nValue != tx.vout[0].nValue + tx.vout[1].nValue ) return eval->Invalid("locked value doesnt match vout0+1 fillbuy"); - else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) + else if( tx.vout[4].scriptPubKey.IsPayToCryptoCondition() != 0 ) { if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, 0) == 0 ) // tokens on user cc addr return eval->Invalid("vout2 doesnt go to origpubkey fillbuy"); - else if ( inputs != tx.vout[2].nValue + tx.vout[3].nValue ) + else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue ) return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy"); } else if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, inputs) == 0 ) // tokens on user cc addr return eval->Invalid("vout2 doesnt match inputs fillbuy"); else if( ConstrainVout(tx.vout[1],0,0,0) == 0 ) return eval->Invalid("vout1 is CC for fillbuy"); + else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 ) + return eval->Invalid("invalid marker for original pubkey"); else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) return eval->Invalid("mismatched remainder for fillbuy"); else if( remaining_price != 0 ) @@ -345,7 +348,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if( numvouts < 3 ) + else if( numvouts < 4 ) return eval->Invalid("not enough vouts for fillask"); else if( tmporigpubkey != origpubkey ) return eval->Invalid("mismatched origpubkeys for fillask"); @@ -359,6 +362,8 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti return eval->Invalid("normal vout1 for fillask"); else if( ConstrainVout(tx.vout[2], 0, origaddr, 0) == 0 ) return eval->Invalid("normal vout1 for fillask"); + else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 ) + return eval->Invalid("invalid marker for original pubkey"); else if( remaining_price != 0 ) { //char tokensUnspendableAddr[64];