Browse Source

Adding dual daemon import and gateway import. (#21)

pull/28/head
Mihailo Milenkovic 5 years ago
committed by GitHub
parent
commit
2872c88795
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Makefile.am
  2. 1
      src/cc/CCGateways.h
  3. 38
      src/cc/CCImportGateway.h
  4. 22
      src/cc/CCcustom.cpp
  5. 14
      src/cc/CCinclude.h
  6. 89
      src/cc/CCutils.cpp
  7. 77
      src/cc/dapps/oraclefeed.c
  8. 3
      src/cc/eval.h
  9. 187
      src/cc/gateways.cpp
  10. 591
      src/cc/import.cpp
  11. 1292
      src/cc/importgateway.cpp
  12. 3
      src/cc/oracles.cpp
  13. 83
      src/importcoin.cpp
  14. 13
      src/importcoin.h
  15. 357
      src/rpc/crosschain.cpp
  16. 15
      src/rpc/server.cpp
  17. 13
      src/rpc/server.h
  18. 14
      src/wallet/rpcwallet.cpp

1
src/Makefile.am

@ -288,6 +288,7 @@ libbitcoin_server_a_SOURCES = \
bloom.cpp \
cc/eval.cpp \
cc/import.cpp \
cc/importgateway.cpp \
cc/CCassetsCore.cpp \
cc/CCcustom.cpp \
cc/CCtx.cpp \

1
src/cc/CCGateways.h

@ -18,7 +18,6 @@
#define CC_GATEWAYS_H
#include "CCinclude.h"
#include "../merkleblock.h"
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
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,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);

38
src/cc/CCImportGateway.h

@ -0,0 +1,38 @@
/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#ifndef CC_IMPORTGATEWAY_H
#define CC_IMPORTGATEWAY_H
#include "CCinclude.h"
// CCcustom
bool ImportGatewayValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn);
bool ImportGatewayExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid);
std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t burnvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub);
std::string ImportGatewayWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
std::string ImportGatewayPartialSign(uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex);
std::string ImportGatewayCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex);
std::string ImportGatewayMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin);
UniValue ImportGatewayPendingDeposits(uint256 bindtxid,std::string refcoin);
UniValue ImportGatewayPendingWithdraws(uint256 bindtxid,std::string refcoin);
UniValue ImportGatewayProcessedWithdraws(uint256 bindtxid,std::string refcoin);
UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey);
UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key);
UniValue ImportGatewayList();
UniValue ImportGatewayInfo(uint256 bindtxid);
#endif

22
src/cc/CCcustom.cpp

@ -31,6 +31,7 @@
#include "CCPayments.h"
#include "CCGateways.h"
#include "CCtokens.h"
#include "CCImportGateway.h"
/*
CCcustom has most of the functions that need to be extended to create a new CC contract.
@ -63,7 +64,6 @@ const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6";
const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u";
char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" };
uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 };
#include "CCcustom.inc"
#undef FUNCNAME
#undef EVALCODE
@ -75,7 +75,6 @@ const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC";
const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk";
char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" };
uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 };
#include "CCcustom.inc"
#undef FUNCNAME
#undef EVALCODE
@ -243,6 +242,17 @@ uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f
#undef FUNCNAME
#undef EVALCODE
// ImportGateway
#define FUNCNAME IsImportGatewayInput
#define EVALCODE EVAL_IMPORTGATEWAY
const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ";
const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y";
char ImportGatewayCChexstr[67] = { "0397231cfe04ea32d5fafb2206773ec9fba6e15c5a4e86064468bca195f7542714" };
uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0xae, 0x0f, 0xbc, 0x77, 0xdb, 0xf8, 0x40, 0x48, 0x90, 0x52, 0x20, 0x9e, 0x45, 0x3b, 0x49, 0xd8, 0x97, 0x60, 0x8c, 0x27, 0x4c, 0x59, 0x46, 0xe1, 0xdf };
#include "CCcustom.inc"
#undef FUNCNAME
#undef EVALCODE
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode)
{
CPubKey pk; int32_t i; uint8_t pub33[33],check33[33],hash[32]; char CCaddr[64],checkaddr[64],str[67];
@ -425,6 +435,14 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
cp->validate = TokensValidate;
cp->ismyvin = IsTokensInput;
break;
case EVAL_IMPORTGATEWAY:
strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr);
strcpy(cp->normaladdr, ImportGatewayNormaladdr);
strcpy(cp->CChexstr, ImportGatewayCChexstr);
memcpy(cp->CCpriv, ImportGatewayCCpriv, 32);
cp->validate = ImportGatewayValidate;
cp->ismyvin = IsImportGatewayInput;
break;
default:
if ( CClib_initcp(cp,evalcode) < 0 )
return(0);

14
src/cc/CCinclude.h

@ -51,6 +51,7 @@ one other technical note is that komodod has the insight-explorer extensions bui
#include "../komodo_defs.h"
#include "../utlist.h"
#include "../uthash.h"
#include "merkleblock.h"
#define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead"
#define CC_MAXVINS 1024
@ -185,9 +186,12 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn,
CTransaction &txOut, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> &params);
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);
uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format);
uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubKey &pk,int64_t &num);
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
//int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs);
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);
@ -212,11 +216,6 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible);
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys);
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
// CCcustom
CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv);
//uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopret1, std::vector<uint8_t> &vopret2);
@ -270,6 +269,9 @@ bool GetCustomscriptaddress(char *destaddr,const CScript &scriptPubKey,uint8_t t
std::vector<uint8_t> Mypubkey();
bool Myprivkey(uint8_t myprivkey[]);
int64_t CCduration(int32_t &numblocks,uint256 txid);
uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid);
int32_t CCCointxidExists(char const *logcategory,uint256 cointxid);
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
bool komodo_txnotarizedconfirmed(uint256 txid);
CPubKey check_signing_pubkey(CScript scriptSig);
// CCtx

89
src/cc/CCutils.cpp

@ -532,6 +532,95 @@ int64_t CCduration(int32_t &numblocks,uint256 txid)
return(duration);
}
uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
{
CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts;
int64_t val,merkleht; CPubKey pk; std::vector<uint8_t>data; char str[65],str2[65];
txid = zeroid;
LogPrint(logcategory,"start reverse scan %s\n",uint256_str(str,batontxid));
while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
{
LogPrint(logcategory,"check %s\n",uint256_str(str,batontxid));
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid )
{
LogPrint(logcategory,"decoded %s\n",uint256_str(str,batontxid));
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
{
len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size());
len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size());
LogPrint(logcategory,"found merkleht.%d len.%d len2.%d %s %s\n",(int32_t)merkleht,len,len2,uint256_str(str,hash),uint256_str(str2,mhash));
if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid )
{
txid = batontxid;
LogPrint(logcategory,"set txid\n");
return(mhash);
}
else
{
LogPrint(logcategory,"missing hash\n");
return(zeroid);
}
}
else LogPrint(logcategory,"height.%d vs search ht.%d\n",(int32_t)merkleht,(int32_t)height);
batontxid = bhash;
LogPrint(logcategory,"new hash %s\n",uint256_str(str,batontxid));
} else break;
}
LogPrint(logcategory,"end of loop\n");
return(zeroid);
}
int32_t myIs_coinaddr_inmempoolvout(char const *logcategory,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 )
{
LogPrint(logcategory,"found (%s) vout in mempool\n",coinaddr);
return(1);
}
}
}
}
return(0);
}
int32_t CCCointxidExists(char const *logcategory,uint256 cointxid)
{
char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
CCtxidaddr(txidaddr,cointxid);
SetCCtxids(addressIndex,txidaddr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
return(-1);
}
return(myIs_coinaddr_inmempoolvout(logcategory,txidaddr));
}
/* Get the block merkle root for a proof
* IN: proofData
* OUT: merkle root
* OUT: transaction IDS
*/
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids)
{
CMerkleBlock merkleBlock;
if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
return uint256();
return merkleBlock.txn.ExtractMatches(txids);
}
bool komodo_txnotarizedconfirmed(uint256 txid)
{
char str[65];

77
src/cc/dapps/oraclefeed.c

@ -450,10 +450,12 @@ int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *m
return(0);
}
cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr)
cJSON *get_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr)
{
cJSON *retjson; char *retstr;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspendingwithdraws",bindtxidstr,refcoin,"","")) != 0 )
cJSON *retjson; char *retstr; char function[64];
if (type==0) sprintf(function,"%s","gatewayspendingwithdraws");
else if (type==1) sprintf(function,"%s","importgatewaypendingwithdraws");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
{
//printf("pending.(%s)\n",jprint(retjson,0));
return(retjson);
@ -466,10 +468,13 @@ cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr)
return(0);
}
cJSON *get_gatewaysprocessed(char *refcoin,char *acname,char *bindtxidstr)
cJSON *get_gatewaysprocessed(int8_t type,char *refcoin,char *acname,char *bindtxidstr)
{
cJSON *retjson; char *retstr;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysprocessed",bindtxidstr,refcoin,"","")) != 0 )
char function[64];
if (type==0) sprintf(function,"%s","gatewaysprocessed");
else if (type==1) sprintf(function,"%s","importgatewayprocessed");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
{
//printf("pending.(%s)\n",jprint(retjson,0));
return(retjson);
@ -692,10 +697,12 @@ cJSON *addsignature(char *refcoin,char *acname,char *rawtx, int M)
return(0);
}
bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex)
bits256 gatewayspartialsign(int8_t type,char *refcoin,char *acname,bits256 txid,char *hex)
{
char str[65],*retstr; cJSON *retjson;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspartialsign",bits256_str(str,txid),refcoin,hex,"")) != 0 )
char str[65],*retstr; cJSON *retjson; char function[64];
if (type==0) sprintf(function,"%s","gatewayspartialsign");
else if (type==1) sprintf(function,"%s","importgatewaypartialsign");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,txid),refcoin,hex,"")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
@ -710,10 +717,13 @@ bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex)
return (zeroid);
}
bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char *hex)
bits256 gatewayscompletesigning(int8_t type,char *refcoin,char *acname,bits256 withtxid,char *hex)
{
char str[65],*retstr; cJSON *retjson; bits256 txid;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayscompletesigning",bits256_str(str,withtxid),refcoin,hex,"")) != 0 )
char str[65],*retstr; cJSON *retjson; bits256 txid; char function[64];
if (type==0) sprintf(function,"%s","gatewayscompletesigning");
else if (type==1) sprintf(function,"%s","importgatewaycompletesigning");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,hex,"")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
@ -728,10 +738,13 @@ bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char
return (zeroid);
}
bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid)
bits256 gatewaysmarkdone(int8_t type,char *refcoin,char *acname,bits256 withtxid)
{
char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,withtxid),refcoin,"","")) != 0 )
char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid; ; char function[64];
if (type==0) sprintf(function,"%s","gatewaysmarkdone");
else if (type==1) sprintf(function,"%s","importgatewaymarkdone");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,"","")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
@ -746,10 +759,13 @@ bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid)
return (zeroid);
}
int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys)
int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys)
{
char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n;
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysinfo",bindtxidstr,"","","")) != 0 )
char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n; char function[64];
if (type==0) sprintf(function,"%s","gatewaysinfo");
else if (type==1) sprintf(function,"%s","importgatewayinfo");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,"","","")) != 0 )
{
if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 )
{
@ -774,7 +790,6 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M
strcat(*pubkeys,temp);
}
}
else printf("%s != %s\n",oracle,oraclestr);
free_json(retjson);
}
else if ( retstr != 0 )
@ -851,7 +866,7 @@ int32_t markerexists(char *refcoin,char *acname,char *coinaddr)
}
void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N)
void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N)
{
// check queue to prevent duplicate
// check KMD chain and mempool for txidaddr
@ -864,7 +879,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
int32_t i,j,n,K,retval,processed = 0; bits256 txid,cointxid,withdrawtxid,lasttxid,completetxid; int64_t satoshis;
memset(&zeroid,0,sizeof(zeroid));
if ( (retjson= get_gatewayspending(refcoin,acname,bindtxidstr)) != 0 )
if ( (retjson= get_gatewayspending(type,refcoin,acname,bindtxidstr)) != 0 )
{
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 )
{
@ -888,7 +903,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
{
if ( (clijson=addsignature(refcoin,"",rawtx,M)) != 0 && is_cJSON_True(jobj(clijson,"complete")) != 0)
{
txid=gatewayscompletesigning(refcoin,acname,withdrawtxid,jstr(clijson,"hex"));
txid=gatewayscompletesigning(type,refcoin,acname,withdrawtxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s 1of1\n",bits256_str(str,withdrawtxid));
else fprintf(stderr,"### SIGNING error broadcasting tx on %s",acname);
free_json(clijson);
@ -910,13 +925,13 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
{
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
{
txid=gatewayscompletesigning(refcoin,acname,lasttxid,jstr(clijson,"hex"));
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
else if ( jint(clijson,"partialtx") != 0 )
{
txid=gatewayspartialsign(refcoin,acname,lasttxid,jstr(clijson,"hex"));
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
}
@ -932,7 +947,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
}
free_json(retjson);
}
if ( (retjson= get_gatewaysprocessed(refcoin,acname,bindtxidstr)) != 0 )
if ( (retjson= get_gatewaysprocessed(type,refcoin,acname,bindtxidstr)) != 0 )
{
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 )
{
@ -954,7 +969,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
{
withdrawaddr = jstr(item,"withdrawaddr");
fprintf(stderr,"### WITHDRAW %.8f %s sent to %s\n",amount,refcoin,withdrawaddr);
txid=gatewaysmarkdone(refcoin,acname,completetxid);
txid=gatewaysmarkdone(type,refcoin,acname,completetxid);
if (txid.txid!=zeroid.txid) fprintf(stderr,"### MARKDONE withdraw %s\n",bits256_str(str,withdrawtxid));
else fprintf(stderr,"### MARKDONE error broadcasting tx on %s\n",refcoin);
}
@ -1024,7 +1039,7 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034
int32_t main(int32_t argc,char **argv)
{
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
cJSON *clijson,*clijson2,*regjson,*item; int32_t type,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
if ( argc < 6 )
{
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
@ -1044,8 +1059,7 @@ int32_t main(int32_t argc,char **argv)
printf("only formats of L and Ihh are supported now\n");
return(-1);
}
M = N = 1;
acheight = 0;
M = N = 0;
refcoin[0] = 0;
while ( 1 )
{
@ -1061,7 +1075,9 @@ int32_t main(int32_t argc,char **argv)
exit(0);
}
pubkeys=0;
if ( get_gatewaysinfo(refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) < 0 )
if ( get_gatewaysinfo(0,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=0;
else if ( get_gatewaysinfo(1,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=1;
else
{
printf("cant find bindtxid.(%s)\n",bindtxidstr);
exit(0);
@ -1089,9 +1105,8 @@ int32_t main(int32_t argc,char **argv)
if ( bits256_nonz(txid) != 0 )
{
prevheight = height;
acheight = get_coinheight(refcoin,"");
printf("%s ht.%d <- %s\n",refcoin,height,hexstr);
update_gatewayspending(refcoin,acname,bindtxidstr,M,N);
update_gatewayspending(type,refcoin,acname,bindtxidstr,M,N);
}
free_json(clijson2);
}

3
src/cc/eval.h

@ -56,7 +56,8 @@
EVAL(EVAL_MARMARA, 0xef) \
EVAL(EVAL_PAYMENTS, 0xf0) \
EVAL(EVAL_GATEWAYS, 0xf1) \
EVAL(EVAL_TOKENS, 0xf2)
EVAL(EVAL_TOKENS, 0xf2) \
EVAL(EVAL_IMPORTGATEWAY, 0xf3) \
// evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC

187
src/cc/gateways.cpp

@ -412,91 +412,6 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
else return(true);
}
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 )
{
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found (" << coinaddr << ") vout in mempool" << std::endl);
return(1);
}
}
}
}
return(0);
}
uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
{
CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts; int64_t val,merkleht; CPubKey pk; std::vector<uint8_t>data;
txid = zeroid;
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "start reverse scan " << batontxid.GetHex() << std::endl);
while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
{
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "check " << batontxid.GetHex() << std::endl);
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid )
{
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "decoded " << batontxid.GetHex() << std::endl);
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
{
len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size());
len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size());
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found merkleht." << (int32_t)merkleht << " len." << len << " len2." << len2 << " " << hash.GetHex() << " " << mhash.GetHex() << std::endl);
if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid )
{
txid = batontxid;
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "set txid" << std::endl);
return(mhash);
}
else
{
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "missing hash" << std::endl);
return(zeroid);
}
} else LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "height." << (int32_t)merkleht << " vs search ht." << (int32_t)height << std::endl);
batontxid = bhash;
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "new hash " << batontxid.GetHex() << std::endl);
} else break;
}
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "end of loop\n");
return(zeroid);
}
int32_t GatewaysCointxidExists(struct CCcontract_info *cp,uint256 cointxid)
{
char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
CCtxidaddr(txidaddr,cointxid);
SetCCtxids(addressIndex,txidaddr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
return(-1);
}
return(myIs_coinaddr_inmempoolvout(txidaddr));
}
/* Get the block merkle root for a proof
* IN: proofData
* OUT: merkle root
* OUT: transaction IDS
*/
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids)
{
CMerkleBlock merkleBlock;
if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
return uint256();
return merkleBlock.txn.ExtractMatches(txids);
}
int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
{
std::vector<uint256> txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format;
@ -737,7 +652,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
merkleroot = zeroid;
for (i=m=0; i<N; i++)
{
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
if ( (mhash= CCOraclesReverseScan("gatewayscc-2",txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
{
if ( merkleroot == zeroid )
merkleroot = mhash, m = 1;
@ -1094,7 +1009,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
{
pubkey33_str(str,(uint8_t *)&pubkeys[i]);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "pubkeys[" << i << "] " << str << std::endl);
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
if ( (mhash= CCOraclesReverseScan("gatewayscc-2",txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
{
if ( merkleroot == zeroid )
merkleroot = mhash, m = 1;
@ -1111,7 +1026,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GatewaysCointxidExists(cp,cointxid) != 0 )
if ( CCCointxidExists("gatewayscc-1",cointxid) != 0 )
{
CCerror = strprintf("cointxid.%s already exists",uint256_str(str,cointxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
@ -1574,16 +1489,16 @@ UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
@ -1630,15 +1545,15 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
GetTokensCCaddress(cp,tokensaddr,gatewayspk);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
n = msigpubkeys.size();
queueflag = 0;
@ -1717,16 +1632,16 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
n = msigpubkeys.size();
queueflag = 0;
@ -1795,16 +1710,16 @@ UniValue GatewaysExternalAddress(uint256 bindtxid,CPubKey pubkey)
cp = CCinit(&C,EVAL_GATEWAYS);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
GetCustomscriptaddress(addr,CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG,taddr,prefix,prefix2);
result.push_back(Pair("result","success"));
@ -1819,16 +1734,16 @@ UniValue GatewaysDumpPrivKey(uint256 bindtxid,CKey key)
cp = CCinit(&C,EVAL_GATEWAYS);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
priv=EncodeCustomSecret(key,wiftype);
@ -1848,16 +1763,16 @@ UniValue GatewaysInfo(uint256 bindtxid)
Gatewayspk = GetUnspendable(cp,0);
GetTokensCCaddress(cp,gatewaystokens,Gatewayspk);
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
return(result);
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
result.push_back(Pair("result","error"));
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
return(result);
}
if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )
{
@ -1866,19 +1781,17 @@ UniValue GatewaysInfo(uint256 bindtxid)
depositaddr[0] = 0;
if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 0 && M <= N && N > 0 )
{
if ( N > 1 )
{
result.push_back(Pair("M",M));
result.push_back(Pair("N",N));
for (i=0; i<N; i++)
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
result.push_back(Pair("pubkeys",a));
} else result.push_back(Pair("pubkey",pubkey33_str(str,(uint8_t *)&pubkeys[0])));
result.push_back(Pair("M",M));
result.push_back(Pair("N",N));
for (i=0; i<N; i++)
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
result.push_back(Pair("pubkeys",a));
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("wiftype",wiftype));
result.push_back(Pair("deposit",depositaddr));
result.push_back(Pair("tokenid",uint256_str(str,tokenid)));
sprintf(numstr,"%.8f",(double)totalsupply/COIN);

591
src/cc/import.cpp

@ -19,19 +19,10 @@
#include "crosschain.h"
#include "primitives/transaction.h"
#include "cc/CCinclude.h"
#include <openssl/sha.h>
//#define LEV_INFO 0
//#define LEV_DEBUG1 1
//#define LOGSTREAM(category, level, logoperator) { std::ostringstream stream; logoperator; for(int i = 0; i < level; i ++) if( LogAcceptCategory( (std::string(category) + (level > 0 ? std::string("-")+std::to_string(level) : std::string("") )).c_str() ) ) LogPrintStr(stream.str()); }
/*
* CC Eval method for import coin.
*
* This method should control every parameter of the ImportCoin transaction, since it has no signature
* to protect it from malleability.
##### 0xffffffff is a special CCid for single chain/dual daemon imports
*/
#include "key_io.h"
#define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA"
extern std::string ASSETCHAINS_SELFIMPORT;
extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT;
@ -41,10 +32,97 @@ extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid);
int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid);
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);
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
char *nonportable_path(char *str)
{
int32_t i;
for (i=0; str[i]!=0; i++)
if ( str[i] == '/' )
str[i] = '\\';
return(str);
}
char *portable_path(char *str)
{
#ifdef _WIN32
return(nonportable_path(str));
#else
#ifdef __PNACL
/*int32_t i,n;
if ( str[0] == '/' )
return(str);
else
{
n = (int32_t)strlen(str);
for (i=n; i>0; i--)
str[i] = str[i-1];
str[0] = '/';
str[n+1] = 0;
}*/
#endif
return(str);
#endif
}
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
{
FILE *fp;
long filesize,buflen = *allocsizep;
uint8_t *buf = *bufp;
*lenp = 0;
if ( (fp= fopen(portable_path(fname),"rb")) != 0 )
{
fseek(fp,0,SEEK_END);
filesize = ftell(fp);
if ( filesize == 0 )
{
fclose(fp);
*lenp = 0;
//printf("loadfile null size.(%s)\n",fname);
return(0);
}
if ( filesize > buflen )
{
*allocsizep = filesize;
*bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64);
}
rewind(fp);
if ( buf == 0 )
printf("Null buf ???\n");
else
{
if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
printf("error reading filesize.%ld\n",(long)filesize);
buf[filesize] = 0;
}
fclose(fp);
*lenp = filesize;
//printf("loaded.(%s)\n",buf);
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
return(buf);
}
void *filestr(long *allocsizep,char *_fname)
{
long filesize = 0; char *fname,*buf = 0; void *retptr;
*allocsizep = 0;
fname = (char *)malloc(strlen(_fname)+1);
strcpy(fname,_fname);
retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep);
free(fname);
return(retptr);
}
// ac_import=chain support:
// encode opret for gateways import
CScript EncodeImportTxOpRet(uint32_t targetCCid, std::string coin, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
{
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount);
return(opret);
}
CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint256 bindtxid, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
{
CScript opret;
@ -52,169 +130,132 @@ CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint2
return(opret);
}
bool ImportCoinGatewaysVerify(char *refdepositaddr, uint256 oracletxid, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vector<uint8_t>proof, uint256 merkleroot)
CScript EncodeCodaImportTxOpRet(uint32_t targetCCid, std::string coin, std::string burntx, uint256 bindtxid, CPubKey destpub, int64_t amount)
{
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << burntx << bindtxid << destpub << amount);
return(opret);
}
cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5)
{
char cmdstr[5000],fname[256],*jsonstr;
long fsize;
cJSON *retjson=NULL;
sprintf(fname,"/tmp/coda.%s",arg0);
sprintf(cmdstr,"coda.exe client %s %s %s %s %s %s > %s 2>&1",arg0,arg1,arg2,arg3,arg4,arg5,fname);
*retstr = 0;
if (system(cmdstr)<0) return (retjson);
if ( (jsonstr=(char *)filestr(&fsize,fname)) != 0 )
{
jsonstr[strlen(jsonstr)-1]='\0';
if ( (strncmp(jsonstr,"Merkle List of transactions:",28)!=0) || (retjson= cJSON_Parse(jsonstr+29)) == 0)
*retstr=jsonstr;
else free(jsonstr);
}
return(retjson);
}
bool ImportCoinGatewaysVerify(CTransaction oracletx, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vector<uint8_t>proof, uint256 merkleroot)
{
std::vector<uint256> txids;
uint256 proofroot, hashBlock, foundtxid = zeroid;
CTransaction oracletx, burntx;
uint256 proofroot;
std::string name, description, format;
char destaddr[64], destpubaddr[64], claimaddr[64];
int32_t i, numvouts;
int64_t nValue = 0;
if (myGetTransaction(oracletxid, oracletx, hashBlock) == 0 || (numvouts = oracletx.vout.size()) <= 0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify can't find oracletxid=" << oracletxid.GetHex() << std::endl);
return false;
}
if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey, name, description, format) != 'C' || name != refcoin)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched oracle name=" << name.c_str() << " != " << refcoin.c_str() << std::endl);
return false;
}
proofroot = BitcoinGetProofMerkleRoot(proof, txids);
if (proofroot != merkleroot)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
return false;
}
// check the burntxid is in the proof:
if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) {
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify invalid proof for this burntxid=" << burntxid.GetHex() << std::endl);
return false;
}
/*
if (DecodeHexTx(burntx, rawburntx) != 0)
{
Getscriptaddress(claimaddr, burntx.vout[claimvout].scriptPubKey);
Getscriptaddress(destpubaddr, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
if (strcmp(claimaddr, destpubaddr) == 0)
{
for (i = 0; i<numvouts; i++)
{
Getscriptaddress(destaddr, burntx.vout[i].scriptPubKey);
if (strcmp(refdepositaddr, destaddr) == 0)
{
foundtxid = burntx.GetHash();
nValue = burntx.vout[i].nValue;
break;
}
}
}
else fprintf(stderr, "claimaddr.(%s) != destpubaddr.(%s)\n", claimaddr, destpubaddr);
}*/
/*
if (foundtxid == burntxid) {
LOGSTREAM("importcoin", LEV_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in merkleroot merkleroot" << std::endl);
return(nValue);
}
else {
LOGSTREAM("importcoin", LEV_INFO, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in merkleroot merkleroot" << std::endl);
fprintf(stderr, "(%s) != (%s) or txid %s mismatch.%d or script mismatch\n", refdepositaddr, destaddr, uint256_str(str, foundtxid), foundtxid != burntxid);
*/
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in trusted merkleroot" << std::endl);
return true;
}
// make import tx with burntx and its proof of existence
std::string MakeGatewaysImportTx(uint64_t txfee, uint256 bindtxid, int32_t height, std::string refcoin, std::vector<uint8_t>proof, std::string rawburntx, int32_t ivout, uint256 burntxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction burntx, bindtx;
CPubKey mypk, gatewayspk;
uint256 oracletxid, merkleroot, mhash, hashBlock, tokenid, txid;
int64_t totalsupply;
int32_t i, m, n, numvouts;
uint8_t M, N, taddr, prefix, prefix2;
std::string coin;
struct CCcontract_info *cp, C;
std::vector<CPubKey> pubkeys, publishers;
std::vector<uint256>txids;
char depositaddr[64], txidaddr[64];
cp = CCinit(&C, EVAL_GATEWAYS);
/*if (txfee == 0)
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp, 0); */
if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx))
return std::string("");
CAmount amount = GetCoinImportValue(burntx); // equal to int64_t
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl);
if (GetTransaction(bindtxid, bindtx, hashBlock, false) == 0 || (numvouts = bindtx.vout.size()) <= 0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find bindtxid=" << bindtxid.GetHex() << std::endl);
return("");
}
/* if (DecodeGatewaysBindOpRet(depositaddr, bindtx.vout[numvouts - 1].scriptPubKey, coin, tokenid, totalsupply, oracletxid, M, N, pubkeys, taddr, prefix, prefix2) != 'B' || refcoin != coin)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid coin - bindtxid=" << bindtxid.GetHex() << " coin=" << coin.c_str() << std::endl);
return("");
} eliminate link err */
n = (int32_t)pubkeys.size();
merkleroot = zeroid;
for (i = m = 0; i < n; i++)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl);
if ((mhash = GatewaysReverseScan(txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
{
if (merkleroot == zeroid)
merkleroot = mhash, m = 1;
else if (mhash == merkleroot)
m ++;
publishers.push_back(pubkeys[i]);
txids.push_back(txid);
}
}
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl);
if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << coin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
return("");
}
if (GatewaysCointxidExists(cp, burntxid) != 0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " already exists" << std::endl);
return("");
}
if (!ImportCoinGatewaysVerify(depositaddr, oracletxid, ivout, coin, burntxid, rawburntx, proof, merkleroot))
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx could not validate burntx, txid=" << burntxid.GetHex() << std::endl);
return("");
}
std::vector<uint256> leaftxids;
BitcoinGetProofMerkleRoot(proof, leaftxids);
MerkleBranch newBranch(0, leaftxids);
TxProof txProof = std::make_pair(burntxid, newBranch);
std::vector<CTxOut> vouts;
return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts)));
/*if (AddNormalinputs(mtx, mypk, 3 * txfee, 4) > 0)
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, destpub));
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr, burntxid))) << OP_CHECKSIG));
return(FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeGatewaysImportTxOpRet(0xFFFFFFFF, coin, bindtxid, publishers, txids, height, burntxid, ivout, rawburntx, proof, destpub, amount)));
}
LOGSTREAM("importcoin", LEV_INFO, stream << "MakeGatewaysImportTx coud not find normal imputs" << std::endl);*/
return("");
}
// std::string MakeGatewaysImportTx(uint64_t txfee, uint256 oracletxid, int32_t height, std::string refcoin, std::vector<uint8_t> proof, std::string rawburntx, int32_t ivout, uint256 burntxid,std::string destaddr)
// {
// CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
// CTransaction oracletx,regtx; CPubKey regpk;
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
// std::string name,desc,format; std::vector<CTxOut> vouts;
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
// char markeraddr[64]; int64_t datafee;
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
// if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx))
// return std::string("");
// CAmount amount = GetCoinImportValue(burntx); // equal to int64_t
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl);
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find oracletxid=" << oracletxid.GetHex() << std::endl);
// return("");
// }
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
// return("");
// }
// if (name!=refcoin || format!="Ihh")
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
// return("");
// }
// CCtxidaddr(markeraddr,oracletxid);
// SetCCunspents(unspentOutputs,markeraddr);
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
// {
// txid = it->first.txhash;
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
// {
// pubkeys.push_back(regpk);
// n++;
// }
// }
// merkleroot = zeroid;
// for (i = m = 0; i < n; i++)
// {
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl);
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
// {
// if (merkleroot == zeroid)
// merkleroot = mhash, m = 1;
// else if (mhash == merkleroot)
// m ++;
// txids.push_back(txid);
// }
// }
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl);
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
// return("");
// }
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
// if (proofroot != merkleroot)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
// return("");
// }
// // check the burntxid is in the proof:
// if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid proof for this burntxid=" << burntxid.GetHex() << std::endl);
// return("");
// }
// burntx.vout.push_back(MakeBurnOutput(amount,0xffffffff,refcoin,vouts,proof,oracletxid,height));
// std::vector<uint256> leaftxids;
// BitcoinGetProofMerkleRoot(proof, leaftxids);
// MerkleBranch newBranch(0, leaftxids);
// TxProof txProof = std::make_pair(burntxid, newBranch);
// CTxDestination dest = DecodeDestination(destaddr.c_str());
// CScript scriptPubKey = GetScriptForDestination(dest);
// vouts.push_back(CTxOut(amount,scriptPubKey));
// return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts)));
// }
// makes source tx for self import tx
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx)
@ -332,6 +373,90 @@ int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript
return 0;
}
// make import tx with burntx and dual daemon
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint256 codaburntxid; std::vector<unsigned char> dummyproof;
int32_t i,numvouts,n,m; std::string coin,error; struct CCcontract_info *cp, C;
cJSON *result,*tmp,*tmp1; unsigned char hash[SHA256_DIGEST_LENGTH+1];
char out[SHA256_DIGEST_LENGTH*2+1],*retstr,*destaddr,*receiver; TxProof txProof; uint64_t amount;
cp = CCinit(&C, EVAL_GATEWAYS);
if (txfee == 0)
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
SHA256_Final(hash, &sha256);
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(out + (i * 2), "%02x", hash[i]);
}
out[65]='\0';
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: hash=" << out << std::endl);
codaburntxid.SetHex(out);
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receipt=" << receipt << " codaburntxid=" << codaburntxid.GetHex().data() << " amount=" << (double)amount / COIN << std::endl);
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
if (result==0)
{
if (retstr!=0)
{
CCerror=std::string("CodaRPC: ")+retstr;
free(retstr);
}
return("");
}
else
{
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))!=0 && (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))!=0 &&
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))!=0 && (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))!=0)
{
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receiver=" << receiver << " destaddr=" << destaddr << " amount=" << amount << std::endl);
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
{
CCerror="MakeCodaImportTx: invalid burn address, coins do not go to predefined burn address - ";
CCerror+=CODA_BURN_ADDRESS;
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
free(result);
return("");
}
CTxDestination dest = DecodeDestination(destaddr);
CScript scriptPubKey = GetScriptForDestination(dest);
if (vouts[0]!=CTxOut(amount*COIN,scriptPubKey))
{
CCerror="MakeCodaImportTx: invalid destination address, burnTx memo!=importTx destination";
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
free(result);
return("");
}
if (amount*COIN!=vouts[0].nValue)
{
CCerror="MakeCodaImportTx: invalid amount, burnTx amount!=importTx amount";
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
free(result);
return("");
}
burntx.vin.push_back(CTxIn(codaburntxid,0,CScript()));
burntx.vout.push_back(MakeBurnOutput(amount*COIN,0xffffffff,"CODA",vouts,dummyproof,srcaddr,receipt));
return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof,burntx,vouts)));
}
else
{
CCerror="MakeCodaImportTx: invalid Coda burn tx";
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
free(result);
return("");
}
}
CCerror="MakeCodaImportTx: error fetching Coda tx";
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
free(result);
return("");
}
// use proof from the above functions to validate the import
int32_t CheckBEAMimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
@ -340,17 +465,135 @@ int32_t CheckBEAMimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction
return(-1);
}
int32_t CheckCODAimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector<CTxOut> payouts,std::string srcaddr,std::string receipt)
{
cJSON *result,*tmp,*tmp1; char *retstr,out[SHA256_DIGEST_LENGTH*2+1]; unsigned char hash[SHA256_DIGEST_LENGTH+1]; int i,n,m;
SHA256_CTX sha256; uint256 codaburntxid; char *destaddr,*receiver; uint64_t amount;
// check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx
return(-1);
SHA256_Init(&sha256);
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
SHA256_Final(hash, &sha256);
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(out + (i * 2), "%02x", hash[i]);
}
out[65]='\0';
codaburntxid.SetHex(out);
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
if (result==0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CodaRPC error: " << retstr << std::endl);
free(retstr);
return (-1);
}
else
{
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))==0 || (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))==0 ||
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))==0 || (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))==0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid Coda burn tx" << jprint(result,1) << std::endl);
free(result);
return (-1);
}
CTxDestination dest = DecodeDestination(destaddr);
CScript scriptPubKey = GetScriptForDestination(dest);
if (payouts[0]!=CTxOut(amount*COIN,scriptPubKey));
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Destination address in burn tx does not match destination in import tx" << std::endl);
free(result);
return (-1);
}
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid burn address " << jstr(tmp1,(char *)"receiver") << std::endl);
free(result);
return (-1);
}
if (amount*COIN!=payouts[0].nValue)
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Burn amount and import amount not matching, " << j64bits(tmp,(char *)"amount") << " - " << payouts[0].nValue/COIN << std::endl);
free(result);
return (-1);
}
if (burnTx.vin[0].prevout.hash!=codaburntxid || importTx.vin[0].prevout.hash!=burnTx.GetHash())
{
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid import/burn tx vin" << std::endl);
free(result);
return (-1);
}
free(result);
}
return(0);
}
int32_t CheckGATEWAYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
int32_t CheckGATEWAYimport(CTransaction importTx,CTransaction burnTx,std::string refcoin,std::vector<uint8_t> proof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
{
// CTransaction oracletx,regtx; CPubKey regpk;
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
// std::string name,desc,format; std::vector<CTxOut> vouts;
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
// char markeraddr[64]; int64_t datafee;
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
// ASSETCHAINS_SELFIMPORT is coin
// check for valid burn from external coin blockchain and if valid return(0);
return(-1);
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl);
// return(-1);
// }
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
// return(-1);
// }
// if (name!=refcoin || format!="Ihh")
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
// return(-1);
// }
// CCtxidaddr(markeraddr,oracletxid);
// SetCCunspents(unspentOutputs,markeraddr);
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
// {
// txid = it->first.txhash;
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
// {
// pubkeys.push_back(regpk);
// n++;
// }
// }
// merkleroot = zeroid;
// for (i = m = 0; i < n; i++)
// {
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
// {
// if (merkleroot == zeroid)
// merkleroot = mhash, m = 1;
// else if (mhash == merkleroot)
// m ++;
// txids.push_back(txid);
// }
// }
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
// return(-1);
// }
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
// if (proofroot != merkleroot)
// {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
// return(-1);
// }
// // check the burntxid is in the proof:
// if (std::find(txids.begin(), txids.end(), burnTx.GetHash()) == txids.end()) {
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid proof for this burntxid=" << burnTx.GetHash().GetHex() << std::endl);
// return(-1);
// }
return(0);
}
int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
@ -404,10 +647,20 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransacti
return(0);
}
/*
* CC Eval method for import coin.
*
* This method should control every parameter of the ImportCoin transaction, since it has no signature
* to protect it from malleability.
##### 0xffffffff is a special CCid for single chain/dual daemon imports
*/
bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &importTx,unsigned int nIn)
{
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000;
uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector<uint8_t> rawproof;
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000; int32_t height,burnvout; std::vector<CPubKey> publishers;
uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid; std::vector<uint8_t> rawproof;
std::vector<uint256> txids; CPubKey destpub;
if ( importTx.vout.size() < 2 )
return Invalid("too-few-vouts");
// params
@ -458,7 +711,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
{
if ( ASSETCHAINS_CODAPORT == 0 )
return Invalid("CODA-import-without-port");
else if ( CheckCODAimport(proof,rawproof,burnTx,payouts) < 0 )
else if ( UnmarshalBurnTx(burnTx,srcaddr,receipt)==0 || CheckCODAimport(importTx,burnTx,payouts,srcaddr,receipt) < 0 )
return Invalid("CODA-import-failure");
}
else if ( targetSymbol == "PUBKEY" )
@ -472,7 +725,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
{
if ( targetSymbol != ASSETCHAINS_SELFIMPORT )
return Invalid("invalid-gateway-import-coin");
else if ( CheckGATEWAYimport(proof,rawproof,burnTx,payouts) < 0 )
else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub) < 0 )
return Invalid("GATEWAY-import-failure");
}
}

1292
src/cc/importgateway.cpp

File diff suppressed because it is too large

3
src/cc/oracles.cpp

@ -971,7 +971,8 @@ UniValue OracleInfo(uint256 origtxid)
UniValue result(UniValue::VOBJ),a(UniValue::VARR);
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk; struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk;
struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
cp = CCinit(&C,EVAL_ORACLES);
CCtxidaddr(markeraddr,origtxid);
if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 )

83
src/importcoin.cpp

@ -35,8 +35,7 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction b
mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload));
mtx.vout = payouts;
auto importData = E_MARSHAL(ss << proof; ss << burnTx);
mtx.vout.insert(mtx.vout.begin(), CTxOut(0, CScript() << OP_RETURN << importData));
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << importData));
if (nExpiryHeightOverride != 0)
mtx.nExpiryHeight = nExpiryHeightOverride; //this is for construction of the tx used for validating importtx
return CTransaction(mtx);
@ -53,29 +52,97 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb
return CTxOut(value, CScript() << OP_RETURN << opret);
}
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
{
std::vector<uint8_t> opret;
opret = E_MARSHAL(ss << VARINT(targetCCid);
ss << targetSymbol;
ss << SerializeHash(payouts);
ss << rawproof;
ss << bindtxid;
ss << publishers;
ss << txids;
ss << height;
ss << burnvout;
ss << rawburntx;
ss << destpub);
return CTxOut(value, CScript() << OP_RETURN << opret);
}
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,std::string srcaddr,
std::string receipt)
{
std::vector<uint8_t> opret;
opret = E_MARSHAL(ss << VARINT(targetCCid);
ss << targetSymbol;
ss << SerializeHash(payouts);
ss << rawproof;
ss << srcaddr;
ss << receipt);
return CTxOut(value, CScript() << OP_RETURN << opret);
}
bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,
std::vector<CTxOut> &payouts)
{
std::vector<uint8_t> vData;
GetOpReturnData(importTx.vout[0].scriptPubKey, vData);
GetOpReturnData(importTx.vout[importTx.vout.size()-1].scriptPubKey, vData);
if (importTx.vout.size() < 1) return false;
payouts = std::vector<CTxOut>(importTx.vout.begin()+1, importTx.vout.end());
payouts = std::vector<CTxOut>(importTx.vout.begin(), importTx.vout.end()-1);
return importTx.vin.size() == 1 &&
importTx.vin[0].scriptSig == (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN)) &&
E_UNMARSHAL(vData, ss >> proof; ss >> burnTx);
}
bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t>&rawproof)
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t>&rawproof)
{
std::vector<uint8_t> burnOpret; uint32_t ccid = 0;
std::vector<uint8_t> burnOpret; uint32_t ccid = 0; bool isEof=true;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof);
ss >> rawproof; isEof=ss.eof();) || !isEof;
}
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt)
{
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof;
ss >> srcaddr;
ss >> receipt));
}
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub)
{
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof;
ss >> bindtxid;
ss >> publishers;
ss >> txids;
ss >> height;
ss >> burnvout;
ss >> rawburntx;
ss >> destpub));
}

13
src/importcoin.h

@ -29,10 +29,15 @@ CTransaction MakeImportCoinTransaction(const TxProof proof,
const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride = 0);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof);
bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t> &rawproof);
bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
std::vector<CTxOut> &payouts);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256>txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub);
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,std::string srcaddr,
std::string receipt);
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t> &rawproof);
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt);
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub);
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,std::vector<CTxOut> &payouts);
bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state);

357
src/rpc/crosschain.cpp

@ -24,6 +24,7 @@
#include "consensus/validation.h"
#include "cc/eval.h"
#include "cc/utils.h"
#include "cc/CCinclude.h"
#include "main.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
@ -35,6 +36,7 @@
#include "script/standard.h"
#include "key_io.h"
#include "cc/CCImportGateway.h"
#include <stdint.h>
#include <univalue.h>
@ -42,19 +44,23 @@
using namespace std;
#define RETURN_IF_ERROR(CCerror) if ( CCerror != "" ) { ERR_RESULT(CCerror); return(result); }
#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x));
extern std::string CCerror;
extern std::string ASSETCHAINS_SELFIMPORT;
extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT;
int32_t ensure_CCrequirements(uint8_t evalcode);
int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height);
struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi);
uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
extern std::string ASSETCHAINS_SELFIMPORT;
uint256 Parseuint256(char *hexstr);
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx);
int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount);
std::string MakeGatewaysImportTx(uint64_t txfee, uint256 bindtxid, int32_t height, std::string refcoin, std::vector<uint8_t>proof, std::string rawburntx, int32_t ivout, uint256 burntxid);
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts);
UniValue assetchainproof(const UniValue& params, bool fHelp)
{
@ -338,7 +344,6 @@ UniValue selfimport(const UniValue& params, bool fHelp)
source = params[5].get_str();
} */
if (source == "BEAM")
{
if (ASSETCHAINS_BEAMPORT == 0)
@ -398,14 +403,348 @@ UniValue selfimport(const UniValue& params, bool fHelp)
// source is external coin is the assetchains symbol in the burnTx OP_RETURN
// burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent
std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, sourcetxid);
//std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, "");
result.push_back(Pair("hex", hextx));
result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
// result.push_back(Pair("hex", hextx));
// result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
}
return result;
}
UniValue importdual(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx;
std::string hex,source,sourceaddr,destaddr,burntxid; uint64_t burnAmount;
CPubKey destpub; std::vector<CTxOut> vouts;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importdual only works on -ac_import chains");
if (fHelp || params.size() < 4)
throw runtime_error("burntxid source_addr dest_pubkey amount\n");
CCerror = "";
burntxid = params[0].get_str();
sourceaddr = params[1].get_str();
destaddr = params[2].get_str();
burnAmount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999;
source = ASSETCHAINS_SELFIMPORT; //defaults to -ac_import=... param
CTxDestination dest = DecodeDestination(destaddr.c_str());
CScript scriptPubKey = GetScriptForDestination(dest);
vouts.push_back(CTxOut(burnAmount,scriptPubKey));
if (source == "BEAM")
{
if (ASSETCHAINS_BEAMPORT == 0)
return(-1);
// confirm via ASSETCHAINS_BEAMPORT that burnTx/hash is a valid BEAM burn
// return(0);
return -1;
}
else if (source == "CODA")
{
if (ASSETCHAINS_CODAPORT == 0)
return(-1);
hex=MakeCodaImportTx(0,burntxid,sourceaddr,vouts);
// confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn
// return(0);
}
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importdual");
return result;
}
UniValue importgatewayinfo(const UniValue& params, bool fHelp)
{
uint256 txid;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaybind only works on -ac_import chains");
if ( fHelp || params.size() != 1 )
throw runtime_error("importgatewayinfo bindtxid\n");
txid = Parseuint256(params[0].get_str().c_str());
return(ImportGatewayInfo(txid));
}
UniValue importgatewaybind(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx; std::vector<unsigned char> pubkey;
std::string hex,coin; int32_t i,M,N; std::vector<CPubKey> pubkeys;
uint256 oracletxid; uint8_t p1,p2,p3,p4;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaybind only works on -ac_import chains");
if ( fHelp || params.size() != 8)
throw runtime_error("use \'importgatewaybind coin orcletxid M N pubkeys pubtype p2shtype wiftype [taddr]\' to bind an import gateway\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
CCerror = "";
coin = params[0].get_str();
oracletxid = Parseuint256(params[1].get_str().c_str());
M = atoi(params[2].get_str().c_str());
N = atoi(params[3].get_str().c_str());
if ( M > N || N == 0 || N > 15 )
throw runtime_error("illegal M or N > 15\n");
if ( params.size() < 4+N+3 )
throw runtime_error("not enough parameters for N pubkeys\n");
for (i=0; i<N; i++)
{
pubkey = ParseHex(params[4+i].get_str().c_str());
if (pubkey.size()!= 33)
throw runtime_error("invalid destination pubkey");
pubkeys.push_back(pubkey2pk(pubkey));
}
p1 = atoi((char *)params[4+N].get_str().c_str());
p2 = atoi((char *)params[4+N+1].get_str().c_str());
p3 = atoi((char *)params[4+N+2].get_str().c_str());
if (params.size() == 7+N+1) p4 = atoi((char *)params[7+N].get_str().c_str());
if (coin == "BEAM" || coin == "CODA")
{
ERR_RESULT("for BEAM and CODA import use importdual RPC");
return result;
}
else if (coin != ASSETCHAINS_SELFIMPORT)
{
ERR_RESULT("source coin not equal to ac_import name");
return result;
}
hex = ImportGatewayBind(0, coin, oracletxid, M, N, pubkeys, p1, p2, p3, p4);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importgatewaybind");
return result;
}
UniValue importgatewaydeposit(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx; std::vector<uint8_t> rawproof;
std::string hex,coin,rawburntx; int32_t height,burnvout;
CPubKey destpub; std::vector<CTxOut> vouts; uint256 bindtxid,burntxid;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaydeposit only works on -ac_import chains");
if ( fHelp || params.size() != 8)
throw runtime_error("use \'importgatewaydeposit bindtxid height coin burntxid nvout rawburntx rawproof destpub\' to import deposited coins\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
CCerror = "";
bindtxid = Parseuint256(params[0].get_str().c_str());
height = atoi(params[1].get_str().c_str());
coin = params[2].get_str();
burntxid = Parseuint256(params[3].get_str().c_str());
burnvout = atoi(params[4].get_str().c_str());
rawburntx = params[5].get_str();
rawproof = ParseHex(params[6].get_str());
destpub = ParseHex(params[7].get_str());
if (coin == "BEAM" || coin == "CODA")
{
ERR_RESULT("for BEAM and CODA import use importdual RPC");
return result;
}
else if (coin != ASSETCHAINS_SELFIMPORT)
{
ERR_RESULT("source coin not equal to ac_import name");
return result;
}
hex = ImportGatewayDeposit(0, bindtxid, height, coin, burntxid, burnvout, rawburntx, rawproof, destpub);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importgatewaydeposit");
return result;
}
UniValue importgatewaywithdraw(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx; std::vector<uint8_t> rawproof;
std::string hex,coin,rawburntx; int64_t amount; int32_t height,burnvout;
CPubKey destpub; std::vector<CTxOut> vouts; uint256 bindtxid,burntxid;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaywithdraw only works on -ac_import chains");
if ( fHelp || params.size() != 4)
throw runtime_error("use \'importgatewaywithdraw bindtxid coin withdrawpub amount\' to burn imported coins and withdraw them on external chain\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
CCerror = "";
bindtxid = Parseuint256(params[0].get_str().c_str());
coin = params[1].get_str();
destpub = ParseHex(params[2].get_str());
amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999;
if (coin == "BEAM" || coin == "CODA")
{
ERR_RESULT("for BEAM and CODA import use importdual RPC");
return result;
}
else if (coin != ASSETCHAINS_SELFIMPORT)
{
ERR_RESULT("source coin not equal to ac_import name");
return result;
}
hex = ImportGatewayWithdraw(0, bindtxid, coin, destpub, amount);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importgatewaywithdraw");
return result;
}
UniValue importgatewaypartialsign(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); std::string coin,parthex,hex; uint256 txid;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewayspartialsign only works on -ac_import chains");
if ( fHelp || params.size() != 3 )
throw runtime_error("importgatewayspartialsign txidaddr refcoin hex\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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());
coin = params[1].get_str();
parthex = params[2].get_str();
hex = ImportGatewayPartialSign(0,txid,coin,parthex);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex",hex));
} else ERR_RESULT("couldnt importgatewayspartialsign");
return(result);
}
UniValue importgatewaycompletesigning(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); uint256 withdrawtxid; std::string txhex,hex,coin;
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
throw runtime_error("importgatewaycompletesigning only works on -ac_import chains");
if ( fHelp || params.size() != 3 )
throw runtime_error("importgatewaycompletesigning withdrawtxid coin hex\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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());
coin = params[1].get_str();
txhex = params[2].get_str();
hex = ImportGatewayCompleteSigning(0,withdrawtxid,coin,txhex);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importgatewaycompletesigning");
return(result);
}
UniValue importgatewaymarkdone(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); uint256 completetxid; std::string hex,coin;
if ( fHelp || params.size() != 2 )
throw runtime_error("importgatewaymarkdone completesigningtx coin\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
completetxid = Parseuint256((char *)params[0].get_str().c_str());
coin = params[1].get_str();
hex = ImportGatewayMarkDone(0,completetxid,coin);
RETURN_IF_ERROR(CCerror);
if ( hex.size() > 0 )
{
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", hex));
} else ERR_RESULT("couldnt importgatewaymarkdone");
return(result);
}
UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp)
{
uint256 bindtxid; std::string coin;
if ( fHelp || params.size() != 2 )
throw runtime_error("importgatewaypendingdeposits bindtxid coin\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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(ImportGatewayPendingDeposits(bindtxid,coin));
}
UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp)
{
uint256 bindtxid; std::string coin;
if ( fHelp || params.size() != 2 )
throw runtime_error("importgatewaypendingwithdraws bindtxid coin\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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(ImportGatewayPendingWithdraws(bindtxid,coin));
}
UniValue importgatewayprocessed(const UniValue& params, bool fHelp)
{
uint256 bindtxid; std::string coin;
if ( fHelp || params.size() != 2 )
throw runtime_error("importgatewayprocessed bindtxid coin\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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(ImportGatewayProcessedWithdraws(bindtxid,coin));
}
UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp)
{
uint256 bindtxid; CPubKey pubkey;
if ( fHelp || params.size() != 2)
throw runtime_error("importgatewayexternaladdress bindtxid pubkey\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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());
pubkey = ParseHex(params[1].get_str().c_str());
return(ImportGatewayExternalAddress(bindtxid,pubkey));
}
UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp)
{
uint256 bindtxid;
if ( fHelp || params.size() != 2)
throw runtime_error("importgatewaydumpprivkey bindtxid address\n");
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 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());
std::string strAddress = params[1].get_str();
CTxDestination dest = DecodeDestination(strAddress);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid transparent address");
}
const CKeyID *keyID = boost::get<CKeyID>(&dest);
if (!keyID) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
}
CKey vchSecret;
// if (!pwalletMain->GetKey(*keyID, vchSecret)) {
// throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
//}
return(ImportGatewayDumpPrivKey(bindtxid,vchSecret));
}
UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@ -536,9 +875,9 @@ UniValue getimports(const UniValue& params, bool fHelp)
UniValue objTx(UniValue::VOBJ);
objTx.push_back(Pair("txid",tx.GetHash().ToString()));
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
TotalImported += tx.vout[1].nValue;
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[1].nValue)));
if (ExtractDestination(tx.vout[1].scriptPubKey, importaddress))
TotalImported += tx.vout[0].nValue;
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[0].nValue)));
if (ExtractDestination(tx.vout[0].scriptPubKey, importaddress))
{
objTx.push_back(Pair("address", CBitcoinAddress(importaddress).ToString()));
}

15
src/rpc/server.cpp

@ -354,6 +354,21 @@ static const CRPCCommand vRPCCommands[] =
{ "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true },
{ "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true },
{ "crosschain", "selfimport", &selfimport, true },
{ "crosschain", "importdual", &importdual, true },
//ImportGateway
{ "crosschain", "importgatewayddress", &importgatewayaddress, true },
{ "crosschain", "importgatewayinfo", &importgatewayinfo, true },
{ "crosschain", "importgatewaybind", &importgatewaybind, true },
{ "crosschain", "importgatewaydeposit", &importgatewaydeposit, true },
{ "crosschain", "importgatewaywithdraw", &importgatewaywithdraw, true },
{ "crosschain", "importgatewaypartialsign", &importgatewaypartialsign, true },
{ "crosschain", "importgatewaycompletesigning", &importgatewaycompletesigning, true },
{ "crosschain", "importgatewaymarkdone", &importgatewaymarkdone, true },
{ "crosschain", "importgatewaypendingdeposits", &importgatewaypendingdeposits, true },
{ "crosschain", "importgatewaypendingwithdraws", &importgatewaypendingwithdraws, true },
{ "crosschain", "importgatewayprocessed", &importgatewayprocessed, true },
/* Mining */
{ "mining", "getblocktemplate", &getblocktemplate, true },

13
src/rpc/server.h

@ -314,7 +314,6 @@ extern UniValue channelsopen(const UniValue& params, bool fHelp);
extern UniValue channelspayment(const UniValue& params, bool fHelp);
extern UniValue channelsclose(const UniValue& params, bool fHelp);
extern UniValue channelsrefund(const UniValue& params, bool fHelp);
//extern UniValue tokenswapask(const UniValue& params, bool fHelp);
//extern UniValue tokenfillswap(const UniValue& params, bool fHelp);
extern UniValue faucetfund(const UniValue& params, bool fHelp);
@ -435,6 +434,18 @@ extern UniValue invalidateblock(const UniValue& params, bool fHelp);
extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
extern UniValue getspentinfo(const UniValue& params, bool fHelp);
extern UniValue selfimport(const UniValue& params, bool fHelp);
extern UniValue importdual(const UniValue& params, bool fHelp);
extern UniValue importgatewayaddress(const UniValue& params, bool fHelp);
extern UniValue importgatewayinfo(const UniValue& params, bool fHelp);
extern UniValue importgatewaybind(const UniValue& params, bool fHelp);
extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp);
extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp);
extern UniValue importgatewaypartialsign(const UniValue& params, bool fHelp);
extern UniValue importgatewaycompletesigning(const UniValue& params, bool fHelp);
extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp);
extern UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp);
extern UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp);
extern UniValue importgatewayprocessed(const UniValue& params, bool fHelp);
extern UniValue getblocksubsidy(const UniValue& params, bool fHelp);

14
src/wallet/rpcwallet.cpp

@ -5858,6 +5858,19 @@ UniValue tokenaddress(const UniValue& params, bool fHelp)
return(CCaddress(cp,(char *)"Tokens", pubkey));
}
UniValue importgatewayaddress(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
cp = CCinit(&C,EVAL_IMPORTGATEWAY);
if ( fHelp || params.size() > 1 )
throw runtime_error("importgatewayddress [pubkey]\n");
if ( ensure_CCrequirements(0) < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
if ( params.size() == 1 )
pubkey = ParseHex(params[0].get_str().c_str());
return(CCaddress(cp,(char *)"ImportGateway", pubkey));
}
UniValue marmara_poolpayout(const UniValue& params, bool fHelp)
{
int32_t firstheight; double perc; char *jsonstr;
@ -7994,7 +8007,6 @@ UniValue test_heirmarker(const UniValue& params, bool fHelp)
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
}
UniValue test_burntx(const UniValue& params, bool fHelp)
{
// make fake token tx:

Loading…
Cancel
Save