Browse Source

Msig suppport

pull/4/head
jl777 6 years ago
parent
commit
7fccea1dab
  1. 2
      src/cc/CCGateways.h
  2. 149
      src/cc/dapps/oraclefeed.c
  3. 30
      src/cc/gateways.cpp
  4. 1
      src/rpcserver.cpp
  5. 1
      src/rpcserver.h
  6. 20
      src/wallet/rpcwallet.cpp

2
src/cc/CCGateways.h

@ -27,7 +27,7 @@ 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);
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin);
std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,uint256 cointxid);
UniValue GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *unspentstr);
UniValue GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *txidaddr);
// CCcustom
UniValue GatewaysInfo(uint256 bindtxid);

149
src/cc/dapps/oraclefeed.c

@ -546,6 +546,109 @@ void importaddress(char *refcoin,char *acname,char *depositaddr)
return(0);
}
cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
{
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid;
*totalp = 0;
if ( (n= cJSON_GetArraySize(unspents)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(unspents,i);
satoshis = jdouble(item,"amount") * SATOSHIDEN;
txid = jbits256(item,"txid");
v = jint(item,"vout");
if ( bits256_nonz(txid) != 0 )
{
vin = cJSON_CreateObject();
jaddbits256(vin,"txid",txid);
jaddnum(vin,"vout",v);
jadd(vins,vin);
*totalp += satoshis;
if ( (*totalp) >= required )
break;
}
}
}
return(vins);
}
char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signeraddr,char *withdrawaddr,int64_t satoshis)
{
char *retstr,*retstr2,array[128],*txstr = 0; cJSON *retjson2,*retjson,*vins,*vouts; int64_t txfee,total,change = 0;
if ( strcmp(refcoin,"BTC") == 0 )
txfee = 20000;
else txfee = 10000;
if ( satoshis < txfee )
{
printf("createmultisig satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIS);
return(0);
}
satoshis -= txfee;
sprintf(array,"[\"%s\"]",depositaddr);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"listunspent",1,99999999,array,"")) != 0 )
{
//createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...}
if ( (vins= getinputarray(&total,retjson,satoshis)) != 0 )
{
if ( total >= satoshis )
{
vouts = cJSON_CreatObject();
jaddstr(vouts,withdrawaddr,(double)satoshis/SATOSHIDEN);
if ( total > satoshis+txfee )
{
change = (total - satoshis);
jaddstr(vouts,depositaddr,(double)change/SATOSHIDEN);
}
if ( (retjson2= get_komodocli(refcoin,&txstr,acname,"createrawtransaction",jprint(vins,0),jprint(vouts,0),"","")) != 0 )
{
printf("createmultisig: unexpected JSON2.(%s)\n",jprint(retjson2,0));
free_json(retjson2);
}
else if ( txstr == 0 )
printf("createmultisig: null txstr and JSON2\n");
free_json(vins);
free_json(vouts);
}
}
}
else if ( retstr != 0 )
{
printf("createmultisig: unexpected null JSON, retstr.(%s)\n",retstr);
free(retstr);
}
else printf("createmultisig: null retstr and JSON\n");
return(txstr);
}
cJSON *addmultisignature(char *refcoin,char *acname,char *signeraddr,char *rawtx)
{
char *retstr,*hexstr; cJSON *retjson;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"signrawtransaction",rawtx,"","","")) != 0 )
{
if ( jint(retjson,"complete") != 0 )
return(retjson);
else if ( (hexstr= jstr(retjson,"hex")) != 0 && strlen(hexstr) > strlen(rawtx) )
{
jadd(retjson,"partialtx",1)'
return(retjson);
}
free_json(retjson);
}
return(0);
}
char *get_gatewaysmultisig(char *refcoin,char *acname,char *bindtxidstr,char *withtxidstr,char *txidaddr)
{
char *retstr,*hexstr,*hex=0; cJSON *retjson;
if ( (retjson= get_komodocli("KMD",&retstr,acname,"gatewaysmultisig",bindtxidstr,refcoin,withtxidstr,txidstr)) != 0 )
{
if ( (hexstr= jstr(retjson,"hex")) != 0 )
hex = clonestr(hexstr);
free_json(retjson);
}
return(hex);
}
void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin,bits256 cointxid)
{
@ -661,7 +764,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
/// 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,*clijson; char str[65],*unspentstr,*coinstr,*txidaddr,*signeraddr,*depositaddr,*withdrawaddr; int32_t i,j,n,retval,processed = 0; bits256 txid,cointxid,origtxid,zeroid; int64_t satoshis;
cJSON *retjson,*pending,*item,*clijson; char str[65],*rawtx,*coinstr,*txidaddr,*signeraddr,*depositaddr,*withdrawaddr; int32_t i,j,n,retval,processed = 0; bits256 txid,cointxid,origtxid,zeroid; int64_t satoshis;
memset(&zeroid,0,sizeof(zeroid));
if ( (retjson= get_gatewayspending("KMD",acname,bindtxidstr)) != 0 )
{
@ -699,32 +802,38 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
fprintf(stderr,"ERROR withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
}
}
else if ( (unspentstr= get_listunspent(refcoin,"",depositaddr)) != 0 )
else
{
if ( (clijson= get_komodocli("KMD",&retstr2,acname,"gatewaysmultisig",bindtxidstr,bits256_str(str,origtxid),unspentstr)) != 0 )
if ( (rawtx= get_gatewaysmultisig(refcoin,acname,bindtxidstr,bits256_str(str,origtxid),txidaddr)) == 0 )
{
if ( jint(clijson,"complete") != 0 )
rawtx = createmultisig(refcoin,"",depositaddr,signeraddr,withdrawaddr,satoshis);
}
if ( rawtx != 0 )
{
if ( (clijson= addmultisignature(refcoin,"",signeraddr,rawtx)) != 0 )
{
cointxid = komodobroadcast(refcoin,"",clijson2);
if ( bits256_nonz(cointxid) != 0 )
if ( jint(clijson,"complete") != 0 )
{
fprintf(stderr,"withdraw %s M.%d N.%d %s %s %.8f processed\n",refcoin,M,N,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid);
processed++;
cointxid = komodobroadcast(refcoin,"",clijson);
if ( bits256_nonz(cointxid) != 0 )
{
fprintf(stderr,"withdraw %s M.%d N.%d %s %s %.8f processed\n",refcoin,M,N,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid);
}
}
else if ( jint(clijson,"partialtx") != 0 )
{
// 10000 + ith -> txidaddr
txid = komodobroadcast("KMD",acname,clijson);
fprintf(stderr,"%s M.%d of N.%d partialtx %s sent\n",refcoin,M,N,bits256_str(str,txid));
}
free_json(clijson);
}
else if ( jint(clijson,"partialtx") != 0 )
{
// 10000 + ith -> txidaddr
txid = komodobroadcast("KMD",acname,clijson2);
fprintf(stderr,"%s M.%d of N.%d partialtx %s sent\n",refcoin,M,N,bits256_str(str,txid));
processed++;
}
free_json(clijson);
}
free(unspentstr);
processed++;
free(rawtx);
} else fprintf(stderr,"couldnt create msig rawtx\n");
}
} else fprintf(stderr,"error sending %s txidaddr.%s -> %s exists.%d\n",acname,txidaddr,bits256_str(str,txid),coinaddrexists(refcoin,acname,txidaddr));
}
}
else if ( retval > 0 )
{

30
src/cc/gateways.cpp

@ -837,23 +837,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
return(result);
}
std::string GatewaysMultisigUpdate(struct CCcontract_info *cp,int32_t &complete,int32_t &partialtx,CPubKey mypk,int32_t ith,uint256 withdrawtxid,uint8_t M,uint8_t N,char *unspentstr)
{
CMutableTransaction mtx; cJSON *unspents; std::string hex,rawtx; CScript opret; uint64_t txfee = 10000;
complete = partialtx = 0;
{
// iterate txidaddr, extract signatures!
// iterate for sigs depth and find the deepest
// if not already a signer, add signature and post to next
// if first one, then create a rawtx and sign it, ie. depth 1
// if fully signed, broadcast
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
}
return(hex);
}
UniValue GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *unspentstr)
std::string GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *txidaddr)
{
UniValue result(UniValue::VOBJ); std::string coin,hex; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CPubKey Gatewayspk,mypk; struct CCcontract_info *cp,C; int32_t i,n,complete,partialtx; int64_t totalsupply;
cp = CCinit(&C,EVAL_GATEWAYS);
@ -868,22 +852,16 @@ UniValue GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,ui
depositaddr[0] = 0;
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 > 1 && coin == refcoin )
{
// need a decentralized way to add signatures to msig tx
n = pubkeys.size();
for (i=0; i<n; i++)
if ( mypk == pubkeys[i] )
break;
if ( i != n )
{
hex = GatewaysMultisigUpdate(cp,complete,partialtx,mypk,i,withdrawtxid,M,N,unspentstr);
hex = "";
} else fprintf(stderr,"not one of the multisig signers\n");
}
}
// complete:1 -> send tx to refcoin withdraw complete
// partialtx:1 -> send partialsig to txidaddr, satoshis 10000 + ith pubkey + 1
result.push_back(Pair("result","success"));
result.push_back(Pair("coin",refcoin));
result.push_back(Pair("complete",complete));
result.push_back(Pair("partialtx",partialtx));
result.push_back(Pair("hex",hex));
return(result);
return(hex);
}

1
src/rpcserver.cpp

@ -418,6 +418,7 @@ static const CRPCCommand vRPCCommands[] =
{ "gateways", "gatewaysclaim", &gatewaysclaim, true },
{ "gateways", "gatewayswithdraw", &gatewayswithdraw, true },
{ "gateways", "gatewayspending", &gatewayspending, true },
{ "gateways", "gatewaysmultisig", &gatewaysmultisig, true },
{ "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true },
/* dice */

1
src/rpcserver.h

@ -244,6 +244,7 @@ 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 gatewaysmultisig(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);

20
src/wallet/rpcwallet.cpp

@ -5543,6 +5543,26 @@ UniValue gatewayspending(const UniValue& params, bool fHelp)
return(GatewaysPendingWithdraws(bindtxid,coin));
}
UniValue gatewaysmultisig(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); uint256 bindtxid,withtxid; std::string coin,hex; char *txidaddr;
if ( fHelp || params.size() != 2 )
throw runtime_error("gatewaysmultisig bindtxid coin withtxid txidaddr\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();
withtxid = Parseuint256((char *)params[2].get_str().c_str());
txidaddr = params[3].get_str().c_str();
hex = GatewaysMultisig(0,coin,bindtxid,withdrawtxid,txidaddr);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex",hex));
} else ERR_RESULT("couldnt gatewaysmultisig");
return(result);
}
UniValue oracleslist(const UniValue& params, bool fHelp)
{
if ( fHelp || params.size() > 0 )

Loading…
Cancel
Save