Browse Source

Channels adaptation to TokensCC (#3)

* Initial changes

* ChannelsCC adaptation

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix
pull/4/head
Mihailo Milenkovic 5 years ago
committed by dimxy
parent
commit
e23073fff5
  1. 2
      src/cc/CCchannels.h
  2. 3
      src/cc/CCinclude.h
  3. 8
      src/cc/CCtokens.cpp
  4. 349
      src/cc/channels.cpp
  5. 15
      src/wallet/rpcwallet.cpp

2
src/cc/CCchannels.h

@ -21,7 +21,7 @@
#define CHANNELS_MAXPAYMENTS 1000
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment);
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 tokenid);
std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret);
std::string ChannelClose(uint64_t txfee,uint256 opentxid);
std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid);

3
src/cc/CCinclude.h

@ -59,6 +59,9 @@ extern std::string CCerror;
#define CC_MAXVINS 1024
#define SMALLVAL 0.000000000000001
#define SATOSHIDEN ((uint64_t)100000000L)
#define dstr(x) ((double)(x) / SATOSHIDEN)
#ifndef _BITS256
#define _BITS256
union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; };

8
src/cc/CCtokens.cpp

@ -714,10 +714,10 @@ int64_t GetTokenBalance(CPubKey pk, uint256 tokenid)
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tokentx;
CCerror = strprintf("obsolete, cannot return correct value without eval");
return 0;
// CCerror = strprintf("obsolete, cannot return correct value without eval");
// return 0;
/* if (GetTransaction(tokenid, tokentx, hashBlock, false) == 0)
if (GetTransaction(tokenid, tokentx, hashBlock, false) == 0)
{
fprintf(stderr, "cant find tokenid\n");
CCerror = strprintf("cant find tokenid");
@ -726,7 +726,7 @@ int64_t GetTokenBalance(CPubKey pk, uint256 tokenid)
struct CCcontract_info *cp, C;
cp = CCinit(&C, EVAL_TOKENS);
return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0)); */
return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0));
}
UniValue TokenInfo(uint256 tokenid)

349
src/cc/channels.cpp

@ -64,15 +64,16 @@ Possible third iteration:
int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v)
{
char destaddr[65],channeladdr[65];
char destaddr[65],channeladdr[65],tokenschanneladdr[65];
GetCCaddress1of2(cp,channeladdr,srcpub,destpub);
GetTokensCCaddress1of2(cp,tokenschanneladdr,srcpub,destpub);
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,channeladdr) == 0 )
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && (strcmp(destaddr,channeladdr) == 0 || strcmp(destaddr,tokenschanneladdr) == 0))
return(tx.vout[v].nValue);
}
return(0);
return(0);
}
int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey pubkey,int32_t v)
@ -88,17 +89,31 @@ int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,C
return(0);
}
CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain)
CScript EncodeChannelsOpRet(uint8_t funcid,uint256 tokenid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain)
{
CScript opret; uint8_t evalcode = EVAL_CHANNELS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain);
if (tokenid!=zeroid)
{
std::vector<CPubKey> pks;
pks.push_back(srcpub);
pks.push_back(destpub);
return(EncodeTokenOpRet(tokenid,pks,opret));
}
return(opret);
}
uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain)
uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey, uint256 &tokenid, uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
std::vector<uint8_t> vopret; uint8_t *script,e,f,tokenevalcode;
std::vector<CPubKey> pubkeys; std::vector<uint8_t> vOpretExtra;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
if (!E_UNMARSHAL(vOpretExtra, { ss >> vopret; })) return (0);
}
else GetOpReturnData(scriptPubKey, vopret);
if ( vopret.size() > 2 )
{
script = (uint8_t *)vopret.data();
@ -115,46 +130,56 @@ uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubK
bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
{
static uint256 zerohash;
uint256 txid,param3;
uint256 txid,param3,tokenid;
CPubKey srcpub,destpub;
int32_t param1; int64_t param2; uint8_t funcid;
CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
numvins = tx.vin.size();
numvouts = tx.vout.size();
int32_t param1,numvouts; int64_t param2; uint8_t funcid;
CTransaction vinTx; uint256 hashBlock; int64_t inputs=0,outputs=0;
if ((numvouts=tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)!=0)
{
for (i=0; i<numvins; i++)
if ((numvouts=tx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3))!=0)
{
switch (funcid)
{
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
else
{
inputs += vinTx.vout[tx.vin[i].prevout.n].nValue;
}
case 'O':
return (true);
case 'P':
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
outputs = tx.vout[0].nValue + tx.vout[3].nValue;
break;
case 'C':
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
outputs = tx.vout[0].nValue;
break;
case 'R':
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
outputs = tx.vout[2].nValue;
break;
default:
return (false);
}
if ( inputs != outputs )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("mismatched inputs != outputs");
}
else return (true);
}
else
{
return eval->Invalid("invalid op_return data");
}
for (i=0; i<numvouts; i++)
{
outputs += tx.vout[i].nValue;
}
if ( inputs != outputs+txfee )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("mismatched inputs != outputs + txfee");
}
else return(true);
return(false);
}
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,p1,param1; bool retval;
uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain;
uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain,tokenid;
uint8_t funcid,hash[32],hashdest[32];
int64_t p2,param2,payment;
CPubKey srcpub, destpub;
@ -169,15 +194,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
{
if (ChannelsExactAmounts(cp,eval,tx,1,10000) == false )
{
fprintf(stderr,"Channelsget invalid amount\n");
return false;
return eval->Invalid("invalid channel inputs vs. outputs!");
}
else
{
txid = tx.GetHash();
memcpy(hash,&txid,sizeof(hash));
if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, srcpub, destpub, param1, param2, param3)) != 0)
if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, opentxid, srcpub, destpub, param1, param2, param3)) != 0)
{
switch ( funcid )
{
@ -213,9 +236,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)!");
else if ( IsChannelsMarkervout(cp,tx,destpub,2)==0 )
return eval->Invalid("vout.2 is CC for channelPayment (marker to dstPub)!");
else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 )
else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() == 0 )
return eval->Invalid("vout.3 is CC for channelPayment!");
else if ( tokenid==zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("vout.3 is normal for channelPayment!");
else if ( tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)
else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[3].nValue,destpub).scriptPubKey)
return eval->Invalid("payment funds do not go to receiver!");
else if ( tokenid==zeroid && tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)
return eval->Invalid("payment funds do not go to receiver!");
else if ( param1 > CHANNELS_MAXPAYMENTS)
return eval->Invalid("too many payment increments!");
@ -223,7 +250,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
{
if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0)
{
if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O')
if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O')
return eval->Invalid("invalid channelopen OP_RETURN data!");
endiancpy(hash, (uint8_t * ) & param3, 32);
for (i = 0; i < numpayments-param1; i++)
@ -239,7 +266,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
}
if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
{
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey)
return eval->Invalid("invalid destination for sender marker!");
@ -279,13 +306,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("too many payment increments!");
else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
return eval->Invalid("invalid open txid!");
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
return eval->Invalid("invalid channelopen OP_RETURN data!");
else if (tx.vout[0].nValue != param1*payment)
return eval->Invalid("vout amount does not match number_of_payments*payment!");
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
{
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey)
return eval->Invalid("invalid destination for sender marker!");
@ -318,19 +345,23 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("vout.0 is CC for channelRefund (marker to srcPub)!");
else if ( IsChannelsMarkervout(cp,tx,destpub,1)==0 )
return eval->Invalid("vout.1 is CC for channelRefund (marker to dstPub)!");
else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("vout.2 is normal for channelRefund!");
else if ( tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG)
else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 )
return eval->Invalid("vout.2 is CC for channelPayment!");
else if ( tokenid==zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("vout.2 is normal for channelPayment!");
else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[2].nValue,srcpub).scriptPubKey)
return eval->Invalid("payment funds do not go to sender!");
else if ( tokenid==zeroid && tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG)
return eval->Invalid("payment funds do not go to sender!");
else if ( param1 > CHANNELS_MAXPAYMENTS)
return eval->Invalid("too many payment increments!");
else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
return eval->Invalid("invalid open txid!");
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
return eval->Invalid("invalid channelopen OP_RETURN data!");
else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0)
return eval->Invalid("invalid close txid!");
else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C')
else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C')
return eval->Invalid("invalid channelclose OP_RETURN data!");
else if (tmp_txid!=opentxid)
return eval->Invalid("invalid close tx, opentxid do not match on close and refund!");
@ -338,7 +369,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
return eval->Invalid("vout amount does not match number_of_payments*payment!");
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
{
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
return eval->Invalid("invalid previous tx OP_RETURN data!");
else if (tx.vout[0].scriptPubKey != prevTx.vout[1].scriptPubKey)
return eval->Invalid("invalid destination for sender marker!");
@ -351,9 +382,9 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
default:
fprintf(stderr,"illegal channels funcid.(%c)\n",funcid);
return eval->Invalid("unexpected channels funcid");
break;
}
} else return eval->Invalid("unexpected channels missing funcid");
}
else return eval->Invalid("unexpected channels missing funcid");
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 )
fprintf(stderr,"Channel tx validated\n");
@ -368,14 +399,15 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid, CPubKey mypk)
{
char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t marker,param1;
char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3,tokenid; CTransaction tx; int32_t marker,param1;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CPubKey srcpub,destpub;
uint8_t myprivkey[32];
if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O')
if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)=='O')
{
GetCCaddress1of2(cp,coinaddr,srcpub,destpub);
if (tokenid!=zeroid) GetTokensCCaddress1of2(cp,coinaddr,srcpub,destpub);
else GetCCaddress1of2(cp,coinaddr,srcpub,destpub);
SetCCunspents(unspentOutputs,coinaddr);
}
else
@ -389,7 +421,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
{
if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0)
{
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 &&
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 &&
(tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) &&
(totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsMarkervout(cp,tx,srcpub,marker))>0)
{
@ -407,7 +439,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
const CTransaction &txmempool = e.GetTx();
const uint256 &hash = txmempool.GetHash();
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 &&
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 &&
tmp_txid==openTx.GetHash() && param1 < mindepth)
{
txid=hash;
@ -421,19 +453,19 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
prevtxid=txid;
mtx.vin.push_back(CTxIn(txid,0,CScript()));
mtx.vin.push_back(CTxIn(txid,marker,CScript()));
Myprivkey(myprivkey);
CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr);
CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr);
Myprivkey(myprivkey);
if (tokenid!=zeroid) CCaddrTokens1of2set(cp,srcpub,destpub,coinaddr);
else CCaddr1of2set(cp,srcpub,destpub,coinaddr);
return totalinputs;
}
else return 0;
}
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment)
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment, uint256 tokenid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy;
CPubKey mypk; struct CCcontract_info *cp,C;
uint8_t hash[32],hashdest[32]; uint64_t amount,tokens=0,funds; int32_t i; uint256 hashchain,entropy,hentropy;
CPubKey mypk; struct CCcontract_info *cp,*cpTokens,C,CTokens;
if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS )
{
@ -442,11 +474,18 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
return("");
}
cp = CCinit(&C,EVAL_CHANNELS);
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
funds = numpayments * payment;
if ( AddNormalinputs(mtx,mypk,funds+3*txfee,64) > 0 )
if (tokenid!=zeroid)
{
amount=AddNormalinputs(mtx,mypk,3*txfee,5);
tokens=AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, funds, 64);
}
else amount=AddNormalinputs(mtx,mypk,funds+3*txfee,64);
if (amount+tokens >= funds+2*txfee)
{
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
endiancpy(hash,(uint8_t *)&hentropy,32);
@ -456,10 +495,12 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
memcpy(hash,hashdest,32);
}
endiancpy((uint8_t *)&hashchain,hashdest,32);
mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub));
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub));
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',zeroid,mypk,destpub,numpayments,payment,hashchain)));
if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain)));
}
return("");
}
@ -467,7 +508,7 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3;
CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3,tokenid;
struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,totalnumpayments;
int64_t payment,change,funds,param2;
uint8_t hash[32],hashdest[32];
@ -482,83 +523,85 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
fprintf(stderr, "invalid channel open txid\n");
return ("");
}
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
{
if (mypk != srcpub && mypk != destpub)
{
fprintf(stderr,"this is not our channel\n");
return("");
}
else if (amount % payment != 0 || amount<payment)
{
fprintf(stderr,"invalid amount, not a magnitude of payment size\n");
return ("");
}
}
else
{
fprintf(stderr, "invalid channel open tx\n");
return ("");
}
if (AddNormalinputs(mtx,mypk,2*txfee,3) > 0)
{
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount-txfee)>=0)
{
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
{
numpayments=amount/payment;
if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 &&
((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) &&
(funcid == 'P' || funcid=='O'))
{
if (mypk != srcpub && mypk != destpub)
if (numpayments > prevdepth)
{
fprintf(stderr,"this is not our channel\n");
return("");
}
else if (amount % payment != 0 || amount<payment)
fprintf(stderr,"not enough funds in channel for that amount\n");
return ("");
} else if (numpayments == 0)
{
fprintf(stderr,"invalid amount, not a magnitude of payment size\n");
fprintf(stderr,"invalid amount\n");
return ("");
}
numpayments=amount/payment;
if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 &&
((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) &&
(funcid == 'P' || funcid=='O'))
if (secret!=zeroid)
{
if (numpayments > prevdepth)
endiancpy(hash, (uint8_t * ) & secret, 32);
for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++)
{
fprintf(stderr,"not enough funds in channel for that amount\n");
return ("");
} else if (numpayments == 0)
vcalc_sha256(0, hashdest, hash, 32);
memcpy(hash, hashdest, 32);
}
endiancpy((uint8_t * ) & gensecret, hashdest, 32);
if (gensecret!=hashchain)
{
fprintf(stderr,"invalid amount\n");
return ("");
fprintf(stderr,"invalid secret supplied\n");
return("");
}
if (secret!=zeroid)
}
else
{
hentropy = DiceHashEntropy(entropy,channelOpenTx.vin[0].prevout.hash,channelOpenTx.vin[0].prevout.n,1);
if (prevdepth-numpayments)
{
endiancpy(hash, (uint8_t * ) & secret, 32);
for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++)
endiancpy(hash, (uint8_t * ) & hentropy, 32);
for (i = 0; i < prevdepth-numpayments; i++)
{
vcalc_sha256(0, hashdest, hash, 32);
memcpy(hash, hashdest, 32);
}
endiancpy((uint8_t * ) & gensecret, hashdest, 32);
if (gensecret!=hashchain)
{
fprintf(stderr,"invalid secret supplied\n");
return("");
}
}
else
{
hentropy = DiceHashEntropy(entropy,channelOpenTx.vin[0].prevout.hash,channelOpenTx.vin[0].prevout.n,1);
if (prevdepth-numpayments)
{
endiancpy(hash, (uint8_t * ) & hentropy, 32);
for (i = 0; i < prevdepth-numpayments; i++)
{
vcalc_sha256(0, hashdest, hash, 32);
memcpy(hash, hashdest, 32);
}
endiancpy((uint8_t * ) & secret, hashdest, 32);
}
else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32);
endiancpy((uint8_t * ) & secret, hashdest, 32);
}
}
else
{
fprintf(stderr,"invalid previous tx\n");
return("");
else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32);
}
}
else
{
fprintf(stderr, "invalid channel open tx\n");
return ("");
}
mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
fprintf(stderr,"invalid previous tx\n");
return("");
}
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,srcpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, destpub));
else mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
}
else
{
@ -575,7 +618,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C;
CTransaction channelOpenTx;
uint256 hashblock,tmp_txid,prevtxid,hashchain;
uint256 hashblock,tmp_txid,prevtxid,hashchain,tokenid;
int32_t numvouts,numpayments;
int64_t payment,funds;
@ -589,7 +632,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
fprintf(stderr, "invalid channel open txid\n");
return ("");
}
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{
fprintf(stderr, "invalid channel open tx\n");
return ("");
@ -603,10 +646,11 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
{
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds-txfee>0)
{
mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub));
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub));
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,(funds-txfee)/payment,payment,zeroid)));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,(funds-txfee)/payment,payment,zeroid)));
}
else
{
@ -623,10 +667,9 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2;
int32_t i,numpayments,numvouts,param1;
uint256 hashchain,hashblock,txid,prevtxid,param3,entropy,hentropy,secret;
uint256 hashchain,hashblock,txid,prevtxid,param3,tokenid;
CTransaction channelOpenTx,channelCloseTx,prevTx;
CPubKey srcpub,destpub;
uint8_t funcid,hash[32],hashdest[32];;
// verify stoptxid and origtxid match and are mine
cp = CCinit(&C,EVAL_CHANNELS);
@ -638,7 +681,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
fprintf(stderr, "invalid channel close txid\n");
return ("");
}
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,param1,param2,param3)!='C')
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C')
{
fprintf(stderr, "invalid channel close tx\n");
return ("");
@ -653,7 +696,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
fprintf(stderr, "invalid channel open txid\n");
return ("");
}
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{
fprintf(stderr, "invalid channel open tx\n");
return ("");
@ -668,20 +711,13 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds-txfee>0)
{
if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 &&
DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3) != 0)
DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3) != 0)
{
hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash, channelOpenTx.vin[0].prevout.n,1);
endiancpy(hash, (uint8_t * ) & hentropy, 32);
for (i = 0; i < param1; i++)
{
vcalc_sha256(0, hashdest, hash, 32);
memcpy(hash, hashdest, 32);
}
endiancpy((uint8_t * ) & secret, hashdest, 32);
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,param1,payment,closetxid)));
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds-txfee,mypk));
else mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,param1,payment,closetxid)));
}
else
{
@ -699,7 +735,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
}
UniValue ChannelsList()
{
UniValue result(UniValue::VOBJ); std::vector<std::pair<CAddressIndexKey, CAmount> > txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3;
UniValue result(UniValue::VOBJ); std::vector<std::pair<CAddressIndexKey, CAmount> > txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid;
CTransaction tx; char myCCaddr[65],addr[65],str[256]; CPubKey mypk,srcpub,destpub; int32_t vout,numvouts,param1;
int64_t nValue,param2;
@ -716,7 +752,7 @@ UniValue ChannelsList()
nValue = (int64_t)it->second;
if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
{
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O')
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O')
{
GetCCaddress1of2(cp,addr,srcpub,destpub);
sprintf(str,"%s - %lld payments of %lld satoshi",addr,(long long)param1,(long long)param2);
@ -729,16 +765,16 @@ UniValue ChannelsList()
UniValue ChannelsInfo(uint256 channeltxid)
{
UniValue result(UniValue::VOBJ),array(UniValue::VARR); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid;
UniValue result(UniValue::VOBJ),array(UniValue::VARR); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid,tokenid;
struct CCcontract_info *cp,C; char CCaddr[65],addr[65],str[512]; int32_t vout,numvouts,param1,numpayments;
int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk;
int64_t param2,payment; CPubKey srcpub,destpub,mypk;
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; std::vector<uint256> txids;
cp = CCinit(&C,EVAL_CHANNELS);
mypk = pubkey2pk(Mypubkey());
if (GetTransaction(channeltxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 &&
(DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O'))
(DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'O'))
{
GetCCaddress(cp,CCaddr,mypk);
Getscriptaddress(addr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
@ -746,13 +782,22 @@ UniValue ChannelsInfo(uint256 channeltxid)
result.push_back(Pair("Channel CC address",CCaddr));
result.push_back(Pair("Destination address",addr));
result.push_back(Pair("Number of payments",param1));
result.push_back(Pair("Denomination",i64tostr(param2)+" satoshi"));
result.push_back(Pair("Amount",i64tostr(param1*param2)+" satoshi"));
if(tokenid!=zeroid)
{
result.push_back(Pair("Token id",tokenid.GetHex().data()));
result.push_back(Pair("Denomination (token satoshi)",i64tostr(param2)));
result.push_back(Pair("Amount (token satoshi)",i64tostr(param1*param2)));
}
else
{
result.push_back(Pair("Denomination (satoshi)",i64tostr(param2)));
result.push_back(Pair("Amount (satoshi)",i64tostr(param1*param2)));
}
SetCCtxids(addressIndex,CCaddr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
if (GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (tmp_txid==channeltxid || tx.GetHash()==channeltxid))
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (tmp_txid==channeltxid || tx.GetHash()==channeltxid))
txids.push_back(it->first.txhash);
}
BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx)
@ -760,7 +805,7 @@ UniValue ChannelsInfo(uint256 channeltxid)
const CTransaction &txmempool = e.GetTx();
const uint256 &hash = txmempool.GetHash();
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'P' && tmp_txid==channeltxid)
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'P' && tmp_txid==channeltxid)
txids.push_back(hash);
}
prevtxid=zeroid;
@ -770,14 +815,14 @@ UniValue ChannelsInfo(uint256 channeltxid)
if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
{
UniValue obj(UniValue::VOBJ);
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid)
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid)
{
obj.push_back(Pair("Open",txid.GetHex().data()));
}
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid)
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid)
{
if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 &&
DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O')
DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O')
{
Getscriptaddress(str,tx.vout[3].scriptPubKey);
obj.push_back(Pair("Payment",txid.GetHex().data()));
@ -788,11 +833,11 @@ UniValue ChannelsInfo(uint256 channeltxid)
obj.push_back(Pair("Payments left",param1));
}
}
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid)
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid)
{
obj.push_back(Pair("Close",txid.GetHex().data()));
}
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid)
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid)
{
Getscriptaddress(str,tx.vout[2].scriptPubKey);
obj.push_back(Pair("Refund",txid.GetHex().data()));

15
src/wallet/rpcwallet.cpp

@ -5840,8 +5840,10 @@ UniValue channelsinfo(const UniValue& params, bool fHelp)
UniValue channelsopen(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); int32_t numpayments; int64_t payment; std::vector<unsigned char> destpub; struct CCcontract_info *cp,C; std::string hex;
uint256 tokenid=zeroid;
cp = CCinit(&C,EVAL_CHANNELS);
if ( fHelp || params.size() != 3 )
if ( fHelp || params.size() < 3 || params.size() > 4)
throw runtime_error("channelsopen destpubkey numpayments payment\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");
@ -5865,7 +5867,11 @@ UniValue channelsopen(const UniValue& params, bool fHelp)
ERR_RESULT("invalid payment amount, must be greater than 0");
return result;
}
hex = ChannelOpen(0,pubkey2pk(destpub),numpayments,payment);
if (params.size()==4)
{
tokenid=Parseuint256((char *)params[3].get_str().c_str());
}
hex = ChannelOpen(0,pubkey2pk(destpub),numpayments,payment,tokenid);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
@ -5878,7 +5884,7 @@ UniValue channelspayment(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,secret=zeroid; int32_t n; int64_t amount;
cp = CCinit(&C,EVAL_CHANNELS);
if ( fHelp || params.size() != 2 )
if ( fHelp || params.size() < 2 || params.size() >3 )
throw runtime_error("channelspayment opentxid amount [secret]\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");
@ -6979,7 +6985,6 @@ UniValue tokenbalance(const UniValue& params, bool fHelp)
UniValue result(UniValue::VOBJ); uint256 tokenid; uint64_t balance; std::vector<unsigned char> pubkey; struct CCcontract_info *cp,C;
CCerror.clear();
cp = CCinit(&C,EVAL_ASSETS);
if ( fHelp || params.size() > 2 )
throw runtime_error("tokenbalance tokenid [pubkey]\n");
if ( ensure_CCrequirements() < 0 )
@ -6999,7 +7004,7 @@ UniValue tokenbalance(const UniValue& params, bool fHelp)
char destaddr[64];
result.push_back(Pair("result", "success"));
cp = CCinit(&C,EVAL_TOKENS);
if (GetCCaddress(cp, destaddr, pubkey2pk(pubkey)) != 0)
result.push_back(Pair("CCaddress", destaddr));

Loading…
Cancel
Save