Prevent sell and buy offers to be canceled by anybody (#9)

- Prevent sell and buy offers to be canceled by anybody
This commit is contained in:
Mihailo Milenkovic
2019-01-04 16:06:37 +01:00
committed by dimxy
parent 675787d676
commit da58ead2d3
4 changed files with 52 additions and 44 deletions

View File

@@ -432,6 +432,8 @@ int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmppr
return(0); return(0);
else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
return eval->Invalid("invalid normal vout0 for buyvin"); 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 else
{ {
//fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr); //fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr);

View File

@@ -371,7 +371,7 @@ std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, in
mypk = pubkey2pk(Mypubkey()); 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; std::cerr << "CreateBuyOffer() inputs=" << inputs << std::endl;
if (inputs < bidamount+txfee) { 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); CPubKey unspendablePubkey = GetUnspendable(cpAssets, 0);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendablePubkey)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendablePubkey));
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk));
std::vector<CPubKey> voutTokenPubkeys; // should be empty - no token vouts std::vector<CPubKey> voutTokenPubkeys; // should be empty - no token vouts
return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, EncodeAssetOpRet('b', assetid, zeroid, pricetotal, voutTokenPubkeys, Mypubkey()))); 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 cpTokens = CCinit(&C, EVAL_TOKENS); // NOTE: tokens is here
if (txfee == 0) if (txfee == 0)
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
{ {
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60)) > 0) 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); CPubKey unspendablePubkey = GetUnspendable(cpTokens, 0);
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, unspendablePubkey)); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, unspendablePubkey));
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk));
if (inputs > askamount) if (inputs > askamount)
CCchange = (inputs - askamount); CCchange = (inputs - askamount);
if (CCchange != 0) if (CCchange != 0)
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
std::vector<CPubKey> voutTokenPubkeys; std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(unspendablePubkey); voutTokenPubkeys.push_back(unspendablePubkey);
opret = EncodeAssetOpRet('s',assetid, zeroid, pricetotal, voutTokenPubkeys, Mypubkey()); opret = EncodeAssetOpRet('s',assetid, zeroid, pricetotal, voutTokenPubkeys, Mypubkey());
return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee,opret)); 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; bidamount = vintx.vout[0].nValue;
mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets 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(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
std::vector<CPubKey> voutTokenPubkeys; // should be empty, no tokens vout std::vector<CPubKey> 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()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; 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); cpTokens = CCinit(&C, EVAL_TOKENS);
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
if (txfee == 0) if (txfee == 0)
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
{ {
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if (GetTransaction(asktxid, vintx, hashBlock, false) != 0) if (GetTransaction(asktxid, vintx, hashBlock, false) != 0)
{ {
askamount = vintx.vout[0].nValue; askamount = vintx.vout[0].nValue;
mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); 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(MakeCC1vout(EVAL_TOKENS, askamount, mypk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
std::vector<CPubKey> voutTokenPubkeys; std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(mypk); 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()))); return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee, EncodeAssetOpRet('x', assetid, zeroid, 0, voutTokenPubkeys, Mypubkey())));
} }
} }

View File

@@ -175,7 +175,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
else else
{ {
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); 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); uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata);
if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 ) if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 )
@@ -192,6 +192,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
else else
{ {
fprintf(stderr,"vini.%d has CC signing error address.(%s)\n",i,destaddr); 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()); } else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString().c_str());

View File

@@ -45,32 +45,20 @@
valid CC output: create or transfer or buyoffer or selloffer or exchange or cancel or fill 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] "<assetname>" "<description>"
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: buyoffer:
vins.*: normal inputs (bid + change) vins.*: normal inputs (bid + change)
vout.0: amount of bid to unspendable 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] vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey]
cancelbuy: cancelbuy:
vin.0: normal input vin.0: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
vin.1: 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.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey]
vout.1: normal output for change (if any) 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: fillbuy:
vin.0: normal input vin.0: normal input
@@ -87,8 +75,9 @@
vin.0: normal input vin.0: normal input
vin.1+: valid CC output for sale vin.1+: valid CC output for sale
vout.0: vin.1 assetoshis output to CC to unspendable vout.0: vin.1 assetoshis output to CC to unspendable
vout.1: CC output for change (if any) vout.1: CC output for marker
vout.2: normal output for change (if any) 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] vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey]
exchange: exchange:
@@ -100,8 +89,8 @@
vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
cancel: cancel:
vin.0: normal input vin.0: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
vin.1: 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.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
vout.1: normal output for change (if any) vout.1: normal output for change (if any)
vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] 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 case 'b': // buyoffer
//vins.*: normal inputs (bid + change) //vins.*: normal inputs (bid + change)
//vout.0: amount of bid to unspendable //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] // vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey]
if( remaining_price == 0 ) if( remaining_price == 0 )
return eval->Invalid("illegal null amount for buyoffer"); return eval->Invalid("illegal null amount for buyoffer");
@@ -225,8 +215,8 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
break; break;
case 'o': // cancelbuy case 'o': // cancelbuy
//vin.0: normal input //vin.0: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
//vin.1: 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.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey]
//vout.1: normal output for change (if any) //vout.1: normal output for change (if any)
//vout.n-1: opreturn [EVAL_ASSETS] ['o'] //vout.n-1: opreturn [EVAL_ASSETS] ['o']
@@ -234,7 +224,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return(false); return(false);
else if( ConstrainVout(tx.vout[0],0, origaddr, nValue) == 0 ) else if( ConstrainVout(tx.vout[0],0, origaddr, nValue) == 0 )
return eval->Invalid("invalid refund for cancelbuy"); return eval->Invalid("invalid refund for cancelbuy");
preventCCvins = 2; preventCCvins = 3;
preventCCvouts = 0; preventCCvouts = 0;
fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origaddr); fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origaddr);
break; break;
@@ -288,29 +278,32 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
//vin.0: normal input //vin.0: normal input
//vin.1+: valid CC output for sale //vin.1+: valid CC output for sale
//vout.0: vin.1 assetoshis output to CC to unspendable //vout.0: vin.1 assetoshis output to CC to unspendable
//vout.1: CC output for change (if any) //vout.1: CC output for marker
//vout.2: normal output for change (if any) //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] //'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] //'e'.vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
preventCCvouts = 1; preventCCvouts = 2;
if( remaining_price == 0 ) if( remaining_price == 0 )
return eval->Invalid("illegal null remaining_price for selloffer"); 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++; preventCCvouts++;
if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // check also vout[0] if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // check also vout[0]
return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer");
else if( tx.vout[0].nValue + tx.vout[1].nValue != inputs ) else if( tx.vout[0].nValue + tx.vout[2].nValue != inputs )
return eval->Invalid("mismatched vout0+vout1 total for selloffer"); 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] 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"); return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer");
//fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price); //fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price);
break; break;
case 'x': // cancel case 'x': // cancel
//vin.0: normal input //vin.0: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
//vin.1: 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.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
//vout.1: normal output for change (if any) //vout.1: normal output for change (if any)
//vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid]
@@ -318,7 +311,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return(false); return(false);
else if( ConstrainVout(tx.vout[0], 1, tokensCCaddr, assetoshis) == 0 ) else if( ConstrainVout(tx.vout[0], 1, tokensCCaddr, assetoshis) == 0 )
return eval->Invalid("invalid vout for cancel"); return eval->Invalid("invalid vout for cancel");
preventCCvins = 2; preventCCvins = 3;
preventCCvouts = 1; preventCCvouts = 1;
break; break;