@@ -25,6 +25,8 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
|
||||
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
|
||||
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
|
||||
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount);
|
||||
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin);
|
||||
std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid);
|
||||
|
||||
// CCcustom
|
||||
UniValue GatewaysInfo(uint256 bindtxid);
|
||||
|
||||
@@ -310,7 +310,8 @@ uint64_t get_btcusd()
|
||||
|
||||
cJSON *get_komodocli(char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2)
|
||||
{
|
||||
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,*fname = "/tmp/komodocli";
|
||||
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[256];
|
||||
sprintf(fname,"/tmp/oraclefeed.%s",method);
|
||||
if ( acname[0] != 0 )
|
||||
sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,fname);
|
||||
else sprintf(cmdstr,"./komodo-cli %s %s %s %s > %s\n",method,arg0,arg1,arg2,fname);
|
||||
@@ -344,13 +345,36 @@ bits256 komodobroadcast(char *acname,cJSON *hexjson)
|
||||
retstr[64] = 0;
|
||||
decode_hex(txid.bytes,32,retstr);
|
||||
}
|
||||
fprintf(stderr,"txid.(%s)\n",bits256_str(str,txid));
|
||||
fprintf(stderr,"broadcast %s txid.(%s)\n",acname,bits256_str(str,txid));
|
||||
free(retstr);
|
||||
}
|
||||
}
|
||||
return(txid);
|
||||
}
|
||||
|
||||
bits256 sendtoaddress(char *acname,char *destaddr,int64_t satoshis)
|
||||
{
|
||||
char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid;
|
||||
memset(txid.bytes,0,sizeof(txid));
|
||||
sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN);
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"sendtoaddress",destaddr,numstr,"")) != 0 )
|
||||
{
|
||||
fprintf(stderr,"unexpected sendrawtransaction json.(%s)\n",jprint(retjson,0));
|
||||
free_json(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
if ( strlen(retstr) >= 64 )
|
||||
{
|
||||
retstr[64] = 0;
|
||||
decode_hex(txid.bytes,32,retstr);
|
||||
}
|
||||
fprintf(stderr,"sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid));
|
||||
free(retstr);
|
||||
}
|
||||
return(txid);
|
||||
}
|
||||
|
||||
int32_t get_KMDheight(char *acname)
|
||||
{
|
||||
cJSON *retjson; char *retstr; int32_t height=0;
|
||||
@@ -430,6 +454,206 @@ int32_t get_KMDheader(bits256 *blockhashp,bits256 *merklerootp,int32_t prevheigh
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_gatewayspending(char *acname,char *oraclestxidstr,char *coin)
|
||||
{
|
||||
cJSON *retjson; char *retstr;
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"gatewayspending",oraclestxidstr,coin,"")) != 0 )
|
||||
{
|
||||
//printf("pending.(%s)\n",jprint(retjson,0));
|
||||
return(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
fprintf(stderr,"get_gatewayspending.(%s) error.(%s)\n",acname,retstr);
|
||||
free(retstr);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_rawmempool(char *acname)
|
||||
{
|
||||
cJSON *retjson; char *retstr;
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"getrawmempool","","","")) != 0 )
|
||||
{
|
||||
//printf("mempool.(%s)\n",jprint(retjson,0));
|
||||
return(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
fprintf(stderr,"get_rawmempool.(%s) error.(%s)\n",acname,retstr);
|
||||
free(retstr);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_addressutxos(char *acname,char *coinaddr)
|
||||
{
|
||||
cJSON *retjson; char *retstr,jsonbuf[256];
|
||||
sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr);
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"getaddressutxos",jsonbuf,"","")) != 0 )
|
||||
{
|
||||
//printf("addressutxos.(%s)\n",jprint(retjson,0));
|
||||
return(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
fprintf(stderr,"get_addressutxos.(%s) error.(%s)\n",acname,retstr);
|
||||
free(retstr);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_rawtransaction(char *acname,bits256 txid)
|
||||
{
|
||||
cJSON *retjson; char *retstr,str[65];
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"getrawtransaction",bits256_str(str,txid),"1","")) != 0 )
|
||||
{
|
||||
return(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
fprintf(stderr,"get_rawtransaction.(%s) error.(%s)\n",acname,retstr);
|
||||
free(retstr);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void gatewaysmarkdone(char *acname,bits256 txid)
|
||||
{
|
||||
char str[65],*retstr; cJSON *retjson;
|
||||
printf("spend %s %s/v2 as marker\n",acname,bits256_str(str,txid));
|
||||
if ( (retjson= get_komodocli(&retstr,acname,"gatewaysmarkdone",bits256_str(str,txid),"","")) != 0 )
|
||||
{
|
||||
komodobroadcast(acname,retjson);
|
||||
free_json(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
printf("error parsing gatewaysmarkdone.(%s)\n",retstr);
|
||||
free(retstr);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tx_has_voutaddress(char *acname,bits256 txid,char *coinaddr)
|
||||
{
|
||||
cJSON *txobj,*vouts,*vout,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numvouts,retval = 0;
|
||||
if ( (txobj= get_rawtransaction(acname,txid)) != 0 )
|
||||
{
|
||||
if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 )
|
||||
{
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
vout = jitem(vouts,i);
|
||||
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
|
||||
{
|
||||
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 )
|
||||
{
|
||||
for (j=0; j<n; j++)
|
||||
{
|
||||
addr = jstri(addresses,j);
|
||||
if ( strcmp(addr,coinaddr) == 0 )
|
||||
{
|
||||
//fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free_json(txobj);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
int32_t coinaddrexists(char *acname,char *coinaddr)
|
||||
{
|
||||
cJSON *array; bits256 txid; int32_t i,n,num=0;
|
||||
if ( (array= get_addressutxos(acname,coinaddr)) != 0 )
|
||||
{
|
||||
num = cJSON_GetArraySize(array);
|
||||
free_json(array);
|
||||
} else return(-1);
|
||||
if ( num == 0 )
|
||||
{
|
||||
if ( (array= get_rawmempool(acname)) != 0 )
|
||||
{
|
||||
if ( (n= cJSON_GetArraySize(array)) != 0 )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
txid = jbits256i(array,i);
|
||||
if ( tx_has_voutaddress(acname,txid,coinaddr) > 0 )
|
||||
{
|
||||
num = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free_json(array);
|
||||
} else return(-1);
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
void update_gatewayspending(char *acname,char *oraclestxidstr,char *coin)
|
||||
{
|
||||
// check queue to prevent duplicate
|
||||
// check KMD chain and mempool for txidaddr
|
||||
// if txidaddr exists properly, spend the marker (txid.2)
|
||||
// create withdraw tx and sign it
|
||||
/// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2)
|
||||
/// if not enough sigs, post partially signed to acname with marker2
|
||||
// monitor marker2, for the partially signed withdraws
|
||||
cJSON *retjson,*pending,*item; char str[65],*coinstr,*txidaddr,*signeraddr,*withdrawaddr; int32_t i,n,retval,processed = 0; bits256 txid,withtxid,origtxid; int64_t satoshis;
|
||||
if ( (retjson= get_gatewayspending(acname,oraclestxidstr,coin)) != 0 )
|
||||
{
|
||||
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,coin) == 0 )
|
||||
{
|
||||
if ( (pending= jarray(&n,retjson,"pending")) != 0 )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if ( processed != 0 ) // avoid out of utxo conditions
|
||||
break;
|
||||
item = jitem(pending,i);
|
||||
origtxid = jbits256(item,"txid");
|
||||
//process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"}
|
||||
if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 )
|
||||
{
|
||||
if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && (retval= coinaddrexists(acname,txidaddr)) == 0 )
|
||||
{
|
||||
// this is less errors but more expensive: ./komodo-cli z_sendmany "signeraddr" '[{"address":"<txidaddr>","amount":0.0001},{"address":"<withdrawaddr>","amount":<withamount>}]'
|
||||
txid = sendtoaddress(acname,txidaddr,10000);
|
||||
if ( bits256_nonz(txid) != 0 && coinaddrexists(acname,txidaddr) > 0 )
|
||||
{
|
||||
// the actual withdraw
|
||||
withtxid = sendtoaddress(strcmp("KMD",coin)==0?"":coin,withdrawaddr,satoshis);
|
||||
if ( bits256_nonz(withtxid) != 0 )
|
||||
{
|
||||
fprintf(stderr,"withdraw %s %s %s %.8f processed\n",coin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
|
||||
gatewaysmarkdone(acname,origtxid);
|
||||
processed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"ERROR withdraw %s %s %s %.8f processed\n",coin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
|
||||
}
|
||||
} else fprintf(stderr,"error sending %s txidaddr.%s -> %s exists.%d\n",acname,txidaddr,bits256_str(str,txid),coinaddrexists(acname,txidaddr));
|
||||
}
|
||||
else if ( retval > 0 )
|
||||
{
|
||||
fprintf(stderr,"already did withdraw %s %s %.8f processed\n",coin,withdrawaddr,(double)satoshis/SATOSHIDEN);
|
||||
gatewaysmarkdone(acname,origtxid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free_json(retjson);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t get_oracledata(int32_t prevheight,char *hexstr,int32_t maxsize,char *format)
|
||||
{
|
||||
int32_t i; uint32_t height; uint64_t price; bits256 blockhash,merkleroot;
|
||||
@@ -483,22 +707,21 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034
|
||||
|
||||
*/
|
||||
|
||||
//#define ORACLETXID "4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3"
|
||||
//#define MYPUBKEY "02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92"
|
||||
//#define ACNAME "ORCL"
|
||||
// ./a.out AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e
|
||||
|
||||
int32_t main(int32_t argc,char **argv)
|
||||
{
|
||||
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,n,height,prevheight = 0; char *format,*acname,*oraclestr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096]; uint64_t price; bits256 txid;
|
||||
if ( argc != 5 )
|
||||
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,n,height,prevheight = 0; char *format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096]; uint64_t price; bits256 txid;
|
||||
if ( argc != 6 )
|
||||
{
|
||||
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT\nPowered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
|
||||
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID\nPowered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
|
||||
return(-1);
|
||||
}
|
||||
acname = argv[1];
|
||||
oraclestr = argv[2];
|
||||
pkstr = argv[3];
|
||||
format = argv[4];
|
||||
bindtxidstr = argv[5];
|
||||
if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' )
|
||||
{
|
||||
printf("only formats of L and Ihh are supported now\n");
|
||||
@@ -528,6 +751,7 @@ int32_t main(int32_t argc,char **argv)
|
||||
prevheight = height;
|
||||
acheight = get_KMDheight(acname);
|
||||
printf("ht.%d <- %s\n",height,hexstr);
|
||||
update_gatewayspending(acname,bindtxidstr,"KMD");
|
||||
}
|
||||
free_json(clijson2);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#include "CCGateways.h"
|
||||
|
||||
/*
|
||||
prevent duplicate bindtxid and cointxid via mempool scan
|
||||
|
||||
prevent duplicate bindtxid via mempool scan
|
||||
wait for notarization for oraclefeed and validation of gatewaysdeposit
|
||||
|
||||
validation
|
||||
|
||||
string oracles
|
||||
*/
|
||||
|
||||
@@ -112,8 +115,30 @@ string oracles
|
||||
|
||||
gatewaysclaim bindtxid coin deposittxid destpub amount
|
||||
./c gatewaysclaim e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999
|
||||
|
||||
now the asset is in the pubkey's asset address!
|
||||
it can be used, traded freely and any node who has the asset can do a gatewayswithdraw
|
||||
|
||||
gatewayswithdraw bindtxid coin withdrawpub amount
|
||||
./c gatewayswithdraw e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828 1
|
||||
ef3cc452da006eb2edda6b6ed3d3347664be51260f3e91f59ec44ec9701367f0
|
||||
|
||||
Now there is a withdraw pending, so it needs to be processed by the signing nodes on the KMD side
|
||||
|
||||
gatewayspending bindtxid coin
|
||||
gatewayspending will display all pending withdraws and if it is done on one of the msigpubkeys, then it will queue it for processing
|
||||
./c gatewayspending e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int32_t GatewaysAddQueue(std::string coin,uint256 txid,CScript scriptPubKey,int64_t nValue)
|
||||
{
|
||||
char destaddr[64],str[65];
|
||||
Getscriptaddress(destaddr,scriptPubKey);
|
||||
fprintf(stderr,"GatewaysAddQueue: %s %s %s %.8f\n",coin.c_str(),uint256_str(str,txid),destaddr,(double)nValue/COIN);
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -308,18 +333,40 @@ int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr)
|
||||
{
|
||||
int32_t i,n; char destaddr[64];
|
||||
BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx)
|
||||
{
|
||||
const CTransaction &tx = e.GetTx();
|
||||
if ( (n= tx.vout.size()) > 0 )
|
||||
{
|
||||
const uint256 &txid = tx.GetHash();
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
|
||||
if ( strcmp(destaddr,coinaddr) == 0 )
|
||||
{
|
||||
fprintf(stderr,"found (%s) vout in mempool\n",coinaddr);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t GatewaysCointxidExists(struct CCcontract_info *cp,uint256 cointxid) // dont forget to check mempool!
|
||||
{
|
||||
char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
CCtxidaddr(txidaddr,cointxid);
|
||||
fprintf(stderr," txidaddr.(%s) need to scan mempool also\n",txidaddr);
|
||||
SetCCtxids(addressIndex,txidaddr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
return(myIs_coinaddr_inmempoolvout(txidaddr));
|
||||
}
|
||||
|
||||
UniValue GatewaysInfo(uint256 bindtxid)
|
||||
@@ -675,13 +722,18 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
|
||||
|
||||
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,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65];
|
||||
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64];
|
||||
cp = CCinit(&C,EVAL_GATEWAYS);
|
||||
assetscp = CCinit(&C2,EVAL_ASSETS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
_GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk);
|
||||
CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr);
|
||||
Myprivkey(mypriv);
|
||||
_GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
|
||||
CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
|
||||
@@ -692,16 +744,17 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
|
||||
fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 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));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << withdrawpub << OP_CHECKSIG));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG));
|
||||
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(0,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
|
||||
}
|
||||
}
|
||||
@@ -709,6 +762,77 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
|
||||
return("");
|
||||
}
|
||||
|
||||
// withdrawtxid used on external chain to create baton address, its existence in mempool (along with the withdraw) proof that the withdraw is pending
|
||||
std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid)
|
||||
{
|
||||
CMutableTransaction mtx; CScript opret; CPubKey mypk; struct CCcontract_info *cp,C;
|
||||
cp = CCinit(&C,EVAL_GATEWAYS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 5000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
mtx.vin.push_back(CTxIn(withdrawtxid,2,CScript()));
|
||||
mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
|
||||
}
|
||||
|
||||
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ),pending(UniValue::VARR),obj(UniValue::VOBJ); CTransaction tx; std::string coin; CPubKey mypk,gatewayspk; std::vector<CPubKey> msigpubkeys; uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; char depositaddr[64],withmarker[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],signeraddr[64]; int32_t i,n,numvouts,vout,numqueued,queueflag; int64_t totalsupply; struct CCcontract_info *cp,C;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
cp = CCinit(&C,EVAL_GATEWAYS);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
_GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
|
||||
return(result);
|
||||
}
|
||||
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.c_str());
|
||||
return(result);
|
||||
}
|
||||
n = msigpubkeys.size();
|
||||
queueflag = 0;
|
||||
for (i=0; i<n; i++)
|
||||
if ( msigpubkeys[i] == mypk )
|
||||
{
|
||||
queueflag = 1;
|
||||
break;
|
||||
}
|
||||
Getscriptaddress(withmarker,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG);
|
||||
SetCCunspents(unspentOutputs,withmarker);
|
||||
numqueued = 0;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( GetTransaction(txid,tx,hashBlock,false) != 0 )
|
||||
{
|
||||
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
|
||||
Getscriptaddress(withaddr,tx.vout[1].scriptPubKey);
|
||||
if ( strcmp(destaddr,coinaddr) == 0 )
|
||||
{
|
||||
obj.push_back(Pair("txid",uint256_str(str,txid)));
|
||||
CCtxidaddr(txidaddr,txid);
|
||||
obj.push_back(Pair("txidaddr",txidaddr));
|
||||
obj.push_back(Pair("withdrawaddr",withaddr));
|
||||
sprintf(numstr,"%.8f",(double)tx.vout[0].nValue/COIN);
|
||||
obj.push_back(Pair("amount",numstr));
|
||||
if ( queueflag != 0 )
|
||||
{
|
||||
obj.push_back(Pair("depositaddr",depositaddr));
|
||||
Getscriptaddress(signeraddr,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG);
|
||||
obj.push_back(Pair("signeraddr",signeraddr));
|
||||
// numqueued += GatewaysAddQueue(refcoin,txid,tx.vout[1].scriptPubKey,tx.vout[0].nValue);
|
||||
}
|
||||
pending.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("coin",refcoin));
|
||||
result.push_back(Pair("pending",pending));
|
||||
result.push_back(Pair("queueflag",queueflag));
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -417,6 +417,8 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "gateways", "gatewaysdeposit", &gatewaysdeposit, true },
|
||||
{ "gateways", "gatewaysclaim", &gatewaysclaim, true },
|
||||
{ "gateways", "gatewayswithdraw", &gatewayswithdraw, true },
|
||||
{ "gateways", "gatewayspending", &gatewayspending, true },
|
||||
{ "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true },
|
||||
|
||||
/* dice */
|
||||
{ "dice", "dicelist", &dicelist, true },
|
||||
|
||||
@@ -242,6 +242,8 @@ 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 gatewayspending(const UniValue& params, bool fHelp);
|
||||
extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelsinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelsbind(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelsopen(const UniValue& params, bool fHelp);
|
||||
|
||||
@@ -5462,13 +5462,6 @@ UniValue gatewaysdeposit(const UniValue& params, bool fHelp)
|
||||
amount = atof((char *)params[8].get_str().c_str()) * COIN;
|
||||
if ( amount <= 0 || claimvout < 0 )
|
||||
throw runtime_error("invalid param: amount, numpks or claimvout\n");
|
||||
/*for (i=0; i<numpks; i++)
|
||||
{
|
||||
if ( params.size() < 10+i+1 )
|
||||
throw runtime_error("not enough parameters for numpks oraclepubkeys\n");
|
||||
pubkey = ParseHex(params[10+i].get_str().c_str());
|
||||
pubkeys.push_back(pubkey2pk(pubkey));
|
||||
}*/
|
||||
hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
@@ -5482,7 +5475,7 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); std::string hex,coin; uint256 bindtxid,deposittxid; std::vector<uint8_t>destpub; int64_t amount;
|
||||
if ( fHelp || params.size() != 5 )
|
||||
throw runtime_error("gatewaysclaim bindtxid coin deposittxid redeemscript amount\n");
|
||||
throw runtime_error("gatewaysclaim bindtxid coin deposittxid destpub 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");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
@@ -5501,8 +5494,16 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp)
|
||||
|
||||
UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); std::string hex;
|
||||
// std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount)
|
||||
UniValue result(UniValue::VOBJ); uint256 bindtxid; int64_t amount; std::string hex,coin; std::vector<uint8_t> withdrawpub;
|
||||
if ( fHelp || params.size() != 4 )
|
||||
throw runtime_error("gatewayswithdraw bindtxid coin withdrawpub 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");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
withdrawpub = ParseHex(params[2].get_str());
|
||||
amount = atof((char *)params[3].get_str().c_str()) * COIN;
|
||||
hex = GatewaysWithdraw(0,bindtxid,coin,withdrawpub,amount);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
@@ -5511,6 +5512,35 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue gatewaysmarkdone(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint256 withdrawtxid; std::string hex;
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("gatewaysmarkdone withdrawtxid\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");
|
||||
withdrawtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
hex = GatewaysMarkdone(0,withdrawtxid);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt gatewaysmarkdone");
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue gatewayspending(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid; std::string coin;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("gatewayspending bindtxid coin\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");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
return(GatewaysPendingWithdraws(bindtxid,coin));
|
||||
}
|
||||
|
||||
UniValue oracleslist(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if ( fHelp || params.size() > 0 )
|
||||
|
||||
Reference in New Issue
Block a user