Merge pull request #792 from jl777/jl777

Code complete token, faucet and rewards CC contracts

Improve PoW diff adjustment for PoS/PoW mode (breaks backward compatibility)
This commit is contained in:
jl777
2018-07-28 01:11:05 -11:00
committed by GitHub
30 changed files with 1280 additions and 334 deletions

View File

@@ -31,27 +31,35 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
// CCassetsCore // CCassetsCore
//CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk); //CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk);
CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,std::string name,std::string description); CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,std::string name,std::string description);
CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,uint64_t price,std::vector<uint8_t> origpubkey); CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector<uint8_t> origpubkey);
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,uint64_t &price,std::vector<uint8_t> &origpubkey); bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description);
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,uint64_t &price,const CTransaction &tx); uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
uint64_t IsAssetvout(uint64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid); bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx);
bool ValidateAssetRemainder(int32_t sellflag,uint64_t remaining_price,uint64_t remaining_nValue,uint64_t orig_nValue,uint64_t received_nValue,uint64_t paidprice,uint64_t totalprice); int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid);
bool SetAssetFillamounts(int32_t sellflag,uint64_t &paid,uint64_t &remaining_price,uint64_t orig_nValue,uint64_t &received,uint64_t totalprice); bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
uint64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid); bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
uint64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid); bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
bool AssetExactAmounts(struct CCcontract_info *cp,uint64_t &inputs,int32_t starti,uint64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid); bool SetBidFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice);
bool SetAskFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice);
bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice);
int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid);
int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid);
bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid);
// CCassetstx // CCassetstx
uint64_t GetAssetBalance(CPubKey pk,uint256 tokenid); int64_t GetAssetBalance(CPubKey pk,uint256 tokenid);
uint64_t AddAssetInputs(CMutableTransaction &mtx,CPubKey pk,uint256 assetid,uint64_t total,int32_t maxinputs); int64_t AddAssetInputs(CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs);
UniValue AssetOrders(uint256 tokenid); UniValue AssetOrders(uint256 tokenid);
std::string CreateAsset(uint64_t txfee,uint64_t assetsupply,std::string name,std::string description); UniValue AssetInfo(uint256 tokenid);
std::string AssetTransfer(uint64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,uint64_t total); UniValue AssetList();
std::string CreateBuyOffer(uint64_t txfee,uint64_t bidamount,uint256 assetid,uint64_t pricetotal); std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description);
std::string CancelBuyOffer(uint64_t txfee,uint256 assetid,uint256 bidtxid); std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total);
std::string FillBuyOffer(uint64_t txfee,uint256 assetid,uint256 bidtxid,uint64_t fillamount); std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal);
std::string CreateSell(uint64_t txfee,uint64_t askamount,uint256 assetid,uint256 assetid2,uint64_t pricetotal); std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid);
std::string CancelSell(uint64_t txfee,uint256 assetid,uint256 asktxid); std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount);
std::string FillSell(uint64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,uint64_t fillamount); std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal);
std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal);
std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid);
std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillamount);
#endif #endif

View File

@@ -38,9 +38,161 @@
We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it. We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it.
*/ */
bool ValidateAssetRemainder(int32_t sellflag,uint64_t remaining_price,uint64_t remaining_nValue,uint64_t orig_nValue,uint64_t received_nValue,uint64_t paidunits,uint64_t totalunits) bool ValidateBidRemainder(int64_t remaining_units,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidunits,int64_t totalunits)
{ {
uint64_t unitprice,recvunitprice,newunitprice=0; int64_t unitprice,recvunitprice,newunitprice=0;
if ( orig_nValue == 0 || received_nValue == 0 || paidunits == 0 || totalunits == 0 )
{
fprintf(stderr,"ValidateAssetRemainder: orig_nValue == %llu || received_nValue == %llu || paidunits == %llu || totalunits == %llu\n",(long long)orig_nValue,(long long)received_nValue,(long long)paidunits,(long long)totalunits);
return(false);
}
else if ( totalunits != (remaining_units + paidunits) )
{
fprintf(stderr,"ValidateAssetRemainder: totalunits %llu != %llu (remaining_units %llu + %llu paidunits)\n",(long long)totalunits,(long long)(remaining_units + paidunits),(long long)remaining_units,(long long)paidunits);
return(false);
}
else if ( orig_nValue != (remaining_nValue + received_nValue) )
{
fprintf(stderr,"ValidateAssetRemainder: orig_nValue %llu != %llu (remaining_nValue %llu + %llu received_nValue)\n",(long long)orig_nValue,(long long)(remaining_nValue - received_nValue),(long long)remaining_nValue,(long long)received_nValue);
return(false);
}
else
{
unitprice = (orig_nValue * COIN) / totalunits;
recvunitprice = (received_nValue * COIN) / paidunits;
if ( remaining_units != 0 )
newunitprice = (remaining_nValue * COIN) / remaining_units;
if ( recvunitprice < unitprice )
{
fprintf(stderr,"error recvunitprice %.16f < %.16f unitprice, new unitprice %.16f\n",(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN));
return(false);
}
fprintf(stderr,"orig %llu total %llu, recv %llu paid %llu,recvunitprice %.16f >= %.16f unitprice, new unitprice %.16f\n",(long long)orig_nValue,(long long)totalunits,(long long)received_nValue,(long long)paidunits,(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN));
}
return(true);
}
bool SetBidFillamounts(int64_t &received_nValue,int64_t &remaining_units,int64_t orig_nValue,int64_t &paidunits,int64_t totalunits)
{
int64_t remaining_nValue,unitprice; double dprice;
if ( totalunits == 0 )
{
received_nValue = remaining_units = paidunits = 0;
return(false);
}
if ( paidunits >= totalunits )
{
paidunits = totalunits;
received_nValue = orig_nValue;
remaining_units = 0;
fprintf(stderr,"totally filled!\n");
return(true);
}
remaining_units = (totalunits - paidunits);
unitprice = (orig_nValue * COIN) / totalunits;
received_nValue = (paidunits * unitprice) / COIN;
if ( unitprice > 0 && received_nValue > 0 && received_nValue <= orig_nValue )
{
remaining_nValue = (orig_nValue - received_nValue);
printf("total.%llu - paid.%llu, remaining %llu <- %llu (%llu - %llu)\n",(long long)totalunits,(long long)paidunits,(long long)remaining_nValue,(long long)(orig_nValue - received_nValue),(long long)orig_nValue,(long long)received_nValue);
return(ValidateBidRemainder(remaining_units,remaining_nValue,orig_nValue,received_nValue,paidunits,totalunits));
} else return(false);
}
bool SetAskFillamounts(int64_t &received_assetoshis,int64_t &remaining_nValue,int64_t orig_assetoshis,int64_t &paid_nValue,int64_t total_nValue)
{
int64_t remaining_assetoshis; double dunitprice;
if ( total_nValue == 0 )
{
received_assetoshis = remaining_nValue = paid_nValue = 0;
return(false);
}
if ( paid_nValue >= total_nValue )
{
paid_nValue = total_nValue;
received_assetoshis = orig_assetoshis;
remaining_nValue = 0;
fprintf(stderr,"totally filled!\n");
return(true);
}
remaining_nValue = (total_nValue - paid_nValue);
dunitprice = ((double)total_nValue / orig_assetoshis);
received_assetoshis = (paid_nValue / dunitprice);
fprintf(stderr,"remaining_nValue %.8f (%.8f - %.8f)\n",(double)remaining_nValue/COIN,(double)total_nValue/COIN,(double)paid_nValue/COIN);
fprintf(stderr,"unitprice %.8f received_assetoshis %llu orig %llu\n",dunitprice/COIN,(long long)received_assetoshis,(long long)orig_assetoshis);
if ( fabs(dunitprice) > SMALLVAL && received_assetoshis > 0 && received_assetoshis <= orig_assetoshis )
{
remaining_assetoshis = (orig_assetoshis - received_assetoshis);
return(ValidateAskRemainder(remaining_nValue,remaining_assetoshis,orig_assetoshis,received_assetoshis,paid_nValue,total_nValue));
} else return(false);
}
bool ValidateAskRemainder(int64_t remaining_nValue,int64_t remaining_assetoshis,int64_t orig_assetoshis,int64_t received_assetoshis,int64_t paid_nValue,int64_t total_nValue)
{
int64_t unitprice,recvunitprice,newunitprice=0;
if ( orig_assetoshis == 0 || received_assetoshis == 0 || paid_nValue == 0 || total_nValue == 0 )
{
fprintf(stderr,"ValidateAssetRemainder: orig_assetoshis == %llu || received_assetoshis == %llu || paid_nValue == %llu || total_nValue == %llu\n",(long long)orig_assetoshis,(long long)received_assetoshis,(long long)paid_nValue,(long long)total_nValue);
return(false);
}
else if ( total_nValue != (remaining_nValue + paid_nValue) )
{
fprintf(stderr,"ValidateAssetRemainder: total_nValue %llu != %llu (remaining_nValue %llu + %llu paid_nValue)\n",(long long)total_nValue,(long long)(remaining_nValue + paid_nValue),(long long)remaining_nValue,(long long)paid_nValue);
return(false);
}
else if ( orig_assetoshis != (remaining_assetoshis + received_assetoshis) )
{
fprintf(stderr,"ValidateAssetRemainder: orig_assetoshis %llu != %llu (remaining_nValue %llu + %llu received_nValue)\n",(long long)orig_assetoshis,(long long)(remaining_assetoshis - received_assetoshis),(long long)remaining_assetoshis,(long long)received_assetoshis);
return(false);
}
else
{
unitprice = (total_nValue / orig_assetoshis);
recvunitprice = (paid_nValue / received_assetoshis);
if ( remaining_nValue != 0 )
newunitprice = (remaining_nValue / remaining_assetoshis);
if ( recvunitprice < unitprice )
{
fprintf(stderr,"error recvunitprice %.8f < %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/COIN,(double)unitprice/COIN,(double)newunitprice/COIN);
return(false);
}
fprintf(stderr,"got recvunitprice %.8f >= %.8f unitprice, new unitprice %.8f\n",(double)recvunitprice/COIN,(double)unitprice/COIN,(double)newunitprice/COIN);
}
return(true);
}
bool SetSwapFillamounts(int64_t &received_assetoshis,int64_t &remaining_assetoshis2,int64_t orig_assetoshis,int64_t &paid_assetoshis2,int64_t total_assetoshis2)
{
int64_t remaining_assetoshis; double dunitprice;
if ( total_assetoshis2 == 0 )
{
fprintf(stderr,"total_assetoshis2.0 origsatoshis.%llu paid_assetoshis2.%llu\n",(long long)orig_assetoshis,(long long)paid_assetoshis2);
received_assetoshis = remaining_assetoshis2 = paid_assetoshis2 = 0;
return(false);
}
if ( paid_assetoshis2 >= total_assetoshis2 )
{
paid_assetoshis2 = total_assetoshis2;
received_assetoshis = orig_assetoshis;
remaining_assetoshis2 = 0;
fprintf(stderr,"totally filled!\n");
return(true);
}
remaining_assetoshis2 = (total_assetoshis2 - paid_assetoshis2);
dunitprice = ((double)total_assetoshis2 / orig_assetoshis);
received_assetoshis = (paid_assetoshis2 / dunitprice);
fprintf(stderr,"remaining_assetoshis2 %llu (%llu - %llu)\n",(long long)remaining_assetoshis2/COIN,(long long)total_assetoshis2/COIN,(long long)paid_assetoshis2/COIN);
fprintf(stderr,"unitprice %.8f received_assetoshis %llu orig %llu\n",dunitprice/COIN,(long long)received_assetoshis,(long long)orig_assetoshis);
if ( fabs(dunitprice) > SMALLVAL && received_assetoshis > 0 && received_assetoshis <= orig_assetoshis )
{
remaining_assetoshis = (orig_assetoshis - received_assetoshis);
return(ValidateAskRemainder(remaining_assetoshis2,remaining_assetoshis,orig_assetoshis,received_assetoshis,paid_assetoshis2,total_assetoshis2));
} else return(false);
}
bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidunits,int64_t totalunits)
{
int64_t unitprice,recvunitprice,newunitprice=0;
if ( orig_nValue == 0 || received_nValue == 0 || paidunits == 0 || totalunits == 0 ) if ( orig_nValue == 0 || received_nValue == 0 || paidunits == 0 || totalunits == 0 )
{ {
fprintf(stderr,"ValidateAssetRemainder: orig_nValue == %llu || received_nValue == %llu || paidunits == %llu || totalunits == %llu\n",(long long)orig_nValue,(long long)received_nValue,(long long)paidunits,(long long)totalunits); fprintf(stderr,"ValidateAssetRemainder: orig_nValue == %llu || received_nValue == %llu || paidunits == %llu || totalunits == %llu\n",(long long)orig_nValue,(long long)received_nValue,(long long)paidunits,(long long)totalunits);
@@ -72,31 +224,6 @@ bool ValidateAssetRemainder(int32_t sellflag,uint64_t remaining_price,uint64_t r
return(true); return(true);
} }
bool SetAssetFillamounts(int32_t sellflag,uint64_t &received_nValue,uint64_t &remaining_price,uint64_t orig_nValue,uint64_t &paidunits,uint64_t totalunits)
{
uint64_t remaining_nValue,unitprice;
if ( totalunits == 0 )
{
received_nValue = remaining_price = paidunits = 0;
return(false);
}
if ( paidunits >= totalunits )
{
paidunits = totalunits;
received_nValue = orig_nValue;
remaining_price = 0;
fprintf(stderr,"totally filled!\n");
return(true);
}
remaining_price = (totalunits - paidunits);
unitprice = (orig_nValue * COIN) / totalunits; // unit price has 10 decimals precision, eg. unitprice of 100 million is 1 COIN per unit
if ( unitprice > 0 && (received_nValue= (paidunits * unitprice)/COIN) > 0 && received_nValue < orig_nValue )
{
remaining_nValue = (orig_nValue - received_nValue);
return(ValidateAssetRemainder(sellflag,remaining_price,remaining_nValue,orig_nValue,received_nValue,paidunits,totalunits));
} else return(false);
}
CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,std::string name,std::string description) CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,std::string name,std::string description)
{ {
CScript opret; uint8_t evalcode = EVAL_ASSETS; CScript opret; uint8_t evalcode = EVAL_ASSETS;
@@ -104,7 +231,7 @@ CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,st
return(opret); return(opret);
} }
CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,uint64_t price,std::vector<uint8_t> origpubkey) CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector<uint8_t> origpubkey)
{ {
CScript opret; uint8_t evalcode = EVAL_ASSETS; CScript opret; uint8_t evalcode = EVAL_ASSETS;
assetid = revuint256(assetid); assetid = revuint256(assetid);
@@ -128,7 +255,20 @@ CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,uint64_
return(opret); return(opret);
} }
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,uint64_t &price,std::vector<uint8_t> &origpubkey) bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description)
{
std::vector<uint8_t> vopret; uint8_t evalcode,funcid,*script;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( script != 0 && vopret.size() > 2 && script[0] == EVAL_ASSETS && script[1] == 'c' )
{
if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description) != 0 )
return(true);
}
return(0);
}
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey)
{ {
std::vector<uint8_t> vopret; uint8_t funcid=0,*script,e,f; std::vector<uint8_t> vopret; uint8_t funcid=0,*script,e,f;
GetOpReturnData(scriptPubKey, vopret); GetOpReturnData(scriptPubKey, vopret);
@@ -136,7 +276,7 @@ uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &a
memset(&assetid,0,sizeof(assetid)); memset(&assetid,0,sizeof(assetid));
memset(&assetid2,0,sizeof(assetid2)); memset(&assetid2,0,sizeof(assetid2));
price = 0; price = 0;
if ( script[0] == EVAL_ASSETS ) if ( script != 0 && script[0] == EVAL_ASSETS )
{ {
funcid = script[1]; funcid = script[1];
//fprintf(stderr,"decode.[%c]\n",funcid); //fprintf(stderr,"decode.[%c]\n",funcid);
@@ -162,7 +302,7 @@ uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &a
case 'E': case 'e': case 'E': case 'e':
if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> assetid2; ss >> price; ss >> origpubkey) != 0 ) if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> assetid2; ss >> price; ss >> origpubkey) != 0 )
{ {
fprintf(stderr,"got price %llu\n",(long long)price); //fprintf(stderr,"got price %llu\n",(long long)price);
assetid = revuint256(assetid); assetid = revuint256(assetid);
assetid2 = revuint256(assetid2); assetid2 = revuint256(assetid2);
return(funcid); return(funcid);
@@ -177,17 +317,17 @@ uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &a
return(funcid); return(funcid);
} }
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,uint64_t &price,const CTransaction &tx) bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx)
{ {
uint256 assetid,assetid2; uint256 assetid,assetid2;
if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 ) if ( tx.vout.size() > 0 && DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 )
return(true); return(true);
else return(false); else return(false);
} }
bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,const CTransaction& tx) bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,const CTransaction& tx)
{ {
uint256 assetid,assetid2; uint64_t price,nValue=0; int32_t n; uint8_t funcid; std::vector<uint8_t> origpubkey; CScript script; uint256 assetid,assetid2; int64_t price,nValue=0; int32_t n; uint8_t funcid; std::vector<uint8_t> origpubkey; CScript script;
n = tx.vout.size(); n = tx.vout.size();
if ( n == 0 || (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 ) if ( n == 0 || (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 )
return(false); return(false);
@@ -196,9 +336,9 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,co
else return(false); else return(false);
} }
uint64_t IsAssetvout(uint64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid) int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
{ {
uint256 assetid,assetid2; uint64_t nValue=0; int32_t n; uint8_t funcid; uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid;
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too? if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too?
{ {
n = tx.vout.size(); n = tx.vout.size();
@@ -235,7 +375,7 @@ uint64_t IsAssetvout(uint64_t &price,std::vector<uint8_t> &origpubkey,const CTra
return(0); return(0);
} }
uint64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *CCaddr,char *origaddr,const CTransaction &tx,int32_t vini,CTransaction &vinTx) int64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *CCaddr,char *origaddr,const CTransaction &tx,int32_t vini,CTransaction &vinTx)
{ {
uint256 hashBlock; char destaddr[64]; uint256 hashBlock; char destaddr[64];
origaddr[0] = destaddr[0] = CCaddr[0] = 0; origaddr[0] = destaddr[0] = CCaddr[0] = 0;
@@ -256,17 +396,19 @@ uint64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *CCaddr,c
fprintf(stderr,"%s vs %s\n",destaddr,(char *)cp->unspendableCCaddr); fprintf(stderr,"%s vs %s\n",destaddr,(char *)cp->unspendableCCaddr);
return eval->Invalid("invalid vin AssetsCCaddr"); return eval->Invalid("invalid vin AssetsCCaddr");
} }
else if ( vinTx.vout[0].nValue < 10000 ) //else if ( vinTx.vout[0].nValue < 10000 )
return eval->Invalid("invalid dust for buyvin"); // return eval->Invalid("invalid dust for buyvin");
else if ( GetAssetorigaddrs(cp,CCaddr,origaddr,vinTx) == 0 ) else if ( GetAssetorigaddrs(cp,CCaddr,origaddr,vinTx) == 0 )
return eval->Invalid("couldnt get origaddr for buyvin"); return eval->Invalid("couldnt get origaddr for buyvin");
fprintf(stderr,"Got %.8f to origaddr.(%s)\n",(double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr); fprintf(stderr,"Got %.8f to origaddr.(%s)\n",(double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr);
if ( vinTx.vout[0].nValue == 0 )
return eval->Invalid("null value CCvin");
return(vinTx.vout[0].nValue); return(vinTx.vout[0].nValue);
} }
uint64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid) int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid)
{ {
CTransaction vinTx; uint64_t nValue; uint256 assetid,assetid2; uint8_t funcid; CTransaction vinTx; int64_t nValue; uint256 assetid,assetid2; uint8_t funcid;
CCaddr[0] = origaddr[0] = 0; CCaddr[0] = origaddr[0] = 0;
if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 ) if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 )
return(0); return(0);
@@ -275,7 +417,7 @@ uint64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmp
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);
if ( (funcid= DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,assetid,assetid2,tmpprice,tmporigpubkey)) != 'b' && funcid != 'B' ) if ( vinTx.vout.size() > 0 && (funcid= DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,assetid,assetid2,tmpprice,tmporigpubkey)) != 'b' && funcid != 'B' )
return eval->Invalid("invalid opreturn for buyvin"); return eval->Invalid("invalid opreturn for buyvin");
else if ( refassetid != assetid ) else if ( refassetid != assetid )
return eval->Invalid("invalid assetid for buyvin"); return eval->Invalid("invalid assetid for buyvin");
@@ -286,20 +428,20 @@ uint64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmp
return(nValue); return(nValue);
} }
uint64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,uint64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid) int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid)
{ {
CTransaction vinTx; uint64_t nValue,assetoshis; CTransaction vinTx; int64_t nValue,assetoshis;
fprintf(stderr,"AssetValidateSellvin\n"); fprintf(stderr,"AssetValidateSellvin\n");
if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 ) if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 )
return(0); return(0);
if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,0,assetid)) != 0 ) if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 )
return eval->Invalid("invalid missing CC vout0 for sellvin"); return eval->Invalid("invalid missing CC vout0 for sellvin");
else return(assetoshis); else return(assetoshis);
} }
bool AssetExactAmounts(struct CCcontract_info *cp,uint64_t &inputs,int32_t starti,uint64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid) bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid)
{ {
CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; uint64_t assetoshis; std::vector<uint8_t> tmporigpubkey; uint64_t tmpprice; CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t assetoshis; std::vector<uint8_t> tmporigpubkey; int64_t tmpprice;
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
inputs = outputs = 0; inputs = outputs = 0;

View File

@@ -15,22 +15,30 @@
#include "CCassets.h" #include "CCassets.h"
uint64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,uint64_t total,int32_t maxinputs) // need allassets
// find asset
int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs)
{ {
char coinaddr[64]; uint64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0; char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t j,vout,n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk); GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr); SetCCunspents(unspentOutputs,coinaddr);
//std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
vout = (int32_t)it->first.index;
for (j=0; j<mtx.vin.size(); j++)
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
break;
if ( j != mtx.vin.size() )
continue;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsAssetvout(price,origpubkey,vintx,(int32_t)it->first.index,assetid)) > 0 ) if ( (nValue= IsAssetvout(price,origpubkey,vintx,vout,assetid)) > 0 )
{ {
if ( total != 0 && maxinputs != 0 ) if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,(int32_t)it->first.index,CScript())); mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis; nValue = it->second.satoshis;
totalinputs += nValue; totalinputs += nValue;
n++; n++;
@@ -42,16 +50,60 @@ uint64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
return(totalinputs); return(totalinputs);
} }
uint64_t GetAssetBalance(CPubKey pk,uint256 tokenid) int64_t GetAssetBalance(CPubKey pk,uint256 tokenid)
{ {
CMutableTransaction mtx; struct CCcontract_info *cp,C; CMutableTransaction mtx; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
return(AddAssetInputs(cp,mtx,pk,tokenid,0,0)); return(AddAssetInputs(cp,mtx,pk,tokenid,0,0));
} }
UniValue AssetInfo(uint256 assetid)
{
UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description; char str[67],numstr[65];
if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find assetid\n");
result.push_back(Pair("error","cant find assetid"));
return(0);
}
if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 )
{
fprintf(stderr,"assetid isnt assetcreation txid\n");
result.push_back(Pair("error","assetid isnt assetcreation txid"));
}
result.push_back(Pair("result","success"));
result.push_back(Pair("tokenid",uint256_str(str,assetid)));
result.push_back(Pair("owner",pubkey33_str(str,origpubkey.data())));
result.push_back(Pair("name",name));
sprintf(numstr,"%.8f",(double)vintx.vout[0].nValue/COIN);
result.push_back(Pair("supply",numstr));
result.push_back(Pair("description",description));
return(result);
}
UniValue AssetList()
{
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description; char str[65];
cp = CCinit(&C,EVAL_ASSETS);
SetCCtxids(addressIndex,cp->normaladdr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
txid = it->first.txhash;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{
if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) != 0 )
{
result.push_back(uint256_str(str,txid));
}
}
}
return(result);
}
UniValue AssetOrders(uint256 refassetid) UniValue AssetOrders(uint256 refassetid)
{ {
uint64_t price; uint256 txid,hashBlock,assetid,assetid2; std::vector<uint8_t> origpubkey; CTransaction vintx; UniValue result(UniValue::VARR); std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; uint8_t funcid; char funcidstr[16],origaddr[64],assetidstr[65]; struct CCcontract_info *cp,C; static uint256 zero;
int64_t price; uint256 txid,hashBlock,assetid,assetid2; std::vector<uint8_t> origpubkey; CTransaction vintx; UniValue result(UniValue::VARR); std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; uint8_t funcid; char numstr[32],funcidstr[16],origaddr[64],assetidstr[65]; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
SetCCunspents(unspentOutputs,(char *)cp->unspendableCCaddr); SetCCunspents(unspentOutputs,(char *)cp->unspendableCCaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
@@ -59,18 +111,41 @@ UniValue AssetOrders(uint256 refassetid)
txid = it->first.txhash; txid = it->first.txhash;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (funcid= DecodeAssetOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey)) != 0 ) if ( vintx.vout.size() > 0 && (funcid= DecodeAssetOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey)) != 0 )
{ {
if ( refassetid != zero && assetid != refassetid )
{
//int32_t z;
//for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&txid)[z]);
//fprintf(stderr," txid\n");
//for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&assetid)[z]);
//fprintf(stderr," assetid\n");
//for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&refassetid)[z]);
//fprintf(stderr," refassetid\n");
continue;
}
if ( vintx.vout[it->first.index].nValue == 0 )
continue;
UniValue item(UniValue::VOBJ); UniValue item(UniValue::VOBJ);
funcidstr[0] = funcid; funcidstr[0] = funcid;
funcidstr[1] = 0; funcidstr[1] = 0;
item.push_back(Pair("funcid", funcidstr)); item.push_back(Pair("funcid", funcidstr));
item.push_back(Pair("txid", uint256_str(assetidstr,txid))); item.push_back(Pair("txid", uint256_str(assetidstr,txid)));
item.push_back(Pair("vout", (int64_t)it->first.index)); item.push_back(Pair("vout", (int64_t)it->first.index));
item.push_back(Pair("amount", (double)vintx.vout[it->first.index].nValue/COIN));
if ( funcid == 'b' || funcid == 'B' ) if ( funcid == 'b' || funcid == 'B' )
item.push_back(Pair("bidamount",(double)vintx.vout[0].nValue/COIN)); {
else item.push_back(Pair("askamount",(double)vintx.vout[0].nValue)); sprintf(numstr,"%.8f",(double)vintx.vout[it->first.index].nValue/COIN);
item.push_back(Pair("amount",numstr));
sprintf(numstr,"%.8f",(double)vintx.vout[0].nValue/COIN);
item.push_back(Pair("bidamount",numstr));
}
else
{
sprintf(numstr,"%llu",(long long)vintx.vout[it->first.index].nValue);
item.push_back(Pair("amount",numstr));
sprintf(numstr,"%llu",(long long)vintx.vout[0].nValue);
item.push_back(Pair("askamount",numstr));
}
if ( origpubkey.size() == 33 ) if ( origpubkey.size() == 33 )
{ {
GetCCaddress(cp,origaddr,pubkey2pk(origpubkey)); GetCCaddress(cp,origaddr,pubkey2pk(origpubkey));
@@ -82,8 +157,19 @@ UniValue AssetOrders(uint256 refassetid)
item.push_back(Pair("otherid",uint256_str(assetidstr,assetid2))); item.push_back(Pair("otherid",uint256_str(assetidstr,assetid2)));
if ( price > 0 ) if ( price > 0 )
{ {
item.push_back(Pair("totalrequired", (int64_t)price)); if ( funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'e' )
item.push_back(Pair("price", (double)vintx.vout[0].nValue / (price * COIN))); {
sprintf(numstr,"%.8f",(double)price / COIN);
item.push_back(Pair("totalrequired", numstr));
sprintf(numstr,"%.8f",(double)price / (COIN * vintx.vout[0].nValue));
item.push_back(Pair("price", numstr));
}
else
{
item.push_back(Pair("totalrequired", (int64_t)price));
sprintf(numstr,"%.8f",(double)vintx.vout[0].nValue / (price * COIN));
item.push_back(Pair("price",numstr));
}
} }
result.push_back(item); result.push_back(item);
//fprintf(stderr,"func.(%c) %s/v%d %.8f\n",funcid,uint256_str(assetidstr,txid),(int32_t)it->first.index,(double)vintx.vout[it->first.index].nValue/COIN); //fprintf(stderr,"func.(%c) %s/v%d %.8f\n",funcid,uint256_str(assetidstr,txid),(int32_t)it->first.index,(double)vintx.vout[it->first.index].nValue/COIN);
@@ -93,9 +179,14 @@ UniValue AssetOrders(uint256 refassetid)
return(result); return(result);
} }
std::string CreateAsset(uint64_t txfee,uint64_t assetsupply,std::string name,std::string description) std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description)
{ {
CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C;
if ( assetsupply < 0 )
{
fprintf(stderr,"negative assetsupply %lld\n",(long long)assetsupply);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( name.size() > 32 || description.size() > 4096 ) if ( name.size() > 32 || description.size() > 4096 )
{ {
@@ -109,14 +200,19 @@ std::string CreateAsset(uint64_t txfee,uint64_t assetsupply,std::string name,std
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,assetsupply,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,assetsupply,mypk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description)));
} }
return(0); return(0);
} }
std::string AssetTransfer(uint64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,uint64_t total) std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total)
{ {
CMutableTransaction mtx; CPubKey mypk; uint64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
if ( total < 0 )
{
fprintf(stderr,"negative total %lld\n",(long long)total);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
@@ -128,6 +224,7 @@ std::string AssetTransfer(uint64_t txfee,uint256 assetid,std::vector<uint8_t> de
{ {
for (i=0; i<n; i++) for (i=0; i<n; i++)
total += amounts[i];*/ total += amounts[i];*/
mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 ) if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
{ {
if ( inputs > total ) if ( inputs > total )
@@ -136,16 +233,31 @@ std::string AssetTransfer(uint64_t txfee,uint256 assetid,std::vector<uint8_t> de
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,total,pubkey2pk(destpubkey))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,total,pubkey2pk(destpubkey)));
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
} else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN); } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN);
//} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size()); //} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size());
} }
return(0); return(0);
} }
std::string CreateBuyOffer(uint64_t txfee,uint64_t bidamount,uint256 assetid,uint64_t pricetotal) std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal)
{ {
CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; uint256 hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description;
if ( bidamount < 0 || pricetotal < 0 )
{
fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n",(long long)bidamount,(long long)pricetotal);
return(0);
}
if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find assetid\n");
return(0);
}
if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 )
{
fprintf(stderr,"assetid isnt assetcreation txid\n");
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
@@ -153,22 +265,62 @@ std::string CreateBuyOffer(uint64_t txfee,uint64_t bidamount,uint256 assetid,uin
if ( AddNormalinputs(mtx,mypk,bidamount+txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,bidamount+txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount,GetUnspendable(cp,0))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount,GetUnspendable(cp,0)));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet('b',assetid,zeroid,pricetotal,Mypubkey()))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('b',assetid,zeroid,pricetotal,Mypubkey())));
} }
return(0); return(0);
} }
std::string CreateSell(uint64_t txfee,uint64_t askamount,uint256 assetid,uint256 assetid2,uint64_t pricetotal) std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal)
{ {
CMutableTransaction mtx; CPubKey mypk; uint64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
if ( askamount < 0 || pricetotal < 0 )
{
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{ {
mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 )
{ {
if ( inputs < askamount )
askamount = inputs;
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0)));
if ( inputs > askamount )
CCchange = (inputs - askamount);
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey());
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n");
}
fprintf(stderr,"need some native coins to place ask\n");
return(0);
}
std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal)
{
CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
if ( askamount < 0 || pricetotal < 0 )
{
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{
mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 )
{
if ( inputs < askamount )
askamount = inputs;
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0)));
if ( inputs > askamount ) if ( inputs > askamount )
CCchange = (inputs - askamount); CCchange = (inputs - askamount);
@@ -176,62 +328,74 @@ std::string CreateSell(uint64_t txfee,uint64_t askamount,uint256 assetid,uint256
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
if ( assetid2 == zeroid ) if ( assetid2 == zeroid )
opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey()); opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey());
else opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey()); else
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); {
} opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey());
}
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n");
} }
fprintf(stderr,"need some native coins to place ask\n");
return(0); return(0);
} }
std::string CancelBuyOffer(uint64_t txfee,uint256 assetid,uint256 bidtxid) std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
{ {
CMutableTransaction mtx; CTransaction vintx; uint256 hashBlock; uint64_t bidamount; CPubKey mypk; struct CCcontract_info *cp,C; CMutableTransaction mtx; CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t bidamount; CPubKey mypk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{ {
mask = ~((1LL << mtx.vin.size()) - 1);
if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 )
{ {
bidamount = vintx.vout[0].nValue; bidamount = vintx.vout[0].nValue;
mtx.vin.push_back(CTxIn(bidtxid,0,CScript())); mtx.vin.push_back(CTxIn(bidtxid,0,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));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet('o',assetid,zeroid,0,Mypubkey()))); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('o',assetid,zeroid,0,Mypubkey())));
} }
} }
return(0); return(0);
} }
std::string CancelSell(uint64_t txfee,uint256 assetid,uint256 asktxid) std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
{ {
CMutableTransaction mtx; CTransaction vintx; uint256 hashBlock; uint64_t askamount; CPubKey mypk; struct CCcontract_info *cp,C; CMutableTransaction mtx; CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{ {
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.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,mypk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet('x',assetid,zeroid,0,Mypubkey()))); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('x',assetid,zeroid,0,Mypubkey())));
} }
} }
return(0); return(0);
} }
std::string FillBuyOffer(uint64_t txfee,uint256 assetid,uint256 bidtxid,uint64_t fillamount) std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount)
{ {
CTransaction vintx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; int32_t bidvout=0; uint64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C; CTransaction vintx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; int32_t bidvout=0; uint64_t mask; int64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C;
if ( fillamount < 0 )
{
fprintf(stderr,"negative fillamount %lld\n",(long long)fillamount);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{ {
mask = ~((1LL << mtx.vin.size()) - 1);
if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 )
{ {
bidamount = vintx.vout[bidvout].nValue; bidamount = vintx.vout[bidvout].nValue;
@@ -239,51 +403,68 @@ std::string FillBuyOffer(uint64_t txfee,uint256 assetid,uint256 bidtxid,uint64_t
mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript())); mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript()));
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,fillamount,60)) > 0 ) if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,fillamount,60)) > 0 )
{ {
if ( inputs < fillamount )
fillamount = inputs;
SetBidFillamounts(paid_amount,remaining_required,bidamount,fillamount,origprice);
if ( inputs > fillamount ) if ( inputs > fillamount )
CCchange = (inputs - fillamount); CCchange = (inputs - fillamount);
SetAssetFillamounts(0,paid_amount,remaining_required,bidamount,fillamount,origprice);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount - paid_amount,GetUnspendable(cp,0))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount - paid_amount,GetUnspendable(cp,0)));
mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,fillamount,pubkey2pk(origpubkey))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,fillamount,pubkey2pk(origpubkey)));
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
fprintf(stderr,"remaining %llu -> origpubkey\n",(long long)remaining_required); fprintf(stderr,"remaining %llu -> origpubkey\n",(long long)remaining_required);
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet('B',assetid,zeroid,remaining_required,origpubkey))); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('B',assetid,zeroid,remaining_required,origpubkey)));
} else fprintf(stderr,"filltx wasnt for assetid\n"); } else return("dont have any assets to fill bid\n");
} }
} }
return(0); return("no normal coins left");
} }
std::string FillSell(uint64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,uint64_t fillamount) std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillunits)
{ {
CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; int32_t askvout=0; uint64_t totalunits,askamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C; CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C;
if ( fillunits < 0 )
{
fprintf(stderr,"negative fillunits %lld\n",(long long)fillunits);
return(0);
}
cp = CCinit(&C,EVAL_ASSETS); cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{ {
mask = ~((1LL << mtx.vin.size()) - 1);
if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 )
{ {
askamount = vintx.vout[askvout].nValue; orig_assetoshis = vintx.vout[askvout].nValue;
SetAssetOrigpubkey(origpubkey,totalunits,vintx); SetAssetOrigpubkey(origpubkey,total_nValue,vintx);
dprice = (double)total_nValue / orig_assetoshis;
paid_nValue = dprice * fillunits;
mtx.vin.push_back(CTxIn(asktxid,askvout,CScript())); mtx.vin.push_back(CTxIn(asktxid,askvout,CScript()));
if ( assetid2 == zeroid ) if ( assetid2 != zeroid )
inputs = AddAssetInputs(cp,mtx,mypk,assetid2,fillamount,60); inputs = AddAssetInputs(cp,mtx,mypk,assetid2,paid_nValue,60);
else inputs = AddNormalinputs(mtx,mypk,fillamount,60); else
{
inputs = AddNormalinputs(mtx,mypk,paid_nValue,60);
mask = ~((1LL << mtx.vin.size()) - 1);
}
if ( inputs > 0 ) if ( inputs > 0 )
{ {
if ( assetid2 == zeroid && inputs > fillamount ) if ( inputs < paid_nValue )
CCchange = (inputs - fillamount); paid_nValue = inputs;
SetAssetFillamounts(1,paid_amount,remaining_required,askamount,fillamount,totalunits); if ( assetid2 != zeroid )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount - paid_amount,GetUnspendable(cp,0))); SetSwapFillamounts(received_assetoshis,remaining_nValue,orig_assetoshis,paid_nValue,total_nValue);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,paid_amount,mypk)); else SetAskFillamounts(received_assetoshis,remaining_nValue,orig_assetoshis,paid_nValue,total_nValue);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,fillamount,pubkey2pk(origpubkey))); if ( assetid2 != zeroid && inputs > paid_nValue )
CCchange = (inputs - paid_nValue);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,orig_assetoshis - received_assetoshis,GetUnspendable(cp,0)));
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,received_assetoshis,mypk));
mtx.vout.push_back(CTxOut(paid_nValue,CScript() << origpubkey << OP_CHECKSIG));
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
fprintf(stderr,"remaining %llu -> origpubkey\n",(long long)remaining_required); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet(assetid2!=zeroid?'E':'S',assetid,assetid2,remaining_nValue,origpubkey)));
return(FinalizeCCTx(cp,mtx,mypk,txfee,EncodeAssetOpRet(assetid2==zeroid?'E':'S',assetid,assetid2,remaining_required,origpubkey)));
} else fprintf(stderr,"filltx not enough utxos\n"); } else fprintf(stderr,"filltx not enough utxos\n");
} }
} }

View File

@@ -36,6 +36,12 @@
4. make helper functions to create rawtx for RPC functions 4. make helper functions to create rawtx for RPC functions
5. add rpc calls to rpcserver.cpp and rpcserver.h and in one of the rpc.cpp files 5. add rpc calls to rpcserver.cpp and rpcserver.h and in one of the rpc.cpp files
6. add the new .cpp files to src/Makefile.am 6. add the new .cpp files to src/Makefile.am
IMPORTANT: make sure that all CC inputs and CC outputs are properly accounted for and reconcile to the satoshi. The built in utxo management will enforce overall vin/vout constraints but it wont know anything about the CC constraints. That is what your Validate function needs to do.
Generally speaking, there will be normal coins that change into CC outputs, CC outputs that go back to being normal coins, CC outputs that are spent to new CC outputs.
Make sure both the CC coins and normal coins are preserved and follow the rules that make sense. It is a good idea to define specific roles for specific vins and vouts to reduce the complexity of validation.
*/ */
//BTCD Address: RAssetsAtGnvwgK9gVHBbAU4sVTah1hAm5 //BTCD Address: RAssetsAtGnvwgK9gVHBbAU4sVTah1hAm5
@@ -46,7 +52,8 @@
// Assets, aka Tokens // Assets, aka Tokens
#define FUNCNAME IsAssetsInput #define FUNCNAME IsAssetsInput
#define EVALCODE EVAL_ASSETS #define EVALCODE EVAL_ASSETS
const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6"; //"RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u"; const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6";
const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u";
char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" }; char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" };
uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 }; uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 };
@@ -57,7 +64,8 @@ uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xb
// Faucet // Faucet
#define FUNCNAME IsFaucetInput #define FUNCNAME IsFaucetInput
#define EVALCODE EVAL_FAUCET #define EVALCODE EVAL_FAUCET
const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC"; //"RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk"; const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC";
const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk";
char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" }; char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" };
uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 }; uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 };
@@ -68,9 +76,10 @@ uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4
// Rewards // Rewards
#define FUNCNAME IsRewardsInput #define FUNCNAME IsRewardsInput
#define EVALCODE EVAL_REWARDS #define EVALCODE EVAL_REWARDS
const char *RewardsCCaddr = "RJCqA4jQTFEZ841dZgxko8aYgUU3FRNGNm"; //"RYRJGMAYEfLCZ6ZddbpxPiUZ1sens8vPYK"; const char *RewardsCCaddr = "RTsRBYL1HSvMoE3qtBJkyiswdVaWkm8YTK";
char RewardsCChexstr[67] = { "026f00fdc2f1ed0006d66e2ca1787633590581c2fc90e7cb7b01a6c1131b40e94d" }; const char *RewardsNormaladdr = "RMgye9jeczNjQx9Uzq8no8pTLiCSwuHwkz";
uint8_t RewardsCCpriv[32] = { 0x9f, 0x0c, 0x57, 0xdc, 0x6f, 0x78, 0xae, 0xb0, 0xc7, 0x62, 0x9e, 0x7d, 0x2b, 0x90, 0x6b, 0xbd, 0x40, 0x78, 0x19, 0x5b, 0x3c, 0xb8, 0x82, 0x2d, 0x29, 0x84, 0x72, 0x7a, 0x59, 0x5a, 0x4b, 0x69 }; char RewardsCChexstr[67] = { "03da60379d924c2c30ac290d2a86c2ead128cb7bd571f69211cb95356e2dcc5eb9" };
uint8_t RewardsCCpriv[32] = { 0x82, 0xf5, 0xd2, 0xe7, 0xd6, 0x99, 0x33, 0x77, 0xfb, 0x80, 0x00, 0x97, 0x23, 0x3d, 0x1e, 0x6f, 0x61, 0xa9, 0xb5, 0x2e, 0x5e, 0xb4, 0x96, 0x6f, 0xbc, 0xed, 0x6b, 0xe2, 0xbb, 0x7b, 0x4b, 0xb3 };
#include "CCcustom.inc" #include "CCcustom.inc"
#undef FUNCNAME #undef FUNCNAME
#undef EVALCODE #undef EVALCODE
@@ -78,7 +87,8 @@ uint8_t RewardsCCpriv[32] = { 0x9f, 0x0c, 0x57, 0xdc, 0x6f, 0x78, 0xae, 0xb0, 0x
// Dice // Dice
#define FUNCNAME IsDiceInput #define FUNCNAME IsDiceInput
#define EVALCODE EVAL_DICE #define EVALCODE EVAL_DICE
const char *DiceCCaddr = "REabWB7KjFN5C3LFMZ5odExHPenYzHLtVw"; //"RLEe8f7Eg3TDuXii9BmNiiiaVGraHUt25c"; const char *DiceCCaddr = "REabWB7KjFN5C3LFMZ5odExHPenYzHLtVw";
const char *DiceNormaladdr = "RLEe8f7Eg3TDuXii9BmNiiiaVGraHUt25c";
char DiceCChexstr[67] = { "039d966927cfdadab3ee6c56da63c21f17ea753dde4b3dfd41487103e24b27e94e" }; char DiceCChexstr[67] = { "039d966927cfdadab3ee6c56da63c21f17ea753dde4b3dfd41487103e24b27e94e" };
uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, 0xf1, 0x2f, 0x04, 0x5f, 0x01, 0x26, 0xb8, 0xd1, 0xac, 0x3a, 0x5a, 0xea, 0xe0, 0x25, 0xa2, 0x8f, 0x2a, 0x8e, 0x0e, 0xf9, 0x34, 0xfa, 0x77 }; uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1, 0xf1, 0x2f, 0x04, 0x5f, 0x01, 0x26, 0xb8, 0xd1, 0xac, 0x3a, 0x5a, 0xea, 0xe0, 0x25, 0xa2, 0x8f, 0x2a, 0x8e, 0x0e, 0xf9, 0x34, 0xfa, 0x77 };
#include "CCcustom.inc" #include "CCcustom.inc"
@@ -88,7 +98,8 @@ uint8_t DiceCCpriv[32] = { 0x0e, 0xe8, 0xf5, 0xb4, 0x3d, 0x25, 0xcc, 0x35, 0xd1,
// Lotto // Lotto
#define FUNCNAME IsLottoInput #define FUNCNAME IsLottoInput
#define EVALCODE EVAL_LOTTO #define EVALCODE EVAL_LOTTO
const char *LottoCCaddr = "RNXZxgyWSAE6XS3qGnTaf5dVNCxnYzhPrg"; //"RLW6hhRqBZZMBndnyPv29Yg3krh6iBYCyg"; const char *LottoCCaddr = "RNXZxgyWSAE6XS3qGnTaf5dVNCxnYzhPrg";
const char *LottoNormaladdr = "RLW6hhRqBZZMBndnyPv29Yg3krh6iBYCyg";
char LottoCChexstr[67] = { "03f72d2c4db440df1e706502b09ca5fec73ffe954ea1883e4049e98da68690d98f" }; char LottoCChexstr[67] = { "03f72d2c4db440df1e706502b09ca5fec73ffe954ea1883e4049e98da68690d98f" };
uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80, 0x4e, 0x25, 0x55, 0xc0, 0x50, 0x66, 0x84, 0xbb, 0xa2, 0xe7, 0xc0, 0x39, 0x17, 0xb4, 0xc5, 0x07, 0xb7, 0x3f, 0xca, 0x07, 0xb0, 0x9a, 0xeb }; uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80, 0x4e, 0x25, 0x55, 0xc0, 0x50, 0x66, 0x84, 0xbb, 0xa2, 0xe7, 0xc0, 0x39, 0x17, 0xb4, 0xc5, 0x07, 0xb7, 0x3f, 0xca, 0x07, 0xb0, 0x9a, 0xeb };
#include "CCcustom.inc" #include "CCcustom.inc"
@@ -98,7 +109,8 @@ uint8_t LottoCCpriv[32] = { 0xb4, 0xac, 0xc2, 0xd9, 0x67, 0x34, 0xd7, 0x58, 0x80
// Ponzi // Ponzi
#define FUNCNAME IsPonziInput #define FUNCNAME IsPonziInput
#define EVALCODE EVAL_PONZI #define EVALCODE EVAL_PONZI
const char *PonziCCaddr = "RUKTbLBeKgHkm3Ss4hKZP3ikuLW1xx7B2x"; //"RWSHRbxnJYLvDjpcQ2i8MekgP6h2ctTKaj"; const char *PonziCCaddr = "RUKTbLBeKgHkm3Ss4hKZP3ikuLW1xx7B2x";
const char *PonziNormaladdr = "RWSHRbxnJYLvDjpcQ2i8MekgP6h2ctTKaj";
char PonziCChexstr[67] = { "039b52d294b413b07f3643c1a28c5467901a76562d8b39a785910ae0a0f3043810" }; char PonziCChexstr[67] = { "039b52d294b413b07f3643c1a28c5467901a76562d8b39a785910ae0a0f3043810" };
uint8_t PonziCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, 0x34, 0xe1, 0x21, 0xb8, 0x02, 0xb9, 0x4b, 0x12, 0x37, 0x8f, 0xa0, 0x86, 0x23, 0x50, 0xb2, 0x5f, 0xe4, 0xe7, 0x36, 0x0f, 0xda, 0xae, 0xfc }; uint8_t PonziCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6, 0x34, 0xe1, 0x21, 0xb8, 0x02, 0xb9, 0x4b, 0x12, 0x37, 0x8f, 0xa0, 0x86, 0x23, 0x50, 0xb2, 0x5f, 0xe4, 0xe7, 0x36, 0x0f, 0xda, 0xae, 0xfc };
#include "CCcustom.inc" #include "CCcustom.inc"
@@ -108,7 +120,8 @@ uint8_t PonziCCpriv[32] = { 0x11, 0xe1, 0xea, 0x3e, 0xdb, 0x36, 0xf0, 0xa8, 0xc6
// Auction // Auction
#define FUNCNAME IsAuctionInput #define FUNCNAME IsAuctionInput
#define EVALCODE EVAL_AUCTION #define EVALCODE EVAL_AUCTION
const char *AuctionCCaddr = "RL4YPX7JYG3FnvoPqWF2pn3nQknH5NWEwx"; //"RFtVDNmdTZBTNZdmFRbfBgJ6LitgTghikL"; const char *AuctionCCaddr = "RL4YPX7JYG3FnvoPqWF2pn3nQknH5NWEwx";
const char *AuctionNormaladdr = "RFtVDNmdTZBTNZdmFRbfBgJ6LitgTghikL";
char AuctionCChexstr[67] = { "037eefe050c14cb60ae65d5b2f69eaa1c9006826d729bc0957bdc3024e3ca1dbe6" }; char AuctionCChexstr[67] = { "037eefe050c14cb60ae65d5b2f69eaa1c9006826d729bc0957bdc3024e3ca1dbe6" };
uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x28, 0x59, 0xf5, 0xea, 0xda, 0xec, 0x0d, 0x11, 0xcd, 0x38, 0x47, 0xac, 0x0b, 0x6f, 0x19, 0xc0, 0x24, 0x36, 0xbf, 0x1c, 0x0a, 0x06, 0x31, 0xfb }; uint8_t AuctionCCpriv[32] = { 0x8c, 0x1b, 0xb7, 0x8c, 0x02, 0xa3, 0x9d, 0x21, 0x28, 0x59, 0xf5, 0xea, 0xda, 0xec, 0x0d, 0x11, 0xcd, 0x38, 0x47, 0xac, 0x0b, 0x6f, 0x19, 0xc0, 0x24, 0x36, 0xbf, 0x1c, 0x0a, 0x06, 0x31, 0xfb };
#include "CCcustom.inc" #include "CCcustom.inc"
@@ -122,6 +135,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
{ {
case EVAL_ASSETS: case EVAL_ASSETS:
strcpy(cp->unspendableCCaddr,AssetsCCaddr); strcpy(cp->unspendableCCaddr,AssetsCCaddr);
strcpy(cp->normaladdr,AssetsNormaladdr);
strcpy(cp->CChexstr,AssetsCChexstr); strcpy(cp->CChexstr,AssetsCChexstr);
memcpy(cp->CCpriv,AssetsCCpriv,32); memcpy(cp->CCpriv,AssetsCCpriv,32);
cp->validate = AssetsValidate; cp->validate = AssetsValidate;
@@ -129,6 +143,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_FAUCET: case EVAL_FAUCET:
strcpy(cp->unspendableCCaddr,FaucetCCaddr); strcpy(cp->unspendableCCaddr,FaucetCCaddr);
strcpy(cp->normaladdr,FaucetNormaladdr);
strcpy(cp->CChexstr,FaucetCChexstr); strcpy(cp->CChexstr,FaucetCChexstr);
memcpy(cp->CCpriv,FaucetCCpriv,32); memcpy(cp->CCpriv,FaucetCCpriv,32);
cp->validate = FaucetValidate; cp->validate = FaucetValidate;
@@ -136,6 +151,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_REWARDS: case EVAL_REWARDS:
strcpy(cp->unspendableCCaddr,RewardsCCaddr); strcpy(cp->unspendableCCaddr,RewardsCCaddr);
strcpy(cp->normaladdr,RewardsNormaladdr);
strcpy(cp->CChexstr,RewardsCChexstr); strcpy(cp->CChexstr,RewardsCChexstr);
memcpy(cp->CCpriv,RewardsCCpriv,32); memcpy(cp->CCpriv,RewardsCCpriv,32);
cp->validate = RewardsValidate; cp->validate = RewardsValidate;
@@ -143,6 +159,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_DICE: case EVAL_DICE:
strcpy(cp->unspendableCCaddr,DiceCCaddr); strcpy(cp->unspendableCCaddr,DiceCCaddr);
strcpy(cp->normaladdr,DiceNormaladdr);
strcpy(cp->CChexstr,DiceCChexstr); strcpy(cp->CChexstr,DiceCChexstr);
memcpy(cp->CCpriv,DiceCCpriv,32); memcpy(cp->CCpriv,DiceCCpriv,32);
cp->validate = DiceValidate; cp->validate = DiceValidate;
@@ -150,6 +167,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_LOTTO: case EVAL_LOTTO:
strcpy(cp->unspendableCCaddr,LottoCCaddr); strcpy(cp->unspendableCCaddr,LottoCCaddr);
strcpy(cp->normaladdr,LottoNormaladdr);
strcpy(cp->CChexstr,LottoCChexstr); strcpy(cp->CChexstr,LottoCChexstr);
memcpy(cp->CCpriv,LottoCCpriv,32); memcpy(cp->CCpriv,LottoCCpriv,32);
cp->validate = LottoValidate; cp->validate = LottoValidate;
@@ -157,6 +175,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_PONZI: case EVAL_PONZI:
strcpy(cp->unspendableCCaddr,PonziCCaddr); strcpy(cp->unspendableCCaddr,PonziCCaddr);
strcpy(cp->normaladdr,PonziNormaladdr);
strcpy(cp->CChexstr,PonziCChexstr); strcpy(cp->CChexstr,PonziCChexstr);
memcpy(cp->CCpriv,PonziCCpriv,32); memcpy(cp->CCpriv,PonziCCpriv,32);
cp->validate = PonziValidate; cp->validate = PonziValidate;
@@ -164,6 +183,7 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
break; break;
case EVAL_AUCTION: case EVAL_AUCTION:
strcpy(cp->unspendableCCaddr,AuctionCCaddr); strcpy(cp->unspendableCCaddr,AuctionCCaddr);
strcpy(cp->normaladdr,AuctionNormaladdr);
strcpy(cp->CChexstr,AuctionCChexstr); strcpy(cp->CChexstr,AuctionCChexstr);
memcpy(cp->CCpriv,AuctionCCpriv,32); memcpy(cp->CCpriv,AuctionCCpriv,32);
cp->validate = AuctionValidate; cp->validate = AuctionValidate;

View File

@@ -28,10 +28,13 @@
#include <univalue.h> #include <univalue.h>
#include <exception> #include <exception>
#define SMALLVAL 0.000000000000001
struct CCcontract_info struct CCcontract_info
{ {
uint256 prevtxid; uint256 prevtxid;
char unspendableCCaddr[64],CChexstr[72]; char unspendableCCaddr[64],CChexstr[72],normaladdr[64];
uint8_t CCpriv[32]; uint8_t CCpriv[32];
bool (*validate)(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); bool (*validate)(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
bool (*ismyvin)(CScript const& scriptSig); bool (*ismyvin)(CScript const& scriptSig);
@@ -58,6 +61,7 @@ int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str); uint64_t stringbits(char *str);
uint256 revuint256(uint256 txid); uint256 revuint256(uint256 txid);
char *uint256_str(char *dest,uint256 txid); char *uint256_str(char *dest,uint256 txid);
char *pubkey33_str(char *dest,uint8_t *pubkey33);
uint256 Parseuint256(char *hexstr); uint256 Parseuint256(char *hexstr);
CPubKey pubkey2pk(std::vector<uint8_t> pubkey); CPubKey pubkey2pk(std::vector<uint8_t> pubkey);
bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk); bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk);
@@ -66,10 +70,13 @@ bool PreventCC(Eval* eval,const CTransaction &tx,int32_t preventCCvins,int32_t n
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
std::vector<uint8_t> Mypubkey(); std::vector<uint8_t> Mypubkey();
bool Myprivkey(uint8_t myprivkey[]); bool Myprivkey(uint8_t myprivkey[]);
int64_t CCduration(uint256 txid);
// CCtx // CCtx
std::string FinalizeCCTx(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret);
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr); void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs); uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs);
uint64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout);
#endif #endif

View File

@@ -22,9 +22,12 @@
#define EVAL_REWARDS 0xe5 #define EVAL_REWARDS 0xe5
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
UniValue RewardsInfo(uint256 rewardid);
UniValue RewardsList();
std::string RewardsFund(uint64_t txfee,char *planstr,uint64_t funds,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit); std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit);
std::string RewardsLock(uint64_t txfee,char *planstr,uint64_t amount); std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 txid); std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid);
#endif #endif

View File

@@ -38,15 +38,16 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,uint64_t utxovalue,const CScri
#endif #endif
} }
std::string FinalizeCCTx(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret)
{ {
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t vinimask=0,utxovalues[64],change,totaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*cond; CPubKey unspendablepk; CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0,utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*cond; CPubKey unspendablepk;
n = mtx.vout.size(); n = mtx.vout.size();
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
//if ( mtx.vout[i].scriptPubKey.IsPayToCryptoCondition() == 0 ) if ( mtx.vout[i].scriptPubKey.IsPayToCryptoCondition() == 0 )
totaloutputs += mtx.vout[i].nValue; normaloutputs += mtx.vout[i].nValue;
totaloutputs += mtx.vout[i].nValue;
} }
if ( (n= mtx.vin.size()) > 64 ) if ( (n= mtx.vin.size()) > 64 )
{ {
@@ -71,13 +72,18 @@ std::string FinalizeCCTx(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu
if ( vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0 ) if ( vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0 )
{ {
//fprintf(stderr,"vin.%d is normal %.8f\n",i,(double)utxovalues[i]/COIN); //fprintf(stderr,"vin.%d is normal %.8f\n",i,(double)utxovalues[i]/COIN);
normalinputs += utxovalues[i];
vinimask |= (1LL << i); vinimask |= (1LL << i);
} }
else else
{ {
mask |= (1LL << i);
} }
} 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());
} }
nmask = (1LL << n) - 1;
if ( (mask & nmask) != (CCmask & nmask) )
fprintf(stderr,"mask.%llx vs CCmask.%llx %llx %llx %llx\n",(long long)(mask & nmask),(long long)(CCmask & nmask),(long long)mask,(long long)CCmask,(long long)nmask);
if ( totalinputs >= totaloutputs+2*txfee ) if ( totalinputs >= totaloutputs+2*txfee )
{ {
change = totalinputs - (totaloutputs+txfee); change = totalinputs - (totaloutputs+txfee);
@@ -163,9 +169,41 @@ void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValu
} }
} }
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr)
{
int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector<std::pair<uint160, int> > addresses;
n = (int32_t)strlen(coinaddr);
addrstr.resize(n+1);
ptr = (char *)addrstr.data();
for (i=0; i<=n; i++)
ptr[i] = coinaddr[i];
CBitcoinAddress address(addrstr);
if ( address.GetIndexKey(hashBytes, type) == 0 )
return;
addresses.push_back(std::make_pair(hashBytes,type));
for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++)
{
if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 )
return;
}
}
uint64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout)
{
uint256 txid; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
if ( txid == utxotxid && utxovout == it->first.index )
return(it->second.satoshis);
}
return(0);
}
uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs) uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs)
{ {
int32_t n = 0; uint64_t nValue,totalinputs = 0; std::vector<COutput> vecOutputs; int32_t vout,j,n = 0; uint64_t nValue,totalinputs = 0; uint256 txid; std::vector<COutput> vecOutputs;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
@@ -175,7 +213,14 @@ uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,in
{ {
if ( out.fSpendable != 0 ) if ( out.fSpendable != 0 )
{ {
mtx.vin.push_back(CTxIn(out.tx->GetHash(),out.i,CScript())); txid = out.tx->GetHash();
vout = out.i;
for (j=0; j<mtx.vin.size(); j++)
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
break;
if ( j != mtx.vin.size() )
continue;
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = out.tx->vout[out.i].nValue; nValue = out.tx->vout[out.i].nValue;
totalinputs += nValue; totalinputs += nValue;
n++; n++;

View File

@@ -92,7 +92,19 @@ char *uint256_str(char *dest,uint256 txid)
int32_t i,j=0; int32_t i,j=0;
for (i=31; i>=0; i--) for (i=31; i>=0; i--)
sprintf(&dest[j++ * 2],"%02x",((uint8_t *)&txid)[i]); sprintf(&dest[j++ * 2],"%02x",((uint8_t *)&txid)[i]);
return(dest); dest[64] = 0;
return(dest);
}
char *pubkey33_str(char *dest,uint8_t *pubkey33)
{
int32_t i;
if ( pubkey33 != 0 )
{
for (i=0; i<33; i++)
sprintf(&dest[i * 2],"%02x",pubkey33[i]);
} else dest[0] = 0;
return(dest);
} }
uint256 Parseuint256(char *hexstr) uint256 Parseuint256(char *hexstr)
@@ -256,6 +268,31 @@ bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> param
return(false); return(false);
} }
int64_t CCduration(uint256 txid)
uint64_t AddFaucetInputs(CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs); {
CTransaction tx; uint256 hashBlock; uint32_t txtime=0; char str[65]; CBlockIndex *pindex; int64_t duration = 0;
if ( GetTransaction(txid,tx,hashBlock,false) == 0 )
{
fprintf(stderr,"CCduration cant find duration txid %s\n",uint256_str(str,txid));
return(0);
}
else if ( hashBlock == zeroid )
{
fprintf(stderr,"CCduration no hashBlock for txid %s\n",uint256_str(str,txid));
return(0);
}
else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txtime= pindex->nTime) == 0 )
{
fprintf(stderr,"CCduration no txtime %u %p for txid %s\n",txtime,pindex,uint256_str(str,txid));
return(0);
}
else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nTime < txtime )
{
fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid));
return(0);
}
duration = (pindex->nTime - txtime);
fprintf(stderr,"duration %d (%u - %u)\n",(int32_t)duration,(uint32_t)pindex->nTime,txtime);
return(duration);
}

View File

@@ -85,7 +85,7 @@
selloffer: selloffer:
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 change (if any)
vout.2: normal output for change (if any) vout.2: normal output for change (if any)
@@ -93,7 +93,7 @@
exchange: exchange:
vin.0: normal input vin.0: normal input
vin.1: valid CC output vin.1+: valid CC output
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 change (if any)
vout.2: normal output for change (if any) vout.2: normal output for change (if any)
@@ -132,17 +132,17 @@
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
{ {
static uint256 zero; static uint256 zero;
CTxDestination address; CTransaction vinTx,createTx; uint256 hashBlock,assetid,assetid2; int32_t i,starti,numvins,numvouts,preventCCvins,preventCCvouts; uint64_t amount,remaining_price,nValue,assetoshis,outputs,inputs,tmpprice,totalunits,ignore; std::vector<uint8_t> origpubkey,tmporigpubkey,ignorepubkey; uint8_t funcid; char destaddr[64],origaddr[64],CCaddr[64]; CTxDestination address; CTransaction vinTx,createTx; uint256 hashBlock,assetid,assetid2; int32_t i,starti,numvins,numvouts,preventCCvins,preventCCvouts; int64_t remaining_price,nValue,assetoshis,outputs,inputs,tmpprice,totalunits,ignore; std::vector<uint8_t> origpubkey,tmporigpubkey,ignorepubkey; uint8_t funcid; char destaddr[64],origaddr[64],CCaddr[64];
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
outputs = inputs = 0; outputs = inputs = 0;
preventCCvins = preventCCvouts = -1; preventCCvins = preventCCvouts = -1;
if ( (funcid= DecodeAssetOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,assetid2,amount,origpubkey)) == 0 ) if ( (funcid= DecodeAssetOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,assetid2,remaining_price,origpubkey)) == 0 )
return eval->Invalid("Invalid opreturn payload"); return eval->Invalid("Invalid opreturn payload");
fprintf(stderr,"AssetValidate (%c)\n",funcid); fprintf(stderr,"AssetValidate (%c)\n",funcid);
if ( eval->GetTxUnconfirmed(assetid,createTx,hashBlock) == 0 ) if ( funcid != 'o' && funcid != 'x' && eval->GetTxUnconfirmed(assetid,createTx,hashBlock) == 0 )
return eval->Invalid("cant find asset create txid"); return eval->Invalid("cant find asset create txid");
else if ( assetid2 != zero && eval->GetTxUnconfirmed(assetid2,createTx,hashBlock) == 0 ) else if ( funcid != 'o' && funcid != 'x' && assetid2 != zero && eval->GetTxUnconfirmed(assetid2,createTx,hashBlock) == 0 )
return eval->Invalid("cant find asset2 create txid"); return eval->Invalid("cant find asset2 create txid");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("illegal asset vin0"); return eval->Invalid("illegal asset vin0");
@@ -227,17 +227,24 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
return eval->Invalid("mismatched origpubkeys for fillbuy"); return eval->Invalid("mismatched origpubkeys for fillbuy");
else else
{ {
if ( ConstrainVout(tx.vout[1],0,0,0) == 0 ) 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 )
{
if ( ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 )
return eval->Invalid("vout2 doesnt go to origpubkey fillbuy");
else if ( inputs != tx.vout[2].nValue+tx.vout[3].nValue )
return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy");
}
else if ( ConstrainVout(tx.vout[2],1,CCaddr,inputs) == 0 )
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"); return eval->Invalid("vout1 is CC for fillbuy");
else if ( ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 ) else if ( ValidateBidRemainder(remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false )
return eval->Invalid("vout2 is normal for fillbuy");
else if ( ValidateAssetRemainder(0,remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false )
return eval->Invalid("mismatched remainder for fillbuy"); return eval->Invalid("mismatched remainder for fillbuy");
else if ( remaining_price != 0 ) else if ( remaining_price != 0 )
{ {
if ( remaining_price < 10000 ) if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 )
return eval->Invalid("dust vout0 to AssetsCCaddr for fillbuy");
else if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 )
return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy"); return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy");
} }
} }
@@ -247,15 +254,16 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
case 's': // selloffer case 's': // selloffer
case 'e': // exchange case 'e': // exchange
//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: normal output for change (if any) //vout.1: 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]
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");
else if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 ) else if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,inputs) == 0 )
return eval->Invalid("mismatched vout0 AssetsCCaddr for selloffer"); return eval->Invalid("mismatched vout0 AssetsCCaddr for selloffer");
//fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price);
preventCCvouts = 1; preventCCvouts = 1;
break; break;
@@ -274,49 +282,84 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
break; break;
case 'S': // fillsell case 'S': // fillsell
case 'E': // fillexchange
//vin.0: normal input //vin.0: normal input
//vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0] //vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
//'S'.vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue //'S'.vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue
//'E'.vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
//vout.0: remaining assetoshis -> unspendable //vout.0: remaining assetoshis -> unspendable
//vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any //vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
//'S'.vout.2: vin.2 value to original pubkey [origpubkey] //'S'.vout.2: vin.2 value to original pubkey [origpubkey]
//'E'.vout.2: vin.2 assetoshis2 to original pubkey [origpubkey]
//vout.3: normal output for change (if any) //vout.3: normal output for change (if any)
//'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] //'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey]
//'E'.vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
if ( funcid == 'E' )
{
if ( AssetExactAmounts(cp,inputs,1,outputs,eval,tx,assetid2) == false )
eval->Invalid("asset2 inputs != outputs");
}
if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 )
return(false); return(false);
else if ( numvouts < 3 ) else if ( numvouts < 3 )
return eval->Invalid("not enough vouts for fill"); return eval->Invalid("not enough vouts for fillask");
else if ( tmporigpubkey != origpubkey ) else if ( tmporigpubkey != origpubkey )
return eval->Invalid("mismatched origpubkeys for fill"); return eval->Invalid("mismatched origpubkeys for fillask");
else else
{ {
if ( ValidateAssetRemainder(1,remaining_price,tx.vout[0].nValue,assetoshis,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false ) if ( assetoshis != tx.vout[0].nValue+tx.vout[1].nValue )
return eval->Invalid("mismatched remainder for fill"); return eval->Invalid("locked value doesnt match vout0+1 fillask");
if ( ValidateAskRemainder(remaining_price,tx.vout[0].nValue,assetoshis,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false )
return eval->Invalid("mismatched remainder for fillask");
else if ( ConstrainVout(tx.vout[1],1,0,0) == 0 ) else if ( ConstrainVout(tx.vout[1],1,0,0) == 0 )
return eval->Invalid("normal vout1 for fillask"); return eval->Invalid("normal vout1 for fillask");
else if ( funcid == 'E' && ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 ) else if ( ConstrainVout(tx.vout[2],0,origaddr,0) == 0 )
return eval->Invalid("normal vout2 for fillask"); return eval->Invalid("normal vout1 for fillask");
else if ( funcid == 'S' && ConstrainVout(tx.vout[2],0,origaddr,0) == 0 )
return eval->Invalid("CC vout2 for fillask");
else if ( remaining_price != 0 ) else if ( remaining_price != 0 )
{ {
if ( remaining_price < 10000 ) if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 )
return eval->Invalid("dust vout0 to AssetsCCaddr for fill");
else if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 )
return eval->Invalid("mismatched vout0 AssetsCCaddr for fill"); return eval->Invalid("mismatched vout0 AssetsCCaddr for fill");
} }
} }
fprintf(stderr,"fill validated\n"); fprintf(stderr,"fill validated\n");
break; break;
case 'E': // fillexchange
//vin.0: normal input
//vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
//vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
//vout.0: remaining assetoshis -> unspendable
//vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
//vout.2: vin.2+ assetoshis2 to original pubkey [origpubkey]
//vout.3: CC output for asset2 change (if any)
//vout.3/4: normal output for change (if any)
//vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
if ( AssetExactAmounts(cp,inputs,1,outputs,eval,tx,assetid2) == false )
eval->Invalid("asset2 inputs != outputs");
if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 )
return(false);
else if ( numvouts < 3 )
return eval->Invalid("not enough vouts for fillex");
else if ( tmporigpubkey != origpubkey )
return eval->Invalid("mismatched origpubkeys for fillex");
else
{
if ( assetoshis != tx.vout[0].nValue+tx.vout[1].nValue )
return eval->Invalid("locked value doesnt match vout0+1 fillex");
else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
if ( ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 )
return eval->Invalid("vout2 doesnt go to origpubkey fillex");
else if ( inputs != tx.vout[2].nValue+tx.vout[3].nValue )
return eval->Invalid("asset inputs doesnt match vout2+3 fillex");
}
else if ( ConstrainVout(tx.vout[2],1,CCaddr,inputs) == 0 )
return eval->Invalid("vout2 doesnt match inputs fillex");
else if ( ConstrainVout(tx.vout[1],0,0,0) == 0 )
return eval->Invalid("vout1 is CC for fillex");
fprintf(stderr,"assets vout0 %llu, vin1 %llu, vout2 %llu -> orig, vout1 %llu, total %llu\n",(long long)tx.vout[0].nValue,(long long)assetoshis,(long long)tx.vout[2].nValue,(long long)tx.vout[1].nValue,(long long)totalunits);
if ( ValidateSwapRemainder(remaining_price,tx.vout[0].nValue,assetoshis,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false )
return eval->Invalid("mismatched remainder for fillex");
else if ( ConstrainVout(tx.vout[1],1,0,0) == 0 )
return eval->Invalid("normal vout1 for fillex");
else if ( remaining_price != 0 )
{
if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 )
return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex");
}
}
fprintf(stderr,"fill validated\n");
break;
} }
return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts));
} }

View File

@@ -126,6 +126,7 @@ uint64_t AddAuctionInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
// prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsAuctionvout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (nValue= IsAuctionvout(cp,vintx,(int32_t)it->first.index)) > 0 )
@@ -158,7 +159,7 @@ std::string AuctionBid(uint64_t txfee,uint256 itemhash,uint64_t amount)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk)); mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find Auction inputs\n"); } else fprintf(stderr,"cant find Auction inputs\n");
return(0); return(0);
} }
@@ -178,7 +179,7 @@ std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk)); mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,CCchange,Auctionpk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find Auction inputs\n"); } else fprintf(stderr,"cant find Auction inputs\n");
return(0); return(0);
} }
@@ -194,7 +195,7 @@ std::string AuctionPost(uint64_t txfee,uint256 itemhash,uint64_t minbid,char *ti
if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,funds,Auctionpk)); mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,funds,Auctionpk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
return(0); return(0);
} }

View File

@@ -126,6 +126,7 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
// prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsDicevout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (nValue= IsDicevout(cp,vintx,(int32_t)it->first.index)) > 0 )
@@ -158,7 +159,7 @@ std::string DiceBet(uint64_t txfee,uint64_t amount,uint64_t odds)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_DICE,CCchange,dicepk)); mtx.vout.push_back(MakeCC1vout(EVAL_DICE,CCchange,dicepk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find dice inputs\n"); } else fprintf(stderr,"cant find dice inputs\n");
return(0); return(0);
} }
@@ -174,7 +175,7 @@ std::string DiceFund(uint64_t txfee,uint64_t funds)
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_DICE,funds,dicepk)); mtx.vout.push_back(MakeCC1vout(EVAL_DICE,funds,dicepk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
return(0); return(0);
} }

View File

@@ -133,6 +133,7 @@ uint64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
// prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsFaucetvout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (nValue= IsFaucetvout(cp,vintx,(int32_t)it->first.index)) > 0 )
@@ -165,7 +166,7 @@ std::string FaucetGet(uint64_t txfee)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,CCchange,faucetpk)); mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,CCchange,faucetpk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find faucet inputs\n"); } else fprintf(stderr,"cant find faucet inputs\n");
return(0); return(0);
} }
@@ -181,7 +182,7 @@ std::string FaucetFund(uint64_t txfee,uint64_t funds)
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,funds,faucetpk)); mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,funds,faucetpk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
return(0); return(0);
} }

View File

@@ -54,6 +54,9 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params, const CTransaction &imp
if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol()) if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol())
return Invalid("importcoin-wrong-chain"); return Invalid("importcoin-wrong-chain");
if (targetCcid <= 1000)
return Invalid("chain-not-fungible");
// check burn amount // check burn amount
{ {
uint64_t burnAmount = burnTx.vout[0].nValue; uint64_t burnAmount = burnTx.vout[0].nValue;

View File

@@ -126,6 +126,7 @@ uint64_t AddLottoInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
// prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsLottovout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (nValue= IsLottovout(cp,vintx,(int32_t)it->first.index)) > 0 )
@@ -158,7 +159,7 @@ std::string LottoTicket(uint64_t txfee,uint64_t numtickets)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,CCchange,Lottopk)); mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,CCchange,Lottopk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find Lotto inputs\n"); } else fprintf(stderr,"cant find Lotto inputs\n");
return(0); return(0);
} }
@@ -174,7 +175,7 @@ std::string LottoWinner(uint64_t txfee)
if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,winnings,Lottopk)); mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,winnings,Lottopk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
return(0); return(0);
} }

View File

@@ -126,6 +126,7 @@ uint64_t AddPonziInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
// prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsPonzivout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (nValue= IsPonzivout(cp,vintx,(int32_t)it->first.index)) > 0 )
@@ -158,7 +159,7 @@ std::string PonziBuy(uint64_t txfee,uint64_t amount)
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_PONZI,CCchange,ponzipk)); mtx.vout.push_back(MakeCC1vout(EVAL_PONZI,CCchange,ponzipk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find ponzi inputs\n"); } else fprintf(stderr,"cant find ponzi inputs\n");
return(0); return(0);
} }
@@ -174,7 +175,7 @@ std::string PonziClaim(uint64_t txfee)
if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_PONZI,funds,ponzipk)); mtx.vout.push_back(MakeCC1vout(EVAL_PONZI,funds,ponzipk));
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
return(0); return(0);
} }

View File

@@ -35,18 +35,106 @@
Locks wont have any CC vins, but will send to the RewardsCCaddress, with the plan stringbits in the opreturn. vout1 will have the unlock address and no other destination is valid. Locks wont have any CC vins, but will send to the RewardsCCaddress, with the plan stringbits in the opreturn. vout1 will have the unlock address and no other destination is valid.
Unlock does a CC spend to the vout1 address Unlock does a CC spend to the vout1 address
createfunding
vins.*: normal inputs
vout.0: CC vout for funding
vout.1: normal marker vout for easy searching
vout.2: normal change
vout.n-1: opreturn 'F' sbits APR minseconds maxseconds mindeposit
addfunding
vins.*: normal inputs
vout.0: CC vout for funding
vout.1: normal change
vout.n-1: opreturn 'A' sbits fundingtxid
lock
vins.*: normal inputs
vout.0: CC vout for locked funds
vout.1: normal output to unlock address
vout.2: change
vout.n-1: opreturn 'L' sbits fundingtxid
unlock
vin.0: locked funds CC vout.0 from lock
vin.1+: funding CC vout.0 from 'F' and 'A' and 'U'
vout.0: funding CC change
vout.1: normal output to unlock address
vout.n-1: opreturn 'U' sbits fundingtxid
*/ */
uint64_t RewardsCalc(uint64_t claim,uint256 txid) // min/max time, mindeposit and rate uint64_t RewardsCalc(uint64_t amount,uint256 txid,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit)
{ {
uint64_t reward = 0; uint64_t duration,reward = 0;
// get start time, get current time if ( (duration= CCduration(txid)) < minseconds )
// if elapsed < mintime -> return 0 {
// if elapsed > maxtime, elapsed = maxtime return(0);
// calc reward //duration = (uint32_t)time(NULL) - (1532713903 - 3600 * 24);
} else if ( duration > maxseconds )
maxseconds = duration;
reward = (((amount * APR) / COIN) * duration) / (365*24*3600LL * 100);
fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN);
return(reward); return(reward);
} }
CScript EncodeRewardsFundingOpRet(uint8_t funcid,uint64_t sbits,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit)
{
CScript opret; uint8_t evalcode = EVAL_REWARDS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'F' << sbits << APR << minseconds << maxseconds << mindeposit);
return(opret);
}
uint8_t DecodeRewardsFundingOpRet(const CScript &scriptPubKey,uint64_t &sbits,uint64_t &APR,uint64_t &minseconds,uint64_t &maxseconds,uint64_t &mindeposit)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> APR; ss >> minseconds; ss >> maxseconds; ss >> mindeposit) != 0 )
{
if ( e == EVAL_REWARDS && f == 'F' )
return(f);
}
return(0);
}
CScript EncodeRewardsOpRet(uint8_t funcid,uint64_t sbits,uint256 fundingtxid)
{
CScript opret; uint8_t evalcode = EVAL_REWARDS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << sbits << fundingtxid);
return(opret);
}
uint8_t DecodeRewardsOpRet(uint256 txid,const CScript &scriptPubKey,uint64_t &sbits,uint256 &fundingtxid)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid; uint64_t APR,minseconds,maxseconds,mindeposit;
GetOpReturnData(scriptPubKey, vopret);
if ( vopret.size() > 2 )
{
script = (uint8_t *)vopret.data();
if ( script[0] == EVAL_REWARDS )
{
if ( script[1] == 'F' )
{
if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> APR; ss >> minseconds; ss >> maxseconds; ss >> mindeposit) != 0 )
{
fundingtxid = txid;
return('F');
} else fprintf(stderr,"unmarshal error for F\n");
}
else if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> fundingtxid) != 0 )
{
if ( e == EVAL_REWARDS && (f == 'L' || f == 'U' || f == 'A') )
return(f);
else fprintf(stderr,"mismatched e.%02x f.(%c)\n",e,f);
}
} else fprintf(stderr,"script[0] %02x != EVAL_REWARDS\n",script[0]);
} else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size());
return(0);
}
uint64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) uint64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
{ {
char destaddr[64]; char destaddr[64];
@@ -58,10 +146,10 @@ uint64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t
return(0); return(0);
} }
bool RewardsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx,uint64_t txfee)
{ {
static uint256 zerohash; static uint256 zerohash;
CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis;
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
for (i=0; i<numvins; i++) for (i=0; i<numvins; i++)
@@ -85,17 +173,17 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransactio
if ( (assetoshis= IsRewardsvout(cp,tx,i)) != 0 ) if ( (assetoshis= IsRewardsvout(cp,tx,i)) != 0 )
outputs += assetoshis; outputs += assetoshis;
} }
if ( inputs != outputs+COIN+txfee ) if ( inputs != outputs+txfee )
{ {
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs); fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("mismatched inputs != outputs + COIN + txfee"); return eval->Invalid("mismatched inputs != outputs + txfee");
} }
else return(true); else return(true);
} }
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
{ {
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint256 txid,fundingtxid,hashBlock; uint64_t sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1; preventCCvins = preventCCvouts = -1;
@@ -103,140 +191,361 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
return eval->Invalid("no vouts"); return eval->Invalid("no vouts");
else else
{ {
// follow rules txid = tx.GetHash();
for (i=0; i<numvins; i++) if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 )
{ {
if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) if ( eval->GetTxUnconfirmed(fundingtxid,fundingTx,hashBlock) == 0 )
return eval->Invalid("illegal normal vini"); return eval->Invalid("cant find fundingtxid");
} else if ( fundingTx.vout.size() > 0 && DecodeRewardsFundingOpRet(fundingTx.vout[fundingTx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) != 'F' )
if ( RewardsExactAmounts(cp,eval,tx,1,10000) == false ) return eval->Invalid("fundingTx not valid");
return false; switch ( funcid )
else
{
preventCCvouts = 1;
if ( IsRewardsvout(cp,tx,0) != 0 )
{ {
preventCCvouts++; case 'F':
i = 1; //vins.*: normal inputs
} else i = 0; //vout.0: CC vout for funding
if ( tx.vout[i].nValue != COIN ) //vout.1: normal marker vout for easy searching
return eval->Invalid("invalid rewards output"); //vout.2: normal change
return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); //vout.n-1: opreturn 'F' sbits APR minseconds maxseconds mindeposit
return eval->Invalid("unexpected RewardsValidate for createfunding");
break;
case 'A':
//vins.*: normal inputs
//vout.0: CC vout for funding
//vout.1: normal change
//vout.n-1: opreturn 'A' sbits fundingtxid
return eval->Invalid("unexpected RewardsValidate for addfunding");
break;
case 'L':
//vins.*: normal inputs
//vout.0: CC vout for locked funds
//vout.1: normal output to unlock address
//vout.2: change
//vout.n-1: opreturn 'L' sbits fundingtxid
return eval->Invalid("unexpected RewardsValidate for lock");
break;
case 'U':
//vin.0: locked funds CC vout.0 from lock
//vin.1+: funding CC vout.0 from 'F' and 'A' and 'U'
//vout.0: funding CC change
//vout.1: normal output to unlock address
//vout.n-1: opreturn 'U' sbits fundingtxid
for (i=0; i<numvins; i++)
{
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
return eval->Invalid("unexpected normal vin for unlock");
}
if ( RewardsExactAmounts(cp,eval,tx,txfee+tx.vout[1].nValue) == 0 )
return false;
else if ( eval->GetTxUnconfirmed(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("always should find vin.0, but didnt");
else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
return eval->Invalid("lock tx vout.0 is normal output");
else if ( tx.vout.size() < 3 )
return eval->Invalid("unlock tx not enough vouts");
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
return eval->Invalid("unlock tx vout.0 is normal output");
else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("unlock tx vout.1 is CC output");
else if ( tx.vout[1].scriptPubKey != vinTx.vout[1].scriptPubKey )
return eval->Invalid("unlock tx vout.1 mismatched scriptPubKey");
amount = vinTx.vout[0].nValue;
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
if ( tx.vout[1].nValue > amount+reward )
return eval->Invalid("unlock tx vout.1 isnt amount+reward");
preventCCvouts = 1;
break;
}
} }
return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts));
} }
return(true); return(true);
} }
uint64_t AddRewardsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs) // 'L' vs 'F' and 'A'
uint64_t AddRewardsInputs(CScript &scriptPubKey,int32_t fundsflag,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs)
{ {
char coinaddr[64]; uint64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t n = 0; char coinaddr[64],str[65]; uint64_t sbits,APR,minseconds,maxseconds,mindeposit,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t j,vout,n = 0; uint8_t funcid;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk); GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr); SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) vout = (int32_t)it->first.index;
fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
for (j=0; j<mtx.vin.size(); j++)
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
break;
if ( j != mtx.vin.size() )
continue;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
{ {
if ( (nValue= IsRewardsvout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) != 0 )
{ {
fprintf(stderr,"fundsflag.%d (%c) %.8f %.8f\n",fundsflag,funcid,(double)tx.vout[vout].nValue/COIN,(double)it->second.satoshis/COIN);
if ( fundsflag != 0 && funcid != 'F' && funcid != 'A' && funcid != 'U' )
continue;
else if ( fundsflag == 0 && (funcid != 'L' || tx.vout.size() < 4) )
continue;
if ( total != 0 && maxinputs != 0 ) if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,(int32_t)it->first.index,CScript())); {
if ( fundsflag == 0 )
scriptPubKey = tx.vout[1].scriptPubKey;
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
}
totalinputs += it->second.satoshis; totalinputs += it->second.satoshis;
n++; n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break; break;
} } else fprintf(stderr,"null funcid\n");
} }
} }
return(totalinputs); return(totalinputs);
} }
uint64_t RewardsPlanFunds(uint64_t &refsbits,struct CCcontract_info *cp,CPubKey &pk,char *planstr) uint64_t RewardsPlanFunds(uint64_t refsbits,struct CCcontract_info *cp,CPubKey pk,uint256 reffundingtxid)
{ {
char coinaddr[64]; uint64_t sbits,nValue,totalinputs = 0; uint256 hashBlock; CTransaction vintx; char coinaddr[64]; uint64_t sbits,APR,minseconds,maxseconds,mindeposit,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t vout; uint8_t funcid;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
if ( planstr == 0 || planstr[0] == 0 || strlen(planstr) > 8 )
return(0);
refsbits = stringbits(planstr);
GetCCaddress(cp,coinaddr,pk); GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr); SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
if ( GetTransaction(it->first.txhash,vintx,hashBlock,false) != 0 ) txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
{ {
if ( (nValue= IsRewardsvout(cp,vintx,(int32_t)it->first.index)) > 0 ) if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) != 0 )
{ {
totalinputs += nValue; if ( (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid )
} {
if ( refsbits == sbits && (nValue= IsRewardsvout(cp,tx,vout)) > 0 )
totalinputs += nValue;
else fprintf(stderr,"refsbits.%llx sbits.%llx nValue %.8f\n",(long long)refsbits,(long long)sbits,(double)nValue/COIN);
} else fprintf(stderr,"else case\n");
} else fprintf(stderr,"funcid.%d %c skipped %.8f\n",funcid,funcid,(double)tx.vout[vout].nValue/COIN);
} }
} }
return(totalinputs); return(totalinputs);
} }
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 txid) bool RewardsPlanExists(struct CCcontract_info *cp,uint64_t refsbits,CPubKey rewardspk,uint64_t &APR,uint64_t &minseconds,uint64_t &maxseconds,uint64_t &mindeposit)
{ {
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t reward,amount,inputs,CCchange=0; struct CCcontract_info *cp,C; char CCaddr[64]; uint64_t sbits; uint256 txid,hashBlock; CTransaction tx;
cp = CCinit(&C,EVAL_REWARDS); std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
if ( txfee == 0 ) GetCCaddress(cp,CCaddr,rewardspk);
txfee = 10000; SetCCtxids(txids,CCaddr);
rewardspk = GetUnspendable(cp,0); for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=txids.begin(); it!=txids.end(); it++)
mypk = pubkey2pk(Mypubkey());
if ( (amount= AddRewardsInputs(cp,mtx,mypk,(1LL << 30),1)) > 0 && (reward= RewardsCalc(amount,mtx.vin[0].prevout.hash)) > txfee )
{ {
if ( (inputs= AddRewardsInputs(cp,mtx,mypk,reward+amount+txfee,30)) > 0 ) //int height = it->first.blockHeight;
txid = it->first.txhash;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 )
{ {
if ( inputs > (amount + reward + 2*txfee) ) if ( DecodeRewardsFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) == 'F' )
CCchange = (inputs - amount - reward - txfee); {
if ( CCchange != 0 ) if ( sbits == refsbits )
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk)); return(true);
mtx.vout.push_back(CTxOut(amount+reward,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); }
opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'U');
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret));
} }
} else fprintf(stderr,"cant find rewards inputs\n"); }
return(0); return(false);
} }
std::string RewardsFund(uint64_t txfee,char *planstr,uint64_t funds,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit) UniValue RewardsInfo(uint256 rewardsid)
{ {
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits; struct CCcontract_info *cp,C; UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; uint64_t APR,minseconds,maxseconds,mindeposit,sbits; char str[67],numstr[65];
if ( GetTransaction(rewardsid,vintx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find fundingtxid\n");
result.push_back(Pair("error","cant find fundingtxid"));
return(result);
}
if ( vintx.vout.size() > 0 && DecodeRewardsFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) == 0 )
{
fprintf(stderr,"fundingtxid isnt rewards creation txid\n");
result.push_back(Pair("error","fundingtxid isnt rewards creation txid"));
return(result);
}
result.push_back(Pair("result","success"));
result.push_back(Pair("fundingtxid",uint256_str(str,rewardsid)));
unstringbits(str,sbits);
result.push_back(Pair("name",str));
result.push_back(Pair("sbits",sbits));
sprintf(numstr,"%.8f",(double)APR/COIN);
result.push_back(Pair("APR",numstr));
result.push_back(Pair("minseconds",minseconds));
result.push_back(Pair("maxseconds",maxseconds));
sprintf(numstr,"%.8f",(double)mindeposit/COIN);
result.push_back(Pair("mindeposit",numstr));
sprintf(numstr,"%.8f",(double)vintx.vout[0].nValue/COIN);
result.push_back(Pair("funding",numstr));
return(result);
}
UniValue RewardsList()
{
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction vintx; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; char str[65];
cp = CCinit(&C,EVAL_REWARDS);
SetCCtxids(addressIndex,cp->normaladdr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
txid = it->first.txhash;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{
if ( vintx.vout.size() > 0 && DecodeRewardsFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) != 0 )
{
result.push_back(uint256_str(str,txid));
}
}
}
return(result);
}
std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit)
{
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
if ( funds < 0 || mindeposit < 0 || minseconds < 0 || maxseconds < 0 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
}
cp = CCinit(&C,EVAL_REWARDS); cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
rewardspk = GetUnspendable(cp,0); rewardspk = GetUnspendable(cp,0);
sbits = stringbits(planstr);
if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) != 0 )
{
fprintf(stderr,"Rewards plan (%s) already exists\n",planstr);
return(0);
}
if ( AddNormalinputs(mtx,mypk,funds+2*txfee,64) > 0 ) if ( AddNormalinputs(mtx,mypk,funds+2*txfee,64) > 0 )
{ {
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,rewardspk)); mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,rewardspk));
mtx.vout.push_back(CTxOut(APR,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(minseconds,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsFundingOpRet('F',sbits,APR,minseconds,maxseconds,mindeposit)));
mtx.vout.push_back(CTxOut(maxseconds,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(mindeposit,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG));
opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'F' << sbits);
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret));
} }
fprintf(stderr,"cant find enough inputs\n");
return(0); return(0);
} }
std::string RewardsLock(uint64_t txfee,char *planstr,uint64_t amount) std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount)
{ {
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,funding; struct CCcontract_info *cp,C; CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
if ( amount < 0 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
}
cp = CCinit(&C,EVAL_REWARDS); cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
rewardspk = GetUnspendable(cp,0); rewardspk = GetUnspendable(cp,0);
if ( (funding= RewardsPlanFunds(sbits,cp,rewardspk,planstr)) >= amount ) sbits = stringbits(planstr);
if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) == 0 )
{ {
if ( txfee == 0 ) fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr);
txfee = 10000; return(0);
if ( AddNormalinputs(mtx,mypk,amount+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,rewardspk));
opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'L' << sbits);
return(FinalizeCCTx(cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"cant find rewards inputs\n");
} }
sbits = stringbits(planstr);
if ( AddNormalinputs(mtx,mypk,amount+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,rewardspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('A',sbits,fundingtxid)));
} else fprintf(stderr,"cant find enough inputs\n");
fprintf(stderr,"cant find fundingtxid\n");
return(0); return(0);
} }
std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t deposit)
{
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
if ( deposit < 0 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
}
cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
rewardspk = GetUnspendable(cp,0);
sbits = stringbits(planstr);
if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 )
{
fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr);
return(0);
}
if ( deposit < mindeposit )
{
fprintf(stderr,"Rewards plan %s deposit %.8f < mindeposit %.8f\n",planstr,(double)deposit/COIN,(double)mindeposit/COIN);
return(0);
}
if ( (funding= RewardsPlanFunds(sbits,cp,rewardspk,fundingtxid)) >= deposit ) // arbitrary cmpval
{
if ( AddNormalinputs(mtx,mypk,deposit+2*txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,deposit,rewardspk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('L',sbits,fundingtxid)));
} else fprintf(stderr,"cant find enough inputs %.8f note enough for %.8f\n",(double)funding/COIN,(double)deposit/COIN);
}
fprintf(stderr,"cant find rewards inputs\n");
return(0);
}
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid)
{
CMutableTransaction mtx; CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript opret,scriptPubKey,ignore; uint256 hashBlock; uint64_t funding,sbits,reward=0,amount=0,inputs,CCchange=0,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 )
txfee = 10000;
rewardspk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey());
sbits = stringbits(planstr);
if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 )
{
fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr);
return(0);
}
// need to deal with finding the right utxos
if ( locktxid == zeroid )
amount = AddRewardsInputs(scriptPubKey,0,cp,mtx,rewardspk,(1LL << 30),1);
else
{
GetCCaddress(cp,coinaddr,rewardspk);
if ( (amount= CCutxovalue(coinaddr,locktxid,0)) == 0 )
{
fprintf(stderr,"%s locktxid/v0 is spent\n",coinaddr);
return(0);
}
if ( GetTransaction(locktxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
scriptPubKey = tx.vout[1].scriptPubKey;
mtx.vin.push_back(CTxIn(locktxid,0,CScript()));
}
else
{
fprintf(stderr,"%s no normal vout.1 in locktxid\n",coinaddr);
return(0);
}
}
if ( amount > 0 && (reward= RewardsCalc(amount,mtx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit)) > txfee && scriptPubKey.size() > 0 )
{
if ( (inputs= AddRewardsInputs(ignore,1,cp,mtx,rewardspk,reward+txfee,30)) > 0 )
{
if ( inputs >= (reward + 2*txfee) )
CCchange = (inputs - (reward + txfee));
fprintf(stderr,"inputs %.8f CCchange %.8f amount %.8f reward %.8f\n",(double)inputs/COIN,(double)CCchange/COIN,(double)amount/COIN,(double)reward/COIN);
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk));
mtx.vout.push_back(CTxOut(amount+reward,scriptPubKey));
return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
}
fprintf(stderr,"cant find enough rewards inputs\n");
}
fprintf(stderr,"amount %.8f -> reward %.8f\n",(double)amount/COIN,(double)reward/COIN);
return(0);
}

View File

@@ -42,7 +42,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
* > scan backwards > * > scan backwards >
*/ */
if (targetCCid <= 1) if (targetCCid < 2)
return uint256(); return uint256();
if (kmdHeight < 0 || kmdHeight > chainActive.Height()) if (kmdHeight < 0 || kmdHeight > chainActive.Height())

View File

@@ -1293,6 +1293,7 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc) arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
{ {
int32_t oldflag = 0;
CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val;
*percPoSp = percPoS = 0; *percPoSp = percPoS = 0;
if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
@@ -1357,9 +1358,13 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
if ( ave > target ) if ( ave > target )
ave = target; ave = target;
} else ave = easydiff; //else return(target); } else ave = easydiff; //else return(target);
if ( percPoS == 0 )
percPoS = 1;
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{ {
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); if ( oldflag != 0 )
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc);
else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS);
if ( ASSETCHAINS_STAKED < 100 ) if ( ASSETCHAINS_STAKED < 100 )
{ {
for (i=31; i>=24; i--) for (i=31; i>=24; i--)
@@ -1375,9 +1380,12 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
} }
else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
{ {
bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); if ( oldflag != 0 )
//bnTarget = (bnTarget * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc); {
bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
//bnTarget = (bnTarget * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc);
bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS);
} else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS);
if ( bnTarget > easydiff ) if ( bnTarget > easydiff )
bnTarget = easydiff; bnTarget = easydiff;
else if ( bnTarget < ave ) // overflow else if ( bnTarget < ave ) // overflow

View File

@@ -46,7 +46,7 @@ struct komodo_state KOMODO_STATES[34];
int COINBASE_MATURITY = _COINBASE_MATURITY;//100; int COINBASE_MATURITY = _COINBASE_MATURITY;//100;
int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND; int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND;
int32_t KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE = 1; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE = 1;
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY;
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE;

View File

@@ -1605,8 +1605,8 @@ void komodo_args(char *argv0)
if ( (baseid= komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) if ( (baseid= komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 )
MAX_MONEY = komodo_maxallowed(baseid); MAX_MONEY = komodo_maxallowed(baseid);
else if ( ASSETCHAINS_REWARD == 0 ) else if ( ASSETCHAINS_REWARD == 0 )
MAX_MONEY = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN; MAX_MONEY = (ASSETCHAINS_SUPPLY+100) * SATOSHIDEN;
else MAX_MONEY = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + ASSETCHAINS_REWARD * (ASSETCHAINS_ENDSUBSIDY==0 ? 10000000 : ASSETCHAINS_ENDSUBSIDY); else MAX_MONEY = (ASSETCHAINS_SUPPLY+100) * SATOSHIDEN + ASSETCHAINS_REWARD * (ASSETCHAINS_ENDSUBSIDY==0 ? 10000000 : ASSETCHAINS_ENDSUBSIDY);
MAX_MONEY += (MAX_MONEY * ASSETCHAINS_COMMISSION) / SATOSHIDEN; MAX_MONEY += (MAX_MONEY * ASSETCHAINS_COMMISSION) / SATOSHIDEN;
//printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN);
ASSETCHAINS_P2PPORT = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); ASSETCHAINS_P2PPORT = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen);

View File

@@ -56,7 +56,7 @@ using namespace std;
CCriticalSection cs_main; CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33]; extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN; extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC;
int32_t KOMODO_NEWBLOCKS; int32_t KOMODO_NEWBLOCKS;
int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
void komodo_broadcast(CBlock *pblock,int32_t limit); void komodo_broadcast(CBlock *pblock,int32_t limit);
@@ -588,7 +588,7 @@ CBlockTreeDB *pblocktree = NULL;
#define KOMODO_ZCASH #define KOMODO_ZCASH
#include "komodo.h" #include "komodo.h"
UniValue komodo_snapshot() UniValue komodo_snapshot(int top)
{ {
LOCK(cs_main); LOCK(cs_main);
int64_t total = -1; int64_t total = -1;
@@ -596,7 +596,7 @@ UniValue komodo_snapshot()
if (fAddressIndex) { if (fAddressIndex) {
if ( pblocktree != 0 ) { if ( pblocktree != 0 ) {
result = pblocktree->Snapshot(); result = pblocktree->Snapshot(top);
} else { } else {
fprintf(stderr,"null pblocktree start with -addressindex=true\n"); fprintf(stderr,"null pblocktree start with -addressindex=true\n");
} }
@@ -2825,6 +2825,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CBlockUndo blockundo; CBlockUndo blockundo;
if ( ASSETCHAINS_CC != 0 )
{
if ( scriptcheckqueue.IsIdle() == 0 )
{
fprintf(stderr,"scriptcheckqueue isnt idle\n");
sleep(1);
}
}
CCheckQueueControl<CScriptCheck> control(fExpensiveChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); CCheckQueueControl<CScriptCheck> control(fExpensiveChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
int64_t nTimeStart = GetTimeMicros(); int64_t nTimeStart = GetTimeMicros();
@@ -3471,7 +3479,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
if ( ASSETCHAINS_SYMBOL[0] == 0 ) if ( KOMODO_LONGESTCHAIN != 0 && pindexNew->nHeight >= KOMODO_LONGESTCHAIN )
KOMODO_INSYNC = 1;
else KOMODO_INSYNC = 0;
//fprintf(stderr,"connect.%d insync.%d\n",(int32_t)pindexNew->nHeight,KOMODO_INSYNC);
if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_INSYNC != 0 )
komodo_broadcast(pblock,8); komodo_broadcast(pblock,8);
return true; return true;
} }

View File

@@ -106,7 +106,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
#include "komodo_defs.h" #include "komodo_defs.h"
extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; extern int32_t KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE;
extern uint64_t ASSETCHAINS_REWARD,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED; extern uint64_t ASSETCHAINS_REWARD,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
@@ -699,7 +699,7 @@ int32_t komodo_baseid(char *origbase);
int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
extern int32_t KOMODO_LASTMINED; extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
int32_t roundrobin_delay; int32_t roundrobin_delay;
arith_uint256 HASHTarget,HASHTarget_POW; arith_uint256 HASHTarget,HASHTarget_POW;
@@ -725,7 +725,7 @@ void static BitcoinMiner()
unsigned int n = chainparams.EquihashN(); unsigned int n = chainparams.EquihashN();
unsigned int k = chainparams.EquihashK(); unsigned int k = chainparams.EquihashK();
uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1;
while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.LastTip()->nHeight != 235300 && while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) )
{ {
sleep(1); sleep(1);
if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
@@ -911,13 +911,13 @@ void static BitcoinMiner()
} }
while (true) while (true)
{ {
/*if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT ) // skips when it shouldnt if ( KOMODO_INSYNC == 0 )
{ {
fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height);
sleep(10); if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN )
break; KOMODO_INSYNC = 1;
}*/ sleep(3);
//fprintf(stderr,"top of while\n"); }
// Hash state // Hash state
KOMODO_CHOSEN_ONE = 0; KOMODO_CHOSEN_ONE = 0;
crypto_generichash_blake2b_state state; crypto_generichash_blake2b_state state;

View File

@@ -153,8 +153,8 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
"import transaction.\n" "import transaction.\n"
); );
if (ASSETCHAINS_CC < 2) if (ASSETCHAINS_CC <= 1000)
throw runtime_error("-ac_cc < 2"); throw runtime_error("-ac_cc <= 1000");
if (ASSETCHAINS_SYMBOL[0] == 0) if (ASSETCHAINS_SYMBOL[0] == 0)
throw runtime_error("Must be called on assetchain"); throw runtime_error("Must be called on assetchain");
@@ -208,8 +208,8 @@ UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp)
throw runtime_error("migrate_createimporttransaction burnTx payouts\n\n" throw runtime_error("migrate_createimporttransaction burnTx payouts\n\n"
"Create an importTx given a burnTx and the corresponding payouts, hex encoded"); "Create an importTx given a burnTx and the corresponding payouts, hex encoded");
if (ASSETCHAINS_CC < 2) if (ASSETCHAINS_CC <= 1000)
throw runtime_error("-ac_cc < 2"); throw runtime_error("-ac_cc <= 1000");
if (ASSETCHAINS_SYMBOL[0] == 0) if (ASSETCHAINS_SYMBOL[0] == 0)
throw runtime_error("Must be called on assetchain"); throw runtime_error("Must be called on assetchain");

View File

@@ -1015,18 +1015,52 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp)
} }
UniValue komodo_snapshot(); UniValue komodo_snapshot(int top);
UniValue getsnapshot(const UniValue& params, bool fHelp) UniValue getsnapshot(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); int64_t total; UniValue result(UniValue::VOBJ); int64_t total; int32_t top = 0;
if ( fHelp || params.size() > 0 )
if (params.size() > 0 && !params[0].isNull()) {
top = atoi(params[0].get_str().c_str());
if (top <= 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
}
if ( fHelp || params.size() > 1)
{ {
throw runtime_error( throw runtime_error(
"getsnapshot\n" "getsnapshot\n"
"\nReturns a snapshot of (address,amount) pairs at current height (requires addressindex to be enabled).\n"
"\nArguments:\n"
" \"top\" (number, optional) Only return this many addresses, i.e. top N richlist\n"
"\nResult:\n"
"{\n"
" \"addresses\": [\n"
" {\n"
" \"addr\": \"RMEBhzvATA8mrfVK82E5TgPzzjtaggRGN3\",\n"
" \"amount\": \"100.0\"\n"
" },\n"
" {\n"
" \"addr\": \"RqEBhzvATAJmrfVL82E57gPzzjtaggR777\",\n"
" \"amount\": \"23.45\"\n"
" }\n"
" ],\n"
" \"total\": 123.45 (numeric) Total amount in snapshot\n"
" \"average\": 61.7, (numeric) Average amount in each address \n"
" \"utxos\": 14, (number) Total number of UTXOs in snapshot\n"
" \"total_addresses\": 2, (number) Total number of addresses in snapshot,\n"
" \"start_height\": 91, (number) Block height snapshot began\n"
" \"ending_height\": 91 (number) Block height snapsho finished,\n"
" \"start_time\": 1531982752, (number) Unix epoch time snapshot started\n"
" \"end_time\": 1531982752 (number) Unix epoch time snapshot finished\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getsnapshot","")
+ HelpExampleRpc("getsnapshot", "1000")
); );
} }
result = komodo_snapshot(); result = komodo_snapshot(top);
if ( result.size() > 0 ) { if ( result.size() > 0 ) {
result.push_back(Pair("end_time", (int) time(NULL))); result.push_back(Pair("end_time", (int) time(NULL)));
} else { } else {

View File

@@ -196,6 +196,9 @@ int32_t komodo_longestchain()
} }
if ( num > (n >> 1) ) if ( num > (n >> 1) )
{ {
extern char ASSETCHAINS_SYMBOL[];
if ( 0 && height != KOMODO_LONGESTCHAIN )
fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height);
KOMODO_LONGESTCHAIN = height; KOMODO_LONGESTCHAIN = height;
return(height); return(height);
} }

View File

@@ -354,7 +354,10 @@ static const CRPCCommand vRPCCommands[] =
{ "ponzi", "ponziaddress", &ponziaddress, true }, { "ponzi", "ponziaddress", &ponziaddress, true },
/* rewards */ /* rewards */
{ "rewards", "rewardsfund", &rewardsfund, true }, { "rewards", "rewardslist", &rewardslist, true },
{ "rewards", "rewardsinfo", &rewardsinfo, true },
{ "rewards", "rewardscreatefunding", &rewardscreatefunding, true },
{ "rewards", "rewardsaddfunding", &rewardsaddfunding, true },
{ "rewards", "rewardslock", &rewardslock, true }, { "rewards", "rewardslock", &rewardslock, true },
{ "rewards", "rewardsunlock", &rewardsunlock, true }, { "rewards", "rewardsunlock", &rewardsunlock, true },
{ "rewards", "rewardsaddress", &rewardsaddress, true }, { "rewards", "rewardsaddress", &rewardsaddress, true },
@@ -370,6 +373,8 @@ static const CRPCCommand vRPCCommands[] =
{ "dice", "diceaddress", &diceaddress, true }, { "dice", "diceaddress", &diceaddress, true },
/* tokens */ /* tokens */
{ "tokens", "tokeninfo", &tokeninfo, true },
{ "tokens", "tokenlist", &tokenlist, true },
{ "tokens", "tokenorders", &tokenorders, true }, { "tokens", "tokenorders", &tokenorders, true },
{ "tokens", "tokenaddress", &tokenaddress, true }, { "tokens", "tokenaddress", &tokenaddress, true },
{ "tokens", "tokenbalance", &tokenbalance, true }, { "tokens", "tokenbalance", &tokenbalance, true },

View File

@@ -208,6 +208,8 @@ extern UniValue submitblock(const UniValue& params, bool fHelp);
extern UniValue estimatefee(const UniValue& params, bool fHelp); extern UniValue estimatefee(const UniValue& params, bool fHelp);
extern UniValue estimatepriority(const UniValue& params, bool fHelp); extern UniValue estimatepriority(const UniValue& params, bool fHelp);
extern UniValue coinsupply(const UniValue& params, bool fHelp); extern UniValue coinsupply(const UniValue& params, bool fHelp);
extern UniValue tokeninfo(const UniValue& params, bool fHelp);
extern UniValue tokenlist(const UniValue& params, bool fHelp);
extern UniValue tokenorders(const UniValue& params, bool fHelp); extern UniValue tokenorders(const UniValue& params, bool fHelp);
extern UniValue tokenbalance(const UniValue& params, bool fHelp); extern UniValue tokenbalance(const UniValue& params, bool fHelp);
extern UniValue tokenaddress(const UniValue& params, bool fHelp); extern UniValue tokenaddress(const UniValue& params, bool fHelp);
@@ -224,8 +226,11 @@ extern UniValue tokenfillswap(const UniValue& params, bool fHelp);
extern UniValue faucetfund(const UniValue& params, bool fHelp); extern UniValue faucetfund(const UniValue& params, bool fHelp);
extern UniValue faucetget(const UniValue& params, bool fHelp); extern UniValue faucetget(const UniValue& params, bool fHelp);
extern UniValue faucetaddress(const UniValue& params, bool fHelp); extern UniValue faucetaddress(const UniValue& params, bool fHelp);
extern UniValue rewardsinfo(const UniValue& params, bool fHelp);
extern UniValue rewardslist(const UniValue& params, bool fHelp);
extern UniValue rewardsaddress(const UniValue& params, bool fHelp); extern UniValue rewardsaddress(const UniValue& params, bool fHelp);
extern UniValue rewardsfund(const UniValue& params, bool fHelp); extern UniValue rewardscreatefunding(const UniValue& params, bool fHelp);
extern UniValue rewardsaddfunding(const UniValue& params, bool fHelp);
extern UniValue rewardslock(const UniValue& params, bool fHelp); extern UniValue rewardslock(const UniValue& params, bool fHelp);
extern UniValue rewardsunlock(const UniValue& params, bool fHelp); extern UniValue rewardsunlock(const UniValue& params, bool fHelp);
extern UniValue diceaddress(const UniValue& params, bool fHelp); extern UniValue diceaddress(const UniValue& params, bool fHelp);

View File

@@ -399,7 +399,7 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address); bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address);
extern UniValue CBlockTreeDB::Snapshot() extern UniValue CBlockTreeDB::Snapshot(int top)
{ {
char chType; int64_t total = 0; int64_t totalAddresses = 0; std::string address; char chType; int64_t total = 0; int64_t totalAddresses = 0; std::string address;
int64_t utxos = 0; int64_t ignoredAddresses; int64_t utxos = 0; int64_t ignoredAddresses;
@@ -473,7 +473,7 @@ extern UniValue CBlockTreeDB::Snapshot()
addressAmounts[address] += nValue; addressAmounts[address] += nValue;
} }
//fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN); //fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN);
total += nValue; // total += nValue;
utxos++; utxos++;
} catch (const std::exception& e) { } catch (const std::exception& e) {
fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what()); fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what());
@@ -496,21 +496,33 @@ extern UniValue CBlockTreeDB::Snapshot()
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
UniValue addressesSorted(UniValue::VARR); UniValue addressesSorted(UniValue::VARR);
int topN = 0;
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) { for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.push_back( make_pair("addr", it->second.c_str() ) ); obj.push_back( make_pair("addr", it->second.c_str() ) );
char amount[32]; char amount[32];
sprintf(amount, "%.8f", (double) it->first / COIN); sprintf(amount, "%.8f", (double) it->first / COIN);
obj.push_back( make_pair("amount", amount) ); obj.push_back( make_pair("amount", amount) );
total += it->first;
addressesSorted.push_back(obj); addressesSorted.push_back(obj);
topN++;
// If requested, only show top N addresses in output JSON
if (top == topN)
break;
} }
if (top)
totalAddresses = top;
if (totalAddresses > 0) { if (totalAddresses > 0) {
// Array of all addreses with balances
result.push_back(make_pair("addresses", addressesSorted)); result.push_back(make_pair("addresses", addressesSorted));
// Total amount in this snapshot, which is less than circulating supply if top parameter is used
result.push_back(make_pair("total", (double) total / COIN )); result.push_back(make_pair("total", (double) total / COIN ));
// Average amount in each address of this snapshot
result.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); result.push_back(make_pair("average",(double) (total/COIN) / totalAddresses ));
} }
// Total number of utxos in this snaphot // Total number of utxos processed in this snaphot
result.push_back(make_pair("utxos", utxos)); result.push_back(make_pair("utxos", utxos));
// Total number of addresses in this snaphot // Total number of addresses in this snaphot
result.push_back(make_pair("total_addresses", totalAddresses)); result.push_back(make_pair("total_addresses", totalAddresses));

View File

@@ -95,7 +95,7 @@ public:
bool ReadFlag(const std::string &name, bool &fValue); bool ReadFlag(const std::string &name, bool &fValue);
bool LoadBlockIndexGuts(); bool LoadBlockIndexGuts();
bool blockOnchainActive(const uint256 &hash); bool blockOnchainActive(const uint256 &hash);
UniValue Snapshot(); UniValue Snapshot(int top);
}; };
#endif // BITCOIN_TXDB_H #endif // BITCOIN_TXDB_H

View File

@@ -4850,10 +4850,10 @@ int32_t ensure_CCrequirements()
UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey) UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey)
{ {
UniValue result(UniValue::VOBJ); ; char destaddr[64],str[64]; UniValue result(UniValue::VOBJ); ; char destaddr[64],str[64],marker[64];
// { uint8_t p[32]; Myprivkey(p); }
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
sprintf(str,"%sCCaddress",name); sprintf(str,"%sCCaddress",name);
sprintf(marker,"%smarker",name);
if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 ) if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 )
result.push_back(Pair(str,destaddr)); result.push_back(Pair(str,destaddr));
if ( pubkey.size() == 33 ) if ( pubkey.size() == 33 )
@@ -4863,6 +4863,8 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned ch
} }
if ( GetCCaddress(cp,destaddr,pubkey2pk(Mypubkey())) != 0 ) if ( GetCCaddress(cp,destaddr,pubkey2pk(Mypubkey())) != 0 )
result.push_back(Pair("myCCaddress",destaddr)); result.push_back(Pair("myCCaddress",destaddr));
if ( Getscriptaddress(destaddr,(CScript() << Mypubkey() << OP_CHECKSIG)) != 0 )
result.push_back(Pair("myaddress",destaddr));
return(result); return(result);
} }
@@ -4957,18 +4959,18 @@ UniValue tokenaddress(const UniValue& params, bool fHelp)
return(CCaddress(cp,(char *)"Assets",pubkey)); return(CCaddress(cp,(char *)"Assets",pubkey));
} }
UniValue rewardsfund(const UniValue& params, bool fHelp) UniValue rewardscreatefunding(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); char *name; uint64_t funds,APR,minseconds,maxseconds,mindeposit; std::string hex; UniValue result(UniValue::VOBJ); char *name; uint64_t funds,APR,minseconds,maxseconds,mindeposit; std::string hex;
if ( fHelp || params.size() > 6 || params.size() < 2 ) if ( fHelp || params.size() > 6 || params.size() < 2 )
throw runtime_error("rewardsfund name amount APR mindays maxdays mindeposit\n"); throw runtime_error("rewardscreatefunding name amount APR mindays maxdays mindeposit\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
// default to OOT params // default to OOT params
APR = 5 * COIN; APR = 5 * COIN;
minseconds = maxseconds = 60 * 3600 * 24; minseconds = maxseconds = 60 * 3600 * 24;
mindeposit = 100 * COIN; mindeposit = 100 * COIN;
name = (char *)params[1].get_str().c_str(); name = (char *)params[0].get_str().c_str();
funds = atof(params[1].get_str().c_str()) * COIN; funds = atof(params[1].get_str().c_str()) * COIN;
if ( params.size() > 2 ) if ( params.size() > 2 )
{ {
@@ -4984,7 +4986,7 @@ UniValue rewardsfund(const UniValue& params, bool fHelp)
} }
} }
} }
hex = RewardsFund(0,name,funds,APR,minseconds,maxseconds,mindeposit); hex = RewardsCreateFunding(0,name,funds,APR,minseconds,maxseconds,mindeposit);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -4995,14 +4997,34 @@ UniValue rewardsfund(const UniValue& params, bool fHelp)
UniValue rewardslock(const UniValue& params, bool fHelp) UniValue rewardslock(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); char *name; uint64_t amount; std::string hex; UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; uint64_t amount; std::string hex;
if ( fHelp || params.size() > 2 ) if ( fHelp || params.size() != 3 )
throw runtime_error("rewardslock name amount\n"); throw runtime_error("rewardslock name fundingtxid amount\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
name = (char *)params[0].get_str().c_str(); name = (char *)params[0].get_str().c_str();
amount = atof(params[1].get_str().c_str()) * COIN; fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
hex = RewardsLock(0,name,amount); amount = atof(params[2].get_str().c_str()) * COIN;
hex = RewardsLock(0,name,fundingtxid,amount);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else result.push_back(Pair("error", "couldnt create rewards lock transaction"));
return(result);
}
UniValue rewardsaddfunding(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; uint64_t amount; std::string hex;
if ( fHelp || params.size() != 3 )
throw runtime_error("rewardsaddfunding name fundingtxid amount\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
name = (char *)params[0].get_str().c_str();
fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
amount = atof(params[2].get_str().c_str()) * COIN;
hex = RewardsAddfunding(0,name,fundingtxid,amount);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5013,16 +5035,17 @@ UniValue rewardslock(const UniValue& params, bool fHelp)
UniValue rewardsunlock(const UniValue& params, bool fHelp) UniValue rewardsunlock(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); std::string hex; char *name; uint256 txid; UniValue result(UniValue::VOBJ); std::string hex; char *name; uint256 fundingtxid,txid;
if ( fHelp || params.size() > 2 ) if ( fHelp || params.size() > 3 )
throw runtime_error("rewardsunlock name [txid]\n"); throw runtime_error("rewardsunlock name fundingtxid [txid]\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
name = (char *)params[0].get_str().c_str(); name = (char *)params[0].get_str().c_str();
if ( params.size() > 1 ) fundingtxid = Parseuint256((char *)params[1].get_str().c_str());
txid = Parseuint256((char *)params[1].get_str().c_str()); if ( params.size() > 2 )
txid = Parseuint256((char *)params[2].get_str().c_str());
else memset(&txid,0,sizeof(txid)); else memset(&txid,0,sizeof(txid));
hex = RewardsUnlock(0,name,txid); hex = RewardsUnlock(0,name,fundingtxid,txid);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5101,6 +5124,48 @@ UniValue dicebet(const UniValue& params, bool fHelp)
return(result); return(result);
} }
UniValue rewardslist(const UniValue& params, bool fHelp)
{
uint256 tokenid;
if ( fHelp || params.size() > 0 )
throw runtime_error("rewardslist\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
return(RewardsList());
}
UniValue rewardsinfo(const UniValue& params, bool fHelp)
{
uint256 fundingtxid;
if ( fHelp || params.size() != 1 )
throw runtime_error("rewardsinfo fundingtxid\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
return(RewardsInfo(fundingtxid));
}
UniValue tokenlist(const UniValue& params, bool fHelp)
{
uint256 tokenid;
if ( fHelp || params.size() > 0 )
throw runtime_error("tokenlist\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
return(AssetList());
}
UniValue tokeninfo(const UniValue& params, bool fHelp)
{
uint256 tokenid;
if ( fHelp || params.size() != 1 )
throw runtime_error("tokeninfo tokenid\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
tokenid = Parseuint256((char *)params[0].get_str().c_str());
return(AssetInfo(tokenid));
}
UniValue tokenorders(const UniValue& params, bool fHelp) UniValue tokenorders(const UniValue& params, bool fHelp)
{ {
uint256 tokenid; uint256 tokenid;
@@ -5233,7 +5298,6 @@ UniValue tokenfillbid(const UniValue& params, bool fHelp)
UniValue tokenask(const UniValue& params, bool fHelp) UniValue tokenask(const UniValue& params, bool fHelp)
{ {
static uint256 zeroid;
UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid; UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid;
if ( fHelp || params.size() != 3 ) if ( fHelp || params.size() != 3 )
throw runtime_error("tokenask numtokens tokenid price\n"); throw runtime_error("tokenask numtokens tokenid price\n");
@@ -5243,7 +5307,7 @@ UniValue tokenask(const UniValue& params, bool fHelp)
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
price = atof(params[2].get_str().c_str()); price = atof(params[2].get_str().c_str());
askamount = (price * numtokens) * COIN + 0.0000000049999; askamount = (price * numtokens) * COIN + 0.0000000049999;
hex = CreateSell(0,numtokens,tokenid,zeroid,askamount); hex = CreateSell(0,numtokens,tokenid,askamount);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5257,15 +5321,15 @@ UniValue tokenswapask(const UniValue& params, bool fHelp)
static uint256 zeroid; static uint256 zeroid;
UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid,otherid; UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid,otherid;
if ( fHelp || params.size() != 4 ) if ( fHelp || params.size() != 4 )
throw runtime_error("tokenswap numtokens tokenid otherid price\n"); throw runtime_error("tokenswapask numtokens tokenid otherid price\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
numtokens = atoi(params[0].get_str().c_str()); numtokens = atoi(params[0].get_str().c_str());
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
otherid = Parseuint256((char *)params[2].get_str().c_str()); otherid = Parseuint256((char *)params[2].get_str().c_str());
price = atof(params[3].get_str().c_str()); price = atof(params[3].get_str().c_str());
askamount = (price * numtokens) * COIN + 0.0000000049999; askamount = (price * numtokens);
hex = CreateSell(0,numtokens,tokenid,otherid,askamount); hex = CreateSwap(0,numtokens,tokenid,otherid,askamount);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5295,15 +5359,15 @@ UniValue tokencancelask(const UniValue& params, bool fHelp)
UniValue tokenfillask(const UniValue& params, bool fHelp) UniValue tokenfillask(const UniValue& params, bool fHelp)
{ {
static uint256 zeroid; static uint256 zeroid;
UniValue result(UniValue::VOBJ); uint64_t fillamount; std::string hex; uint256 tokenid,asktxid; UniValue result(UniValue::VOBJ); uint64_t fillunits; std::string hex; uint256 tokenid,asktxid;
if ( fHelp || params.size() != 3 ) if ( fHelp || params.size() != 3 )
throw runtime_error("tokenfillask tokenid asktxid fillamount\n"); throw runtime_error("tokenfillask tokenid asktxid fillunits\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
asktxid = Parseuint256((char *)params[1].get_str().c_str()); asktxid = Parseuint256((char *)params[1].get_str().c_str());
fillamount = atol(params[2].get_str().c_str()); fillunits = atol(params[2].get_str().c_str());
hex = FillSell(0,tokenid,zeroid,asktxid,fillamount); hex = FillSell(0,tokenid,zeroid,asktxid,fillunits);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5315,16 +5379,16 @@ UniValue tokenfillask(const UniValue& params, bool fHelp)
UniValue tokenfillswap(const UniValue& params, bool fHelp) UniValue tokenfillswap(const UniValue& params, bool fHelp)
{ {
static uint256 zeroid; static uint256 zeroid;
UniValue result(UniValue::VOBJ); uint64_t fillamount; std::string hex; uint256 tokenid,otherid,asktxid; UniValue result(UniValue::VOBJ); uint64_t fillunits; std::string hex; uint256 tokenid,otherid,asktxid;
if ( fHelp || params.size() != 4 ) if ( fHelp || params.size() != 4 )
throw runtime_error("tokenfillswap tokenid otherid asktxid fillamount\n"); throw runtime_error("tokenfillswap tokenid otherid asktxid fillunits\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
otherid = Parseuint256((char *)params[1].get_str().c_str()); otherid = Parseuint256((char *)params[1].get_str().c_str());
asktxid = Parseuint256((char *)params[2].get_str().c_str()); asktxid = Parseuint256((char *)params[2].get_str().c_str());
fillamount = atol(params[3].get_str().c_str()); fillunits = atol(params[3].get_str().c_str());
hex = FillSell(0,tokenid,otherid,asktxid,fillamount); hex = FillSell(0,tokenid,otherid,asktxid,fillunits);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));