Initial gateways CC

This commit is contained in:
jl777
2018-09-09 21:07:02 -11:00
parent 3334d6f911
commit 3515c101d4
11 changed files with 815 additions and 86 deletions

View File

@@ -20,8 +20,13 @@
#include "CCinclude.h" #include "CCinclude.h"
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys);
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,std::vector<CPubKey>pubkeys,int32_t height,std::string refcoin,uint256 cointxid,std::string deposithex,std::vector<uint256>proof,std::vector<uint8_t> claimpubkey,int64_t amount);
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string coin,uint256 deposittxid,std::string claimaddr,int64_t amount);
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount);
// CCcustom // CCcustom
UniValue GatewaysInfo(); UniValue GatewaysInfo();
UniValue GatewaysList(uint256 bindtxid);
#endif #endif

View File

@@ -223,16 +223,16 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> des
for (i=0; i<n; i++) for (i=0; i<n; i++)
total += amounts[i];*/ total += amounts[i];*/
mask = ~((1LL << mtx.vin.size()) - 1); 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 )
CCchange = (inputs - total); CCchange = (inputs - total);
//for (i=0; i<n; i++) //for (i=0; i<n; i++)
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(mask,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(""); return("");

View File

@@ -76,6 +76,19 @@ struct CCcontract_info
}; };
struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode);
struct oracle_merklepair
{
CPubKey pk;
uint256 txid;
};
struct oracleprice_info
{
CPubKey pk;
std::vector <uint8_t> data;
int32_t height;
};
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
extern CWallet* pwalletMain; extern CWallet* pwalletMain;
#endif #endif
@@ -92,8 +105,15 @@ bool mySendrawtransaction(std::string res);
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp);
int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp);
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
int64_t CCaddress_balance(char *coinaddr);
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format); int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format);
uint256 OracleMerkle(int32_t height,uint256 reforacletxid,char *format,std::vector<struct oracle_merklepair>publishers);
uint256 OraclesBatontxid(uint256 oracletxid,CPubKey pk);
int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs);
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
// CCcustom // CCcustom
CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv); CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv);
@@ -114,6 +134,9 @@ char *uint256_str(char *dest,uint256 txid);
char *pubkey33_str(char *dest,uint8_t *pubkey33); 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);
int64_t CCfullsupply(uint256 tokenid);
int64_t CCtoken_balance(char *destaddr,uint256 tokenid);
bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk);
bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk); bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk);
bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2); bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2);
bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue); bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue);

View File

@@ -212,6 +212,48 @@ int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout)
return(0); return(0);
} }
int64_t CCaddress_balance(char *coinaddr)
{
int64_t sum = 0; 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++)
{
sum += it->second.satoshis;
}
return(sum);
}
int64_t CCfullsupply(uint256 tokenid)
{
uint256 hashBlock; int32_t numvouts; CTransaction tx; std::vector<uint8_t> origpubkey; std::string name,description;
if ( GetTransaction(tokenid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
{
if ( DecodeAssetCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description) > 0 )
{
return(tx.vout[0].nValue);
}
}
return(0);
}
int64_t CCtoken_balance(char *destaddr,uint256 tokenid)
{
int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock; std::vector<uint8_t> origpubkey; 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 ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
{
if ( DecodeAssetOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 && assetid == tokenid )
{
sum += it->second.satoshis;
}
}
}
return(sum);
}
int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,int64_t value) int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,int64_t value)
{ {
int32_t i,abovei,belowi; int64_t above,below,gap,atx_value; int32_t i,abovei,belowi; int64_t above,below,gap,atx_value;

View File

@@ -181,13 +181,11 @@ bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
return(false); return(false);
} }
bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk) bool _GetCCaddress(char *destaddr,uint8_t evalcode,CPubKey pk)
{ {
CC *payoutCond; CC *payoutCond;
destaddr[0] = 0; destaddr[0] = 0;
if ( pk.size() == 0 ) if ( (payoutCond= MakeCCcond1(evalcode,pk)) != 0 )
pk = GetUnspendable(cp,0);
if ( (payoutCond= MakeCCcond1(cp->evalcode,pk)) != 0 )
{ {
Getscriptaddress(destaddr,CCPubKey(payoutCond)); Getscriptaddress(destaddr,CCPubKey(payoutCond));
cc_free(payoutCond); cc_free(payoutCond);
@@ -195,6 +193,14 @@ bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk)
return(destaddr[0] != 0); return(destaddr[0] != 0);
} }
bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk)
{
destaddr[0] = 0;
if ( pk.size() == 0 )
pk = GetUnspendable(cp,0);
return(_GetCCaddress(destaddr,cp->evalcode,pk));
}
bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2) bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2)
{ {
CC *payoutCond; CC *payoutCond;

View File

@@ -20,11 +20,80 @@
the potential pubkeys to be used would be based on active oracle data providers with recent activity. the potential pubkeys to be used would be based on active oracle data providers with recent activity.
bind asset <-> KMD gateway deposit address
KMD deposit -> globally spendable marker utxo
spend marker utxo and spend linked/locked asset to user's CC address
redeem -> asset to global CC address with withdraw address -> gateway spendable marker utxo
spend market utxo and withdraw from gateway deposit address
rpc calls:
GatewayList
GatewayInfo bindtxid
GatewayBind coin tokenid M N pubkey(s)
external: deposit to depositaddr with claimpubkey
GatewayDeposit coin tokenid external.deposittxid -> markertxid
GatewayClaim coin tokenid external.deposittxid markertxid -> spend marker and deposit asset
GatewayWithdraw coin tokenid withdrawaddr
external: do withdraw to withdrawaddr and spend marker, support for partial signatures and autocomplete
deposit addr can be 1 to MofN pubkeys
1:1 gateway with native coin
*/ */
// start of consensus code // start of consensus code
CScript EncodeGatewaysBindOpRet(uint8_t funcid,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << prefix << prefix2 << taddr << tokenid << totalsupply << M << N << pubkeys);
return(opret);
}
CScript EncodeGatewaysOpRet(uint8_t funcid,std::string coin,uint256 bindtxid,std::vector<struct oracle_merklepair> publishers,int32_t height,uint256 cointxid,std::string deposithex,std::vector<uint256>proof,std::vector<uint8_t> redeemscript,int64_t amount)
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << bindtxid << publishers << height << cointxid << deposithex << proof << redeemscript << amount);
return(opret);
}
uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey,std::string &coin,uint256 &bindtxid,std::vector<struct oracle_merklepair> &publishers,int32_t &height,uint256 &cointxid,std::string &deposithex,std::vector<uint256> &proof,std::vector<uint8_t> &redeemscript,int64_t &amount)
{
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 >> coin; ss >> bindtxid; ss >> publishers; ss >> height; ss >> cointxid; ss >> deposithex; ss >> proof; ss >> redeemscript; ss >> amount) != 0 )
{
return(f);
}
return(0);
}
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &tokenid,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &pubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
depositaddr[0] = 0;
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> prefix; ss >> prefix2; ss >> taddr; ss >> tokenid; ss >> totalsupply; ss >> M; ss >> N; ss >> pubkeys) != 0 )
{
if ( prefix == 60 )
{
if ( N > 1 )
Getscriptaddress(depositaddr,GetScriptForMultisig(M,pubkeys));
else Getscriptaddress(depositaddr,CScript() << Mypubkey(pubkeys[0]) << OP_CHECKSIG);
}
else
{
fprintf(stderr,"need to generate non-KMD addresses\n");
}
return(f);
}
return(0);
}
int64_t IsGatewaysvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) int64_t IsGatewaysvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
{ {
char destaddr[64]; char destaddr[64];
@@ -128,7 +197,7 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
// no need to prevent dup // no need to prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{ {
if ( (nValue= IsGatewaysvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) if ( (nValue= IsGatewaysvout(cp,vintx,vout)) > 10000 && myIsutxo_spentinmempool(txid,vout) == 0 )
{ {
if ( total != 0 && maxinputs != 0 ) if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript())); mtx.vin.push_back(CTxIn(txid,vout,CScript()));
@@ -143,73 +212,353 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
return(totalinputs); return(totalinputs);
} }
std::string GatewaysGet(uint64_t txfee,int64_t nValue) UniValue GatewaysInfo(uint256 bindtxid)
{ {
CMutableTransaction mtx,tmpmtx; CPubKey mypk,Gatewayspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; UniValue result(UniValue::VOBJ); std::string coin; char str[65],numstr[65],depositaddr[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid; CTransaction tx; CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int64_t totalsupply,remaining;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
Gatewayspk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey());
if ( (inputs= AddGatewaysInputs(cp,mtx,Gatewayspk,nValue+txfee,60)) > 0 )
{
if ( inputs > nValue )
CCchange = (inputs - nValue - txfee);
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,Gatewayspk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
fprintf(stderr,"start at %u\n",(uint32_t)time(NULL));
j = rand() & 0xfffffff;
for (i=0; i<1000000; i++,j++)
{
tmpmtx = mtx;
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_GATEWAYS << (uint8_t)'G' << j));
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
{
len >>= 1;
decode_hex(buf,len,(char *)rawhex.c_str());
hash = bits256_doublesha256(0,buf,len);
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
{
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
return(rawhex);
}
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
}
}
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
return("");
} else fprintf(stderr,"cant find Gateways inputs\n");
return("");
}
std::string GatewaysFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,Gatewayspk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
Gatewayspk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,funds,Gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
}
return("");
}
UniValue GatewaysInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success")); result.push_back(Pair("result","success"));
result.push_back(Pair("name","Gateways")); result.push_back(Pair("name","Gateways"));
cp = CCinit(&C,EVAL_GATEWAYS); cp = CCinit(&C,EVAL_GATEWAYS);
Gatewayspk = GetUnspendable(cp,0); Gatewayspk = GetUnspendable(cp,0);
funding = AddGatewaysInputs(cp,mtx,Gatewayspk,0,0); if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )
sprintf(numstr,"%.8f",(double)funding/COIN); {
result.push_back(Pair("funding",numstr)); if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 && M <= N && N > 0 )
{
depositaddr[0] = 0;
if ( N > 1 )
{
result.push_back(Pair("M",M));
result.push_back(Pair("N",N));
}
result.push_back(Pair("coin",coin));
result.push_back(Pair("oracletxid",uint256_str(str,oracletxid)));
result.push_back(Pair("taddr",taddr));
result.push_back(Pair("prefix",prefix));
result.push_back(Pair("prefix2",prefix2));
result.push_back(Pair("deposit",depositaddr));
result.push_back(Pair("tokenid",uint256_str(str,tokenid)));
sprintf(numstr,"%.8f",(double)totalsupply/COIN);
result.push_back(Pair("totalsupply",numstr));
remaining = CCaddress_balance(depositaddr);
sprintf(numstr,"%.8f",(double)remaining/COIN);
result.push_back(Pair("remaining",numstr));
sprintf(numstr,"%.8f",(double)(totalsupply - remaining)/COIN);
result.push_back(Pair("issued",numstr));
}
}
return(result); return(result);
} }
UniValue GatewaysList()
{
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid,tokenid; CTransaction vintx; std::string coin,depositaddr; char str[65],depositaddr[64]; uint8_t M,N,taddr,prefix,prefix2; std::vector<CPubKey> pubkeys;
cp = CCinit(&C,EVAL_GATEWAYS);
SetCCtxids(addressIndex,cp->unspendableCCaddr);
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 && DecodeGatewaysBindOpRet(depositaddr,vintx.vout[vintx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 )
{
result.push_back(uint256_str(str,txid));
}
}
}
return(result);
}
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys)
{
CMutableTransaction mtx; CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char coinaddr[64],str[65],*fstr;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( N == 0 || N > 15 || M > N )
{
fprintf(stderr,"illegal M.%d or N.%d\n",M,N);
return("");
}
if ( strcmp((char *)"KMD",coin.c_str()) != 0 )
{
fprintf(stderr,"only KMD supported for now\n");
return("");
}
taddr = 0;
prefix = 60;
prefix2 = 85;
if ( pubkeys.size() != N )
{
fprintf(stderr,"M.%d N.%d but pubkeys[%d]\n",M,N,(int32_t)pubkeys.size());
return("");
}
for (i=0; i<N; i++)
{
Getscriptaddress(coinaddr,CScript() << Mypubkey(pubkeys[i]) << OP_CHECKSIG);
if ( (balance= CCaddress_balance(coinaddr)) == 0 )
{
fprintf(stderr,"M.%d N.%d but pubkeys[%d] has no balance\n",M,N,i);
return("");
}
}
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( _GetCCaddress(destaddr,EVAL_ASSETS,gatewayspk) == 0 )
{
fprintf(stderr,"Gateway bind.%s (%s) cant create globaladdr\n",coin,tokenid);
return("");
}
if ( (fullsupply= CCfullsupply(tokenid)) != tokensupply )
{
fprintf(stderr,"Gateway bind.%s (%s) globaladdr.%s tokensupply %.8f != fullsupply %.8f\n",coin,tokenid,(double)tokensupply/COIN,(double)fullsupply/COIN);
return("");
}
if ( CCtoken_balance(destaddr,tokenid) != tokensupply )
{
fprintf(stderr,"Gateway bind.%s (%s) globaladdr.%s token balance %.8f != %.8f\n",coin,tokenid,(double)CCtoken_balance(destaddr,tokenid)/COIN,(double)tokensupply/COIN);
return("");
}
if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= orcaletx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find oracletxid %s\n",uint256_str(str,oracletxid));
return("");
}
if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' )
{
fprintf(stderr,"mismatched oracle name %s != %s\n",name,coin);
return("");
}
if ( (fstr= (char *)format.c_str()) == 0 || strncmp(fstr,"Ihh",3) != 0 )
{
fprintf(stderr,"illegal format (%s) != (%s)\n",fstr,(char *)"Ihh");
return("");
}
if ( GatewaysBindExists(cp,gatewayspk,coin,tokenid) != 0 ) // dont forget to check mempool!
{
fprintf(stderr,"Gateway bind.%s (%s) already exists\n",coin,tokenid);
return("");
}
if ( AddNormalinputs(mtx,mypk,2*txfee,60) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2)));
}
fprintf(stderr,"cant find enough inputs\n");
return("");
}
uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
{
CTransaction tx; uint256 hash,mhash; int64_t val; int32_t numvouts,merkleht; CPubKey pk; std::vector<uint8_t>data;
txid = zeroid;
while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
{
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,hash,pk,data) == 'D' && oracletxid == reforacletxid )
{
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
{
if ( oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size()) == sizeof(hash) &&
oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()) == sizeof(hash) && mhash != zeroid )
{
txid = batontxid;
return(mhash);
} else return(zeroid);
}
batontxid = hash;
} else break;
}
return(zeroid);
}
int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vector<uint256>proof,uint256 merkleroot,std::vector<uint8_t>redeemscript)
{
uint256 txid = zeroid; CTransaction tx; std::string name,description,format; CScript scriptPubKey; char destaddr[64]; int64_t nValue = 0;
if ( GetTransaction(oracletxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
fprintf(stderr,"GatewaysVerify cant find oracletxid %s\n",uint256_str(str,oracletxid));
return(0);
}
if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin )
{
fprintf(stderr,"GatewaysVerify mismatched oracle name %s != %s\n",name,refcoin);
return(0);
}
if ( DecodeHexTx(tx,deposithex) != 0 )
{
scriptPubKey = CScript() << redeemscript;
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
if ( strcmp(refdepositaddr,destaddr) == 0 && scriptPubKey == tx.vout[1].scriptPubKey )
{
txid = tx.GetHash();
nValue = tx.vout[0].nValue;
}
else
{
Getscriptaddress(destaddr,tx.vout[1].scriptPubKey);
if ( strcmp(refdepositaddr,destaddr) == 0 && scriptPubKey == tx.vout[0].scriptPubKey )
{
txid = tx.GetHash();
nValue = tx.vout[1].nValue;
}
}
}
if ( txid == cointxid )
{
fprintf(stderr,"verify proof for cointxid in merkleroot\n");
return(nValue);
} else fprintf(stderr,"(%s) != (%s) or txid mismatch.%d or script mismatch.%d\n",refdepositaddr,destaddr,txid != cointxid,scriptPubKey != tx.vout[1].scriptPubKey);
return(0);
}
int64_t GatewaysDepositval(CTransaction tx)
{
int32_t numvouts,height; int64_t amount; std::string coin,deposithex; std::vector<struct oracle_merklepair> publishers; uint256 bindtxid,cointxid; std::vector<uint256> proof; std::vector<uint8_t> claimpubkey;
if ( (numvouts= tx.vout.size()) > 0 )
{
if ( DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey,coin,bindtxid,publishers,height,cointxid,deposithex,proof,claimpubkey,amount) == 'D' )
{
// coin, bindtxid, publishers
fprintf(stderr,"need to validate deposittxid more\n");
return(amount);
}
}
return(0);
}
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,std::vector<CPubKey>pubkeys,int32_t height,std::string refcoin,uint256 cointxid,std::string deposithex,std::vector<uint256>proof,std::vector<uint8_t> redeemscript,int64_t amount)
{
CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid; int64_t totalsupply; int32_t i,m,n; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; std::vector<CPubKey> msigpubkeys; std::vector<struct oracle_merklepair> publishers; struct oracle_merklepair P; char str[65],depositaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( GetTransaction(bindtxid,bindtx,hashBlock,false) == 0 || (numvouts= bindtx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || refcoin != coin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin);
return("");
}
n = (int32_t)pubkeys.size();
merkleroot = zeroid;
for (i=m=0; i<n; i++)
{
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i].pk))) != zeroid )
{
if ( merkleroot == zeroid )
merkleroot = mhash, m = 1;
else if ( mhash == merkleroot )
m++;
P.pk = pubkeys[i].pk;
P.txid = txid;
publishers.push_back(P);
}
}
if ( merkleroot == zeroid || m < n/2 )
{
fprintf(stderr,"couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d\n",height,coin,uint256_str(str,oracletxid),m,n);
return("");
}
if ( GatewaysVerify(depositaddr,oracletxid,coin,cointxid,deposithex,proof,merkleroot,redeemscript) != amount )
{
fprintf(stderr,"deposittxid didnt validate\n");
return("");
}
if ( AddNormalinputs(mtx,mypk,2*txfee,60) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysOpRet('D',coin,bindtxid,publishers,height,cointxid,deposithex,proof,redeemscript,amount)));
}
fprintf(stderr,"cant find enough inputs\n");
return("");
}
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,std::vector<uint8_t> claimpubkey,int64_t amount)
{
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector<CPubKey> msigpubkeys; int64_t totalsupply,inputs,CCchange=0; int32_t numvouts; uint256 assetid,oracletxid; char str[65],depositaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
assetscp = CCinit(&C2,EVAL_ASSETS);
memcpy(cp->unspendablepriv2,assetscp->CCpriv,32);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin);
return("");
}
if ( GetTransaction(deposittxid,tx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( (total= GatewaysDepositval(tx)) == 0 )
{
fprintf(stderr,"invalid Gateways deposittxid %s\n",uint256_str(str,deposittxid));
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
{
if ( (inputs= AddAssetInputs(assetscp,mtx,gatewayspk,assetid,total,60)) > 0 )
{
if ( inputs > total )
CCchange = (inputs - total);
mtx.vin.push_back(CTxIn(deposittxid,0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,total,mypk));
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,gatewayspk));
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
}
}
fprintf(stderr,"cant find enough inputs or mismatched total\n");
return("");
}
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount)
{
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint256 assetid; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector<CPubKey> msigpubkeys; char depositaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
assetscp = CCinit(&C2,EVAL_ASSETS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
{
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin);
return("");
}
if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 )
{
if ( (inputs= AddAssetInputs(assetscp,mtx,mypk,assetid,amount,60)) > 0 )
{
if ( inputs > amount )
CCchange = (inputs - amount);
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,gatewayspk));
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG));
return(FinalizeCCTx(mask,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
}
}
fprintf(stderr,"cant find enough inputs or mismatched total\n");
return("");
}
// withdrawtxid used on external chain to create baton address, its existence in mempool (along with the withdraw) proof that the withdraw is pending

View File

@@ -369,13 +369,6 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t
return(offset); return(offset);
} }
struct oracleprice_info
{
CPubKey pk;
std::vector <uint8_t> data;
int32_t height;
};
int64_t _correlate_price(int64_t *prices,int32_t n,int64_t price) int64_t _correlate_price(int64_t *prices,int32_t n,int64_t price)
{ {
int32_t i,count = 0; int64_t diff,threshold = (price >> 8); int32_t i,count = 0; int64_t diff,threshold = (price >> 8);
@@ -451,7 +444,7 @@ int32_t oracleprice_add(std::vector<struct oracleprice_info> &publishers,CPubKey
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format) int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format)
{ {
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CTransaction regtx,tx; uint256 hash,txid,oracletxid,batontxid; CPubKey pk; int32_t i,ht,maxheight=0; int64_t datafee,price; char batonaddr[64]; std::vector <uint8_t> data; struct CCcontract_info *cp,C; std::vector <struct oracleprice_info> publishers; std::vector <int64_t> prices; CTransaction regtx; uint256 hash,txid,oracletxid,batontxid; CPubKey pk; int32_t i,ht,maxheight=0; int64_t datafee,price; char batonaddr[64]; std::vector <uint8_t> data; struct CCcontract_info *cp,C; std::vector <struct oracleprice_info> publishers; std::vector <int64_t> prices;
if ( format[0] != 'L' ) if ( format[0] != 'L' )
return(0); return(0);
cp = CCinit(&C,EVAL_ORACLES); cp = CCinit(&C,EVAL_ORACLES);
@@ -487,6 +480,36 @@ int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *
return(0); return(0);
} }
uint256 OraclesBatontxid(uint256 reforacletxid,CPubKey refpk)
{
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CTransaction tx; uint256 hash,txid,rettxid,oracletxid; CPubKey pk,markerpubkey; int32_t numvouts,ht,maxheight=0; int64_t datafee; uint8_t buf33[33]; char markeraddr[64]; std::vector <uint8_t> data; struct CCcontract_info *cp,C;
rettxid = zeroid;
cp = CCinit(&C,EVAL_ORACLES);
buf33[0] = 0x02;
endiancpy(&buf33[1],(uint8_t *)&reforacletxid,32);
markerpubkey = buf2pk(buf33);
Getscriptaddress(markeraddr,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG);
SetCCunspents(unspentOutputs,markeraddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
//ht = (int32_t)it->second.blockHeight;
if ( myGetTransaction(txid,tx,hash) != 0 && (numvouts= tx.vout.size()) > 0 )
{
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,hash,pk,data) == 'D' && oracletxid == reforacletxid && pk == refpk )
{
if ( oracle_format(&hash,&ht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && ht > maxheight )
{
maxheight = ht;
rettxid = txid;
}
}
}
}
return(rettxid);
}
int64_t IsOraclesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) int64_t IsOraclesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
{ {
char destaddr[64]; char destaddr[64];

View File

@@ -33,6 +33,10 @@
it can be closed at anytime by the trader for cash settlement it can be closed at anytime by the trader for cash settlement
the house account can close it if rekt the house account can close it if rekt
Implementation Notes:
In order to eliminate the need for worrying about sybil attacks, each prices plan would be able to specific pubkey(s?) for whitelisted publishers. It would be possible to have a non-whitelisted plan that would use 50% correlation between publishers.
delta neutral balancing of risk exposure
*/ */
@@ -155,3 +159,176 @@ int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
} }
return(totalinputs); return(totalinputs);
} }
UniValue PricesInfo(uint256 pricesid)
{
UniValue result(UniValue::VOBJ); CPubKey pricepk; uint256 hashBlock,oracletxid; CTransaction vintx; int64_t minbet,maxbet,maxodds; uint64_t funding; char numstr[65]; struct CCcontract_info *cp,C;
if ( GetTransaction(pricesid,vintx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find fundingtxid\n");
ERR_RESULT("cant find fundingtxid");
return(result);
}
if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,oracletxid,minbet,maxbet,maxodds) == 0 )
{
fprintf(stderr,"fundingtxid isnt price creation txid\n");
ERR_RESULT("fundingtxid isnt price creation txid");
return(result);
}
result.push_back(Pair("result","success"));
result.push_back(Pair("pricesid",uint256_str(str,pricesid)));
result.push_back(Pair("oracletxid",uint256_str(str,oracletxid)));
sprintf(numstr,"%.8f",(double)minbet/COIN);
result.push_back(Pair("minbet",numstr));
sprintf(numstr,"%.8f",(double)maxbet/COIN);
result.push_back(Pair("maxbet",numstr));
result.push_back(Pair("maxodds",maxodds));
cp = CCinit(&C,EVAL_PRICES);
pricepk = GetUnspendable(cp,0);
funding = PricePlanFunds(cp,pricepk,pricesid);
sprintf(numstr,"%.8f",(double)funding/COIN);
result.push_back(Pair("funding",numstr));
return(result);
}
UniValue PricesList()
{
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid; CTransaction vintx; int64_t minbet,maxbet,maxodds; char str[65];
cp = CCinit(&C,EVAL_PRICES);
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 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,oracletxid,minbet,maxbet,maxodds) != 0 )
{
result.push_back(uint256_str(str,txid));
}
}
}
return(result);
}
std::string PricesCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks)
{
CMutableTransaction mtx; uint256 zero; CScript fundingPubKey; CPubKey mypk,pricepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C;
if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 )
{
CCerror = "invalid parameter error";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( funds < 100*COIN )
{
CCerror = "price plan needs at least 100 coins";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
memset(&zero,0,sizeof(zero));
if ( (cp= Pricesinit(fundingPubKey,zero,&C,planstr,txfee,mypk,pricepk,sbits,a,b,c,d)) == 0 )
{
CCerror = "Priceinit error in create funding";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( AddNormalinputs(mtx,mypk,funds+3*txfee,60) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,pricepk));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricepk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesFundingOpRet('F',sbits,minbet,maxbet,maxodds,timeoutblocks)));
}
CCerror = "cant find enough inputs";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
std::string PricesAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount)
{
CMutableTransaction mtx; CScript fundingPubKey,scriptPubKey; CPubKey mypk,pricepk; struct CCcontract_info *cp,C; int64_t minbet,maxbet,maxodds;
if ( amount < 0 )
{
CCerror = "amount must be positive";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( (cp= Pricesinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,pricepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 )
return("");
scriptPubKey = CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG;
if ( scriptPubKey == fundingPubKey )
{
if ( AddNormalinputs(mtx,mypk,amount+2*txfee,60) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,pricepk));
mtx.vout.push_back(CTxOut(txfee,fundingPubKey));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesOpRet('E',sbits,fundingtxid,hentropy,zeroid)));
}
else
{
CCerror = "cant find enough inputs";
fprintf(stderr,"%s\n", CCerror.c_str() );
}
}
else
{
CCerror = "only fund creator can add more funds (entropy)";
fprintf(stderr,"%s\n", CCerror.c_str() );
}
return("");
}
std::string PricesBet(uint64_t txfee,uint256 pricesid,int64_t bet,int32_t odds)
{
CMutableTransaction mtx; CScript fundingPubKey; CPubKey mypk,pricepk; int64_t funding,minbet,maxbet,maxodds; struct CCcontract_info *cp,C;
if ( bet < 0 )
{
CCerror = "bet must be positive";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( odds < 1 || odds > 9999 )
{
CCerror = "odds must be between 1 and 9999";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( (cp= Pricesinit(fundingPubKey,pricesid,&C,txfee,mypk,pricepk,minbet,maxbet,maxodds)) == 0 )
return("");
if ( bet < minbet || bet > maxbet || odds > maxodds )
{
CCerror = strprintf("Price plan %s illegal bet %.8f: minbet %.8f maxbet %.8f or odds %d vs max.%d\n",planstr,(double)bet/COIN,(double)minbet/COIN,(double)maxbet/COIN,(int32_t)odds,(int32_t)maxodds);
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( (funding= PricesPlanFunds(cp,pricepk,pricesid)) >= 2*bet*odds+txfee )
{
if ( myIsutxo_spentinmempool(entropytxid,0) != 0 )
{
CCerror = "entropy txid is spent";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( AddNormalinputs(mtx,mypk,bet+2*txfee+odds,60) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,entropyval,pricepk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,bet,pricepk));
mtx.vout.push_back(CTxOut(txfee+odds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesOpRet('B',pricesid)));
} else fprintf(stderr,"cant find enough normal inputs for %.8f, plan funding %.8f\n",(double)bet/COIN,(double)funding/COIN);
}
if ( entropyval == 0 && funding != 0 )
CCerror = "cant find price entropy inputs";
else CCerror = "cant find price input";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
std::string PricesBetFinish(int32_t *resultp,uint64_t txfee,uint256 pricesid,uint256 bettxid)
{
*resultp = -1;
CCerror = "couldnt find bettx or entropytx";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}

View File

@@ -411,6 +411,12 @@ static const CRPCCommand vRPCCommands[] =
/* Gateways */ /* Gateways */
{ "gateways", "gatewaysaddress", &gatewaysaddress, true }, { "gateways", "gatewaysaddress", &gatewaysaddress, true },
{ "gateways", "gatewayslist", &gatewayslist, true },
{ "gateways", "gatewaysinfo", &gatewaysinfo, true },
{ "gateways", "gatewaysbind", &gatewaysbind, true },
{ "gateways", "gatewaysdeposit", &gatewaysdeposit, true },
{ "gateways", "gatewaysclaim", &gatewaysclaim, true },
{ "gateways", "gatewayswithdraw", &gatewayswithdraw, true },
/* dice */ /* dice */
{ "dice", "dicelist", &dicelist, true }, { "dice", "dicelist", &dicelist, true },

View File

@@ -236,7 +236,13 @@ extern UniValue pegsaddress(const UniValue& params, bool fHelp);
extern UniValue triggersaddress(const UniValue& params, bool fHelp); extern UniValue triggersaddress(const UniValue& params, bool fHelp);
extern UniValue paymentsaddress(const UniValue& params, bool fHelp); extern UniValue paymentsaddress(const UniValue& params, bool fHelp);
extern UniValue gatewaysaddress(const UniValue& params, bool fHelp); extern UniValue gatewaysaddress(const UniValue& params, bool fHelp);
extern UniValue channelsinfo(const UniValue& params, bool fHelp); extern UniValue gatewayslist(const UniValue& params, bool fHelp);
extern UniValue gatewaysinfo(const UniValue& params, bool fHelp);
extern UniValue gatewaysbind(const UniValue& params, bool fHelp);
extern UniValue gatewaysdeposit(const UniValue& params, bool fHelp);
extern UniValue gatewaysclaim(const UniValue& params, bool fHelp);
extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp);
extern UniValue channelsbind(const UniValue& params, bool fHelp);
extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelsopen(const UniValue& params, bool fHelp);
extern UniValue channelspayment(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp);
extern UniValue channelscollect(const UniValue& params, bool fHelp); extern UniValue channelscollect(const UniValue& params, bool fHelp);

View File

@@ -4875,6 +4875,11 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned ch
result.push_back(Pair(str,cp->unspendableCCaddr)); result.push_back(Pair(str,cp->unspendableCCaddr));
sprintf(str,"%smarker",name); sprintf(str,"%smarker",name);
result.push_back(Pair(str,cp->normaladdr)); result.push_back(Pair(str,cp->normaladdr));
if ( _GetCCaddress(destaddr,EVAL_ASSETS,pubkey2pk(pubkey)) > 0 )
{
sprintf(str,"%sCCassets",name);
result.push_back(Pair(str,destaddr));
}
if ( pubkey.size() == 33 ) if ( pubkey.size() == 33 )
{ {
if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 ) if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 )
@@ -5386,6 +5391,93 @@ UniValue rewardsinfo(const UniValue& params, bool fHelp)
return(RewardsInfo(fundingtxid)); return(RewardsInfo(fundingtxid));
} }
UniValue gatewayslist(const UniValue& params, bool fHelp)
{
if ( fHelp || params.size() > 0 )
throw runtime_error("gatewayslist\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(GatewaysList());
}
UniValue gatewaysinfo(const UniValue& params, bool fHelp)
{
uint256 txid;
if ( fHelp || params.size() != 1 )
throw runtime_error("gatewaysinfo bindtxid\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");
txid = Parseuint256((char *)params[0].get_str().c_str());
return(GatewaysInfo(txid));
}
UniValue gatewaysbind(const UniValue& params, bool fHelp)
{
uint256 tokenid; int32_t i; int64_t totalsupply; std::vector<CPubKey> pubkeys; uint8_t M,N; std::string hex,coin; std::vector<unsigned char> pubkey;
if ( fHelp || params.size() < 5 )
throw runtime_error("gatewaysbind tokenid coin tokensupply M N pubkey(s)\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());
coin = params[1].get_str();
tokensupply = atol((char *)params[2].get_str().c_str());
M = atoi((char *)params[3].get_str().c_str());
N = atoi((char *)params[4].get_str().c_str());
if ( M > N || N == 0 || N > 15 || tokensupply < COIN/100 || tokenid == zeroid )
throw runtime_error("illegal M or N > 15 or tokensupply or invalid tokenid\n");
pubkeys.resize(N);
for (i=0; i<N; i++)
{
if ( params.size() < 5+i+1 )
throw runtime_error("not enough parameters for N pubkeys\n");
pubkey = ParseHex(params[5+i].get_str().c_str());
pubkeys.push_back(pubkey2pk(pubkey));
}
hex = GatewaysBind(0,coin,tokenid,totalsupply,M,N,pubkeys);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt gatewaysbind");
return(result);
}
UniValue gatewaysdeposit(const UniValue& params, bool fHelp)
{
std::string hex;
//std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,std::vector<CPubKey>pubkeys,int32_t height,std::string refcoin,uint256 cointxid,std::string deposithex,std::vector<uint256>proof,std::vector<uint8_t> claimpubkey,int64_t amount)
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt gatewaysdeposit");
return(result);
}
UniValue gatewaysclaim(const UniValue& params, bool fHelp)
{
std::string hex;
// std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string coin,uint256 deposittxid,std::string claimaddr,int64_t amount)
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt gatewaysclaim");
return(result);
}
UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
{
std::string hex;
// std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount)
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt gatewayswithdraw");
return(result);
}
UniValue oracleslist(const UniValue& params, bool fHelp) UniValue oracleslist(const UniValue& params, bool fHelp)
{ {
if ( fHelp || params.size() > 0 ) if ( fHelp || params.size() > 0 )