Merge pull request #1387 from Mixa84/FSM
Adding dual daemon import and gateway import. (#21)
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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
Normal file
38
src/cc/CCImportGateway.h
Normal file
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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>> ¶ms);
|
||||
|
||||
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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
// 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;
|
||||
|
||||
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("");
|
||||
}
|
||||
// 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
Normal file
1292
src/cc/importgateway.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 )
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
|
||||
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,
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
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 UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
|
||||
std::vector<CTxOut> &payouts);
|
||||
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);
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user