@@ -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 \
|
||||
|
||||
2
src/ac/morty
Executable file
2
src/ac/morty
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6
|
||||
2
src/ac/rick
Executable file
2
src/ac/rick
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6
|
||||
@@ -243,6 +243,19 @@
|
||||
"ac_supply": "10000000000",
|
||||
"ac_cc": "2",
|
||||
"addnode": ["51.75.122.83"]
|
||||
},
|
||||
{
|
||||
"ac_name": "RICK",
|
||||
"ac_supply": "90000000000",
|
||||
"ac_reward": "100000000",
|
||||
"ac_cc": "3",
|
||||
"addnode": ["138.201.136.145"]
|
||||
},
|
||||
{
|
||||
"ac_name": "MORTY",
|
||||
"ac_supply": "90000000000",
|
||||
"ac_reward": "100000000",
|
||||
"ac_cc": "3",
|
||||
"addnode": ["138.201.136.145"]
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
@@ -47,4 +47,5 @@ echo $pubkey
|
||||
./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 &
|
||||
./komodod -pubkey=$pubkey -ac_name=OUR -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_supply=100000000 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c -ac_public=1 -addnode=51.255.195.65 -addnode=217.182.129.38 -addnode=37.187.225.231 &
|
||||
./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 &
|
||||
|
||||
./komodod -pubkey=$pubkey -ac_name=RICK -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -addnode=138.201.136.145 &
|
||||
./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -addnode=138.201.136.145 &
|
||||
|
||||
@@ -70,6 +70,8 @@ void WaitForShutdown(boost::thread_group* threadGroup)
|
||||
{
|
||||
int32_t i; bool fShutdown = ShutdownRequested();
|
||||
// Tell the main threads to shutdown.
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
komodo_pricesinit();
|
||||
while (!fShutdown)
|
||||
{
|
||||
//fprintf(stderr,"call passport iteration\n");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2717,8 +2717,9 @@ int64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack, *tshake;
|
||||
static int cmp_llu(const void *a, const void*b)
|
||||
{
|
||||
if(*(int64_t *)a < *(int64_t *)b) return -1;
|
||||
if(*(int64_t *)a > *(int64_t *)b) return 1;
|
||||
return 0;
|
||||
else if(*(int64_t *)a > *(int64_t *)b) return 1;
|
||||
else if ( (uint64_t)a < (uint64_t)b ) return -1;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
static int64_t median(int64_t *l, size_t llen)
|
||||
|
||||
@@ -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,21 @@ 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);
|
||||
char *portable_path(char *str);
|
||||
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep);
|
||||
void *filestr(long *allocsizep,char *_fname);
|
||||
|
||||
// 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 +54,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 +297,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 +389,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 +571,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 +635,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 +649,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 )
|
||||
|
||||
@@ -72,7 +72,13 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC
|
||||
|
||||
Let us now consider how to enforce a peg onto a specific gateways CC token. If this can also be achieved, then a full DEX for all the different gateways CC supported coins can be created onto a single fiat denominated chain.
|
||||
|
||||
I think just having a pegscreate rpc call that binds an existing gateways create to a price CC syntax price will be almost enough to support this. Let us assume a USD stablechain and we have a BTC token, then pegscreate <btc gateways txid> "BTCUSD, 1"
|
||||
that will specify using the BTCUSD price, so now we need to create a <txid> based way to do tokenbid/tokenask. For a <txid> based price, the smoothed price is substituted.
|
||||
|
||||
There is the issue of the one day delay, so it might make sense to allow specific bid/ask to be based on some simple combinations of the three possible prices. it might even be possible to go a bit overboard and make a forth like syntax to define the dynamic price for a bid, which maybe at times wont be valid, like it is only valid if the three prices are within 1% of each other. But all that seems over complex and for initial release it can just use the mined, correlated or smoothed price, with some specified percentage offset
|
||||
|
||||
Implementation notes:
|
||||
make sure that fees and markers that can be sent to an unspendable address are sent to: RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P, this is the address for BOTS
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -138,6 +138,9 @@ CBOPRET creates trustless oracles, which can be used for making a synthetic cash
|
||||
Another configuration is to send the 0.4% (or 0.2%) fees to a fee collection scriptPubKey (this is not currently implemented, but would be needed for systems that dont use -ac_perc to collect a global override) this requires adding new vouts
|
||||
|
||||
Modification: in the event there is one price in the accumulator and one price on the stack at the end, then it is a (A - B) spread
|
||||
|
||||
Monetizations should be sent to: RGsWqwFviaNJSbmgWi6338NL2tKkY7ZqKL
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -301,6 +301,9 @@ static int _el_buf_cmp(const void *ap, const void *bp) {
|
||||
ret = -1;
|
||||
else if(a->length > b->length)
|
||||
ret = 1;
|
||||
else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism
|
||||
ret = -1;
|
||||
else ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -35,8 +35,15 @@ static uint32_t thresholdSubtypes(const CC *cond) {
|
||||
}
|
||||
|
||||
|
||||
static int cmpCostDesc(const void *a, const void *b) {
|
||||
return (int) ( *(unsigned long*)b - *(unsigned long*)a );
|
||||
static int cmpCostDesc(const void *a, const void *b)
|
||||
{
|
||||
int retval;
|
||||
retval = (int) ( *(unsigned long*)b - *(unsigned long*)a );
|
||||
if ( retval != 0 )
|
||||
return(retval);
|
||||
else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism
|
||||
return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +86,9 @@ static int cmpConditionBin(const void *a, const void *b) {
|
||||
|
||||
if (ret == 0)
|
||||
return r0.encoded < r1.encoded ? -1 : 1;
|
||||
return 0;
|
||||
else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism
|
||||
return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
2
src/fiat/morty
Executable file
2
src/fiat/morty
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6
|
||||
2
src/fiat/rick
Executable file
2
src/fiat/rick
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -691,7 +691,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar
|
||||
else
|
||||
{
|
||||
komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata);
|
||||
if ( !fJustCheck && matched != 0 )
|
||||
if ( matched != 0 )
|
||||
printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff);
|
||||
}
|
||||
if ( MoMoMdata.pairs != 0 )
|
||||
@@ -747,7 +747,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar
|
||||
}
|
||||
else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 )
|
||||
{
|
||||
if ( !fJustCheck && notaryid >= 0 && notaryid < 64 )
|
||||
if ( notaryid >= 0 && notaryid < 64 )
|
||||
komodo_paxpricefeed(height,&scriptbuf[len],opretlen);
|
||||
}
|
||||
else if ( matched != 0 )
|
||||
|
||||
@@ -84,6 +84,9 @@ extern char NOTARYADDRS[64][64];
|
||||
int tx_height( const uint256 &hash );
|
||||
extern std::vector<std::string> vWhiteListAddress;
|
||||
void komodo_netevent(std::vector<uint8_t> payload);
|
||||
|
||||
#define PRICES_SMOOTHWIDTH 1
|
||||
int32_t komodo_priceind(char *symbol);
|
||||
void komodo_pricesinit();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1548,11 +1548,13 @@ void komodo_passport_iteration()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern std::vector<uint8_t> Mineropret; // opreturn data set by the data gathering code
|
||||
#define PRICES_MAXCHANGE (COIN / 100) // maximum acceptable change, set at 1%
|
||||
#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1%
|
||||
#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR
|
||||
#define KOMODO_LOCALPRICE_CACHESIZE 7
|
||||
#define KOMODO_LOCALPRICE_CACHESIZE 13
|
||||
#define KOMODO_MAXPRICES 2048
|
||||
#define PRICES_SMOOTHWIDTH 1
|
||||
|
||||
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0)
|
||||
|
||||
@@ -1562,6 +1564,20 @@ const char *Forex[] =
|
||||
{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR"
|
||||
}; // must be in ECB list
|
||||
|
||||
struct komodo_extremeprice
|
||||
{
|
||||
uint256 blockhash;
|
||||
uint32_t pricebits,timestamp;
|
||||
int32_t height;
|
||||
int16_t dir,ind;
|
||||
} ExtremePrice;
|
||||
|
||||
struct komodo_priceinfo
|
||||
{
|
||||
FILE *fp;
|
||||
char symbol[64];
|
||||
} PRICES[KOMODO_MAXPRICES];
|
||||
|
||||
uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)];
|
||||
int64_t PriceMult[KOMODO_MAXPRICES];
|
||||
int32_t komodo_cbopretsize(uint64_t flags);
|
||||
@@ -1574,26 +1590,33 @@ void komodo_PriceCache_shift()
|
||||
memcpy(PriceCache[0],Mineropret.data(),Mineropret.size());
|
||||
}
|
||||
|
||||
int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block)
|
||||
{
|
||||
CTransaction tx; int32_t numvouts; std::vector<uint8_t> vopret;
|
||||
tx = block->vtx[0];
|
||||
numvouts = (int32_t)tx.vout.size();
|
||||
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
if ( seedp != 0 )
|
||||
memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp));
|
||||
memcpy(heightbits,vopret.data(),vopret.size());
|
||||
return((int32_t)(vopret.size()/sizeof(uint32_t)));
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// komodo_heightpricebits() extracts the price data in the coinbase for nHeight
|
||||
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight)
|
||||
{
|
||||
CBlockIndex *pindex; CBlock block; CTransaction tx; int32_t numvouts; std::vector<uint8_t> vopret;
|
||||
CBlockIndex *pindex; CBlock block;
|
||||
if ( seedp != 0 )
|
||||
*seedp = 0;
|
||||
if ( (pindex= komodo_chainactive(nHeight)) != 0 )
|
||||
{
|
||||
if ( komodo_blockload(block,pindex) == 0 )
|
||||
{
|
||||
tx = block.vtx[0];
|
||||
numvouts = (int32_t)tx.vout.size();
|
||||
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
if ( seedp != 0 )
|
||||
memcpy(seedp,&pindex->hashMerkleRoot,sizeof(*seedp));
|
||||
memcpy(heightbits,vopret.data(),vopret.size());
|
||||
return((int32_t)(vopret.size()/sizeof(uint32_t)));
|
||||
}
|
||||
return(_komodo_heightpricebits(seedp,heightbits,&block));
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"couldnt get pricebits for %d\n",nHeight);
|
||||
@@ -1696,10 +1719,10 @@ CScript komodo_mineropret(int32_t nHeight)
|
||||
{
|
||||
memcpy(pricebits,Mineropret.data(),Mineropret.size());
|
||||
memset(maxflags,0,sizeof(maxflags));
|
||||
if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 )
|
||||
{
|
||||
// if the new prices are outside tolerance, update Mineropret with clamped prices
|
||||
komodo_priceclamp(n,pricebits,prevbits,PRICES_MAXCHANGE);
|
||||
komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE);
|
||||
//fprintf(stderr,"update Mineropret to clamped prices\n");
|
||||
memcpy(Mineropret.data(),pricebits,Mineropret.size());
|
||||
}
|
||||
@@ -1720,18 +1743,26 @@ CScript komodo_mineropret(int32_t nHeight)
|
||||
The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data.
|
||||
|
||||
*/
|
||||
// for PRICES: reconsiderblock 002aca768b09dfcf36bd934ab34b23983148b116e12cb0b6e1a3f895d1db63aa
|
||||
// and
|
||||
// reconsiderblock 0034cf582018eacc0b4ae001491ce460113514cb1a3f217567ef4a2207de361a
|
||||
// reconsiderbloc 000abf51c023b64af327c50c1b060797b8cb281c696d30ab92fd002a8b8c9aea
|
||||
// are needed to sync past initial blocks with different data set
|
||||
|
||||
|
||||
void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits)
|
||||
{
|
||||
ExtremePrice.dir = dir;
|
||||
ExtremePrice.height = height;
|
||||
ExtremePrice.blockhash = blockhash;
|
||||
ExtremePrice.ind = ind;
|
||||
ExtremePrice.timestamp = timestamp;
|
||||
ExtremePrice.pricebits = pricebits;
|
||||
}
|
||||
|
||||
int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey)
|
||||
{
|
||||
int32_t testchain_exemption = 0;
|
||||
std::vector<uint8_t> vopret; char maxflags[KOMODO_MAXPRICES]; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now = (uint32_t)time(NULL);
|
||||
std::vector<uint8_t> vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now;
|
||||
now = (uint32_t)time(NULL);
|
||||
if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 )
|
||||
{
|
||||
bhash = block->GetHash();
|
||||
GetOpReturnData(scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
@@ -1773,7 +1804,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i
|
||||
if ( pricebits[i] == 0 )
|
||||
pricebits[i] = prevbits[i];
|
||||
}
|
||||
if ( komodo_pricecmp(nHeight,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
if ( komodo_pricecmp(nHeight,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 )
|
||||
{
|
||||
for (i=1; i<n; i++)
|
||||
fprintf(stderr,"%.4f ",(double)prevbits[i]/10000);
|
||||
@@ -1815,7 +1846,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i
|
||||
break;
|
||||
}
|
||||
if ( j == KOMODO_LOCALPRICE_CACHESIZE )
|
||||
{
|
||||
komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( maxflag < 0 && localbits[i] > prevbits[i] )
|
||||
{
|
||||
@@ -1828,7 +1862,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i
|
||||
break;
|
||||
}
|
||||
if ( j == KOMODO_LOCALPRICE_CACHESIZE )
|
||||
{
|
||||
komodo_queuelocalprice(-1,nHeight,block->nTime,bhash,i,prevbits[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1844,6 +1881,11 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bhash == ExtremePrice.blockhash )
|
||||
{
|
||||
fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime);
|
||||
memset(&ExtremePrice,0,sizeof(ExtremePrice));
|
||||
}
|
||||
return(0);
|
||||
} else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]);
|
||||
return(-1);
|
||||
@@ -2124,7 +2166,7 @@ void komodo_cbopretupdate(int32_t forceflag)
|
||||
{
|
||||
static uint32_t lasttime,lastcrypto,lastbtc,pending;
|
||||
static uint32_t pricebits[4],cryptoprices[KOMODO_MAXPRICES],forexprices[sizeof(Forex)/sizeof(*Forex)];
|
||||
int32_t size; uint32_t flags=0,now;
|
||||
int32_t size; uint32_t flags=0,now; CBlockIndex *pindex;
|
||||
if ( forceflag != 0 && pending != 0 )
|
||||
{
|
||||
while ( pending != 0 )
|
||||
@@ -2182,6 +2224,16 @@ void komodo_cbopretupdate(int32_t forceflag)
|
||||
if ( (flags & 4) != 0 )
|
||||
lastcrypto = now;
|
||||
memcpy(Mineropret.data(),PriceCache[0],size);
|
||||
if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 )
|
||||
{
|
||||
if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) )
|
||||
{
|
||||
fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits);
|
||||
if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 )
|
||||
pindex->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str());
|
||||
}
|
||||
}
|
||||
// high volatility still strands nodes so we need to check new prices to approve a stuck block
|
||||
// scan list of stuck blocks (one?) and auto reconsiderblock if it changed state
|
||||
|
||||
@@ -2301,16 +2353,19 @@ int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int
|
||||
int32_t i,j,k,n,iter,correlation,maxcorrelation=0; int64_t firstprice,price,sum,den,mult,refprice,lowprice,highprice;
|
||||
if ( PRICES_DAYWINDOW < 2 || ind >= KOMODO_MAXPRICES )
|
||||
return(-1);
|
||||
mult = PriceMult[ind];
|
||||
mult = komodo_pricemult(ind);
|
||||
if ( nonzprices != 0 )
|
||||
memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW);
|
||||
//for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
// fprintf(stderr,"%u ",rawprices[i*rawskip]);
|
||||
//fprintf(stderr,"ind.%d\n",ind);
|
||||
for (iter=0; iter<PRICES_DAYWINDOW; iter++)
|
||||
{
|
||||
correlation = 0;
|
||||
i = (iter + seed) % PRICES_DAYWINDOW;
|
||||
refprice = rawprices[i*rawskip];
|
||||
highprice = (refprice * (COIN + PRICES_MAXCHANGE*5)) / COIN;
|
||||
lowprice = (refprice * (COIN - PRICES_MAXCHANGE*5)) / COIN;
|
||||
highprice = (refprice * (COIN + PRICES_ERRORRATE*5)) / COIN;
|
||||
lowprice = (refprice * (COIN - PRICES_ERRORRATE*5)) / COIN;
|
||||
if ( highprice == refprice )
|
||||
highprice++;
|
||||
if ( lowprice == refprice )
|
||||
@@ -2464,10 +2519,39 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters)
|
||||
} else memcpy(dest,src,width*sizeof(*dest));
|
||||
}
|
||||
|
||||
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprices,int32_t numprices)
|
||||
// http://www.holoborodko.com/pavel/numerical-methods/noise-robust-smoothing-filter/
|
||||
//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 };
|
||||
static int cmp_llu(const void *a, const void*b)
|
||||
{
|
||||
//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 };
|
||||
int32_t i; int64_t sum=0,nonzprice,price;
|
||||
if(*(int64_t *)a < *(int64_t *)b) return -1;
|
||||
else if(*(int64_t *)a > *(int64_t *)b) return 1;
|
||||
else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism
|
||||
return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
static int64_t sort64(int64_t *l, int32_t llen)
|
||||
{
|
||||
qsort(l,llen,sizeof(uint64_t),cmp_llu);
|
||||
}
|
||||
|
||||
static int revcmp_llu(const void *a, const void*b)
|
||||
{
|
||||
if(*(int64_t *)a < *(int64_t *)b) return 1;
|
||||
else if(*(int64_t *)a > *(int64_t *)b) return -1;
|
||||
else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism
|
||||
return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
static int64_t revsort64(int64_t *l, int32_t llen)
|
||||
{
|
||||
qsort(l,llen,sizeof(uint64_t),revcmp_llu);
|
||||
}
|
||||
|
||||
int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip)
|
||||
{
|
||||
int32_t i,dir=0; int64_t sum=0,nonzprice,price,halfave,thirdave,fourthave,decayprice;
|
||||
if ( PRICES_DAYWINDOW < 2 )
|
||||
return(0);
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
@@ -2481,12 +2565,131 @@ int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprice
|
||||
{
|
||||
if ( (price= correlated[i*cskip]) != 0 )
|
||||
nonzprice = price;
|
||||
//correlated2[i] = nonzprice / PRICES_DAYWINDOW; // reduce precision
|
||||
buf[PRICES_DAYWINDOW+i] = nonzprice;
|
||||
sum += nonzprice;
|
||||
if ( i == PRICES_DAYWINDOW/2 )
|
||||
halfave = (sum / (PRICES_DAYWINDOW/2));
|
||||
else if ( i == PRICES_DAYWINDOW/3 )
|
||||
thirdave = (sum / (PRICES_DAYWINDOW/3));
|
||||
else if ( i == PRICES_DAYWINDOW/4 )
|
||||
fourthave = (sum / (PRICES_DAYWINDOW/4));
|
||||
}
|
||||
memcpy(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf));
|
||||
price = sum / PRICES_DAYWINDOW;
|
||||
// improve smoothing with correlated2 processing
|
||||
// price = smooth(correlated2,PRICES_DAYWINDOW,price/daywindow) * PRICES_DAYWINDOW;
|
||||
return(price);
|
||||
if ( halfave == price )
|
||||
return(price);
|
||||
else if ( halfave > price ) // rising prices
|
||||
sort64(buf,PRICES_DAYWINDOW);
|
||||
else revsort64(buf,PRICES_DAYWINDOW);
|
||||
decayprice = buf[0];
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
{
|
||||
decayprice = ((decayprice * 97) + (buf[i] * 3)) / 100;
|
||||
//fprintf(stderr,"%.4f ",(double)buf[i]/COIN);
|
||||
}
|
||||
fprintf(stderr,"%ssort half %.8f %.8f %.8f %.8f %.8f %.8f -> %.8f\n",halfave<price?"rev":"",(double)price/COIN,(double)halfave/COIN,(double)thirdave/COIN,(double)fourthave/COIN,(double)decayprice/COIN,(double)buf[PRICES_DAYWINDOW-1]/COIN,(double)(price*7 + halfave*5 + thirdave*3 + fourthave*2 + decayprice + buf[PRICES_DAYWINDOW-1])/(19*COIN));
|
||||
return((price*7 + halfave*5 + thirdave*3 + fourthave*2 + decayprice + buf[PRICES_DAYWINDOW-1]) / 19);
|
||||
}
|
||||
|
||||
void komodo_pricesinit()
|
||||
{
|
||||
int32_t i,createflag = 0;
|
||||
boost::filesystem::path pricefname,pricesdir = GetDataDir() / "prices";
|
||||
fprintf(stderr,"pricesinit (%s)\n",pricesdir.string().c_str());
|
||||
if (!boost::filesystem::exists(pricesdir))
|
||||
boost::filesystem::create_directories(pricesdir), createflag = 1;
|
||||
for (i=0; i<KOMODO_MAXPRICES; i++)
|
||||
{
|
||||
if ( komodo_pricename(PRICES[i].symbol,i) == 0 )
|
||||
break;
|
||||
if ( i == 0 )
|
||||
strcpy(PRICES[i].symbol,"rawprices");
|
||||
pricefname = pricesdir / PRICES[i].symbol;
|
||||
PRICES[i].fp = fopen(pricefname.string().c_str(), createflag != 0 ? "wb+" : "rb+");
|
||||
if ( createflag != 0 )
|
||||
{
|
||||
fseek(PRICES[i].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(int64_t) * 3,SEEK_SET);
|
||||
fputc(0,PRICES[i].fp);
|
||||
fflush(PRICES[i].fp);
|
||||
}
|
||||
}
|
||||
if ( i > 0 && PRICES[0].fp != 0 && createflag != 0 )
|
||||
{
|
||||
fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET);
|
||||
fputc(0,PRICES[0].fp);
|
||||
fflush(PRICES[0].fp);
|
||||
}
|
||||
}
|
||||
|
||||
void komodo_pricesupdate(int32_t height,CBlock *pblock)
|
||||
{
|
||||
static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf;
|
||||
int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[4];
|
||||
width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH);
|
||||
if ( numprices == 0 )
|
||||
{
|
||||
numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t));
|
||||
ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width);
|
||||
ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*3);
|
||||
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
|
||||
fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64);
|
||||
}
|
||||
if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices )
|
||||
{
|
||||
//for (ind=0; ind<numprices; ind++)
|
||||
// fprintf(stderr,"%u ",rawprices[ind]);
|
||||
//fprintf(stderr,"numprices.%d\n",numprices);
|
||||
if ( PRICES[0].fp != 0 )
|
||||
{
|
||||
fseek(PRICES[0].fp,height * numprices * sizeof(uint32_t),SEEK_SET);
|
||||
if ( fwrite(rawprices,sizeof(uint32_t),numprices,PRICES[0].fp) != numprices )
|
||||
fprintf(stderr,"error writing rawprices for ht.%d\n",height);
|
||||
else fflush(PRICES[0].fp);
|
||||
if ( height > PRICES_DAYWINDOW )
|
||||
{
|
||||
fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET);
|
||||
if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices )
|
||||
{
|
||||
rngval = seed;
|
||||
for (ind=1; ind<numprices; ind++)
|
||||
{
|
||||
offset = (width-1)*numprices + ind;
|
||||
rngval = (rngval*11109 + 13849);
|
||||
if ( (correlated= komodo_pricecorrelated(rngval,ind,&ptr32[offset],-numprices,0,PRICES_SMOOTHWIDTH)) > 0 )
|
||||
{
|
||||
fseek(PRICES[ind].fp,height * sizeof(int64_t) * 3,SEEK_SET);
|
||||
buf[0] = rawprices[ind];
|
||||
buf[1] = rawprices[0]; // timestamp
|
||||
memcpy(&buf[2],&correlated,sizeof(correlated));
|
||||
if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) )
|
||||
fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind);
|
||||
else if ( height > PRICES_DAYWINDOW*2 )
|
||||
{
|
||||
fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * 3 * sizeof(int64_t),SEEK_SET);
|
||||
if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*3-1,PRICES[ind].fp) == PRICES_DAYWINDOW*3-1 )
|
||||
{
|
||||
if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[PRICES_DAYWINDOW*3-2],-3)) > 0 )
|
||||
{
|
||||
fseek(PRICES[ind].fp,(height * 3 + 2) * sizeof(int64_t),SEEK_SET);
|
||||
if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) )
|
||||
fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind);
|
||||
else
|
||||
{
|
||||
if ( ind == 36 )
|
||||
fprintf(stderr,"(%.8f %.8f) ",(double)ptr64[PRICES_DAYWINDOW*3-2]/COIN,(double)smoothed/COIN);
|
||||
fflush(PRICES[ind].fp);
|
||||
}
|
||||
} else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind);
|
||||
} else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind);
|
||||
}
|
||||
} else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind);
|
||||
}
|
||||
fprintf(stderr,"height.%d\n",height);
|
||||
} else fprintf(stderr,"error reading rawprices for ht.%d\n",height);
|
||||
} else fprintf(stderr,"height.%d <= width.%d\n",height,width);
|
||||
} else fprintf(stderr,"null PRICES[0].fp\n");
|
||||
} else fprintf(stderr,"numprices mismatch\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
66
src/main.cpp
66
src/main.cpp
@@ -85,6 +85,7 @@ int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
|
||||
//void komodo_broadcast(CBlock *pblock,int32_t limit);
|
||||
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
|
||||
void komodo_setactivation(int32_t height);
|
||||
void komodo_pricesupdate(int32_t height,CBlock *pblock);
|
||||
|
||||
BlockMap mapBlockIndex;
|
||||
CChain chainActive;
|
||||
@@ -3904,7 +3905,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
||||
if ( block.GetHash() == notarizedhash )
|
||||
{
|
||||
fprintf(stderr,"DisconnectTip trying to disconnect notarized block at ht.%d\n",(int32_t)pindexDelete->GetHeight());
|
||||
return(false);
|
||||
return state.DoS(100, error("AcceptBlock(): DisconnectTip trying to disconnect notarized blockht.%d",(int32_t)pindexDelete->GetHeight()),
|
||||
REJECT_INVALID, "past-notarized-height");
|
||||
}
|
||||
}
|
||||
// Apply the block atomically to the chain state.
|
||||
@@ -4148,6 +4150,8 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
||||
komodo_broadcast(pblock,8);
|
||||
else if ( ASSETCHAINS_SYMBOL[0] != 0 )
|
||||
komodo_broadcast(pblock,4);*/
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
komodo_pricesupdate(pindexNew->GetHeight(),pblock);
|
||||
if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 )
|
||||
komodo_activate_sapling(pindexNew);
|
||||
return true;
|
||||
@@ -4233,43 +4237,43 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
|
||||
const CBlockIndex *pindexOldTip = chainActive.Tip();
|
||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
|
||||
|
||||
// stop trying to reorg if the reorged chain is before last notarized height.
|
||||
// stay on the same chain tip!
|
||||
int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid;
|
||||
notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid);
|
||||
if ( pindexFork != 0 && pindexFork->GetHeight() < notarizedht )
|
||||
{
|
||||
fprintf(stderr,"pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexFork->GetHeight(),notarizedht);
|
||||
return state.DoS(100, error("ActivateBestChainStep(): pindexFork->GetHeight().%d is < notarizedht %d, so ignore it",(int32_t)pindexFork->GetHeight(),notarizedht),
|
||||
REJECT_INVALID, "past-notarized-height");
|
||||
}
|
||||
// - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
|
||||
// - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
|
||||
// then pindexFork will be null, and we would need to remove the entire chain including
|
||||
// our genesis block. In practice this (probably) won't happen because of checks elsewhere.
|
||||
auto reorgLength = pindexOldTip ? pindexOldTip->GetHeight() - (pindexFork ? pindexFork->GetHeight() : -1) : 0;
|
||||
assert(MAX_REORG_LENGTH > 0);//, "We must be able to reorg some distance");
|
||||
if (reorgLength > MAX_REORG_LENGTH)
|
||||
if ( reorgLength > MAX_REORG_LENGTH)
|
||||
{
|
||||
int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid;
|
||||
notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid);
|
||||
if ( pindexFork->GetHeight() < notarizedht )
|
||||
{
|
||||
fprintf(stderr,"pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexFork->GetHeight(),notarizedht);
|
||||
pindexFork = pindexOldTip;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto msg = strprintf(_(
|
||||
"A block chain reorganization has been detected that would roll back %d blocks! "
|
||||
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
|
||||
), reorgLength, MAX_REORG_LENGTH) + "\n\n" +
|
||||
_("Reorganization details") + ":\n" +
|
||||
"- " + strprintf(_("Current tip: %s, height %d, work %s\nstake %s"),
|
||||
pindexOldTip->phashBlock->GetHex(), pindexOldTip->GetHeight(), pindexOldTip->chainPower.chainWork.GetHex(),
|
||||
pindexOldTip->chainPower.chainStake.GetHex()) + "\n" +
|
||||
"- " + strprintf(_("New tip: %s, height %d, work %s\nstake %s"),
|
||||
pindexMostWork->phashBlock->GetHex(), pindexMostWork->GetHeight(), pindexMostWork->chainPower.chainWork.GetHex(),
|
||||
pindexMostWork->chainPower.chainStake.GetHex()) + "\n" +
|
||||
"- " + strprintf(_("Fork point: %s %s, height %d"),
|
||||
ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->GetHeight()) + "\n\n" +
|
||||
_("Please help, human!");
|
||||
LogPrintf("*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg,reorgLength+10);
|
||||
fprintf(stderr,"*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg.c_str(),reorgLength+10);
|
||||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
|
||||
StartShutdown();
|
||||
return false;
|
||||
}
|
||||
auto msg = strprintf(_(
|
||||
"A block chain reorganization has been detected that would roll back %d blocks! "
|
||||
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
|
||||
), reorgLength, MAX_REORG_LENGTH) + "\n\n" +
|
||||
_("Reorganization details") + ":\n" +
|
||||
"- " + strprintf(_("Current tip: %s, height %d, work %s\nstake %s"),
|
||||
pindexOldTip->phashBlock->GetHex(), pindexOldTip->GetHeight(), pindexOldTip->chainPower.chainWork.GetHex(),
|
||||
pindexOldTip->chainPower.chainStake.GetHex()) + "\n" +
|
||||
"- " + strprintf(_("New tip: %s, height %d, work %s\nstake %s"),
|
||||
pindexMostWork->phashBlock->GetHex(), pindexMostWork->GetHeight(), pindexMostWork->chainPower.chainWork.GetHex(),
|
||||
pindexMostWork->chainPower.chainStake.GetHex()) + "\n" +
|
||||
"- " + strprintf(_("Fork point: %s %s, height %d"),
|
||||
ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->GetHeight()) + "\n\n" +
|
||||
_("Please help, human!");
|
||||
LogPrintf("*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg,reorgLength+10);
|
||||
fprintf(stderr,"*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg.c_str(),reorgLength+10);
|
||||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
|
||||
StartShutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disconnect active blocks which are no longer in the best chain.
|
||||
|
||||
@@ -75,8 +75,14 @@ int verifyrec(const crypto_generichash_blake2b_state *ctx, u32 *indices, uchar *
|
||||
}
|
||||
|
||||
int compu32(const void *pa, const void *pb) {
|
||||
int32_t retval;
|
||||
u32 a = *(u32 *)pa, b = *(u32 *)pb;
|
||||
return a<b ? -1 : a==b ? 0 : +1;
|
||||
retval = a<b ? -1 : a==b ? 0 : +1;
|
||||
if ( retval != 0 )
|
||||
return(retval);
|
||||
else if ( (uint64_t)pa < (uint64_t)pb ) // jl777 prevent nondeterminism
|
||||
return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
bool duped(proof prf) {
|
||||
|
||||
@@ -1176,7 +1176,7 @@ UniValue paxprice(const UniValue& params, bool fHelp)
|
||||
|
||||
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight);
|
||||
char *komodo_pricename(char *name,int32_t ind);
|
||||
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *correlated2,int32_t numprices);
|
||||
int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip);
|
||||
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
|
||||
int32_t komodo_nextheight();
|
||||
uint32_t komodo_heightstamp(int32_t height);
|
||||
@@ -1185,9 +1185,7 @@ int64_t komodo_pricemult(int32_t ind);
|
||||
|
||||
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
|
||||
{
|
||||
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; int64_t *correlated2; uint32_t rawprices[1440*6],*ptr;
|
||||
//daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1;
|
||||
//pricedata = (uint32_t *)calloc(sizeof(*prices)*3,numblocks + daywindow*2 + PRICES_SMOOTHWIDTH);
|
||||
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; uint32_t rawprices[1440*6],*ptr; int64_t *tmpbuf;
|
||||
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH;
|
||||
komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1);
|
||||
if ( firstheight < width )
|
||||
@@ -1205,20 +1203,17 @@ int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,
|
||||
ptr[1] = rawprices[0]; // timestamp
|
||||
}
|
||||
rngval = seed;
|
||||
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
|
||||
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++)
|
||||
{
|
||||
rngval = (rngval*11109 + 13849);
|
||||
ptr = (uint32_t *)&pricedata[i*3];
|
||||
correlated2[i] = ptr[0];
|
||||
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 )
|
||||
{
|
||||
free(correlated2);
|
||||
return(-3);
|
||||
}
|
||||
}
|
||||
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
|
||||
for (i=0; i<numblocks; i++)
|
||||
pricedata[i*3+2] = komodo_pricesmoothed(&pricedata[i*3+1],3,correlated2,numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
|
||||
pricedata[i*3+2] = komodo_priceave(tmpbuf,&pricedata[i*3+1],3);
|
||||
free(tmpbuf);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1227,7 +1222,7 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("prices maxsamples\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t smoothed,*correlated,*correlated2; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
|
||||
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t *tmpbuf,smoothed,*correlated; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
|
||||
if ( ASSETCHAINS_CBOPRET == 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
@@ -1244,8 +1239,6 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "illegal numpricefeeds");
|
||||
prices = (uint32_t *)calloc(sizeof(*prices),width*numpricefeeds);
|
||||
correlated = (int64_t *)calloc(sizeof(*correlated),width);
|
||||
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
|
||||
//prices2 = (uint32_t *)calloc(sizeof(*prices2),width);
|
||||
i = 0;
|
||||
for (ht=nextheight-1,i=0; i<width&&ht>2; i++,ht--)
|
||||
{
|
||||
@@ -1287,14 +1280,14 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
{
|
||||
offset = j*width + i;
|
||||
rngval = (rngval*11109 + 13849);
|
||||
correlated2[i] = prices[offset];
|
||||
if ( (correlated[i]= komodo_pricecorrelated(rngval,j,&prices[offset],1,0,PRICES_SMOOTHWIDTH)) < 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "null correlated price");
|
||||
}
|
||||
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
|
||||
for (i=0; i<maxsamples&&i<numsamples; i++)
|
||||
{
|
||||
offset = j*width + i;
|
||||
smoothed = komodo_pricesmoothed(&correlated[i],1,correlated2,maxsamples+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
|
||||
smoothed = komodo_priceave(tmpbuf,&correlated[i],1);
|
||||
UniValue parr(UniValue::VARR);
|
||||
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
|
||||
parr.push_back(ValueFromAmount(correlated[i]));
|
||||
@@ -1302,6 +1295,7 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
// compare to alternate method
|
||||
p.push_back(parr);
|
||||
}
|
||||
free(tmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1326,9 +1320,7 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
ret.push_back(Pair("daywindow",(int64_t)PRICES_DAYWINDOW));
|
||||
ret.push_back(Pair("numpricefeeds",(int64_t)numpricefeeds));
|
||||
free(prices);
|
||||
//free(prices2);
|
||||
free(correlated);
|
||||
free(correlated2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "notaries_staked.h"
|
||||
|
||||
#include "key_io.h"
|
||||
#include "cc/CCImportGateway.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <univalue.h>
|
||||
@@ -43,8 +45,13 @@
|
||||
|
||||
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);
|
||||
@@ -52,11 +59,10 @@ struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t
|
||||
uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
|
||||
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||
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)
|
||||
{
|
||||
@@ -340,7 +346,6 @@ UniValue selfimport(const UniValue& params, bool fHelp)
|
||||
source = params[5].get_str();
|
||||
} */
|
||||
|
||||
|
||||
if (source == "BEAM")
|
||||
{
|
||||
if (ASSETCHAINS_BEAMPORT == 0)
|
||||
@@ -400,16 +405,351 @@ 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;
|
||||
}
|
||||
|
||||
bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector<CTxIn> &vin, std::vector<int8_t> &NotarisationNotaries);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
// TODO take timestamp as param, and loop blockindex to get starting/finish height.
|
||||
@@ -594,9 +934,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);
|
||||
|
||||
|
||||
@@ -1067,9 +1067,9 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp)
|
||||
"1. \"txid\" (string, optional) The transaction id to keep.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"total_transactons\" : n, (numeric) Transactions in wallet of " + strprintf("%s",komodo_chainname()) + "\n"
|
||||
" \"remaining_transactons\" : n, (numeric) Transactions in wallet after clean.\n"
|
||||
" \"removed_transactons\" : n, (numeric) The number of transactions removed.\n"
|
||||
" \"total_transactions\" : n, (numeric) Transactions in wallet of " + strprintf("%s",komodo_chainname()) + "\n"
|
||||
" \"remaining_transactions\" : n, (numeric) Transactions in wallet after clean.\n"
|
||||
" \"removed_transactions\" : n, (numeric) The number of transactions removed.\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("cleanwallettransactions", "")
|
||||
@@ -5860,6 +5860,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;
|
||||
@@ -7996,7 +8009,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