From a268218d115e53f0c8453a42fb3d17e3e6dee8e9 Mon Sep 17 00:00:00 2001 From: jl777 Date: Fri, 25 Jan 2019 01:24:33 -1100 Subject: [PATCH 01/56] Nonz = 0 --- src/komodo_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 289a84d7c..3701f5257 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1654,7 +1654,7 @@ extern int64_t MAX_MONEY; void komodo_args(char *argv0) { extern const char *Notaries_elected1[][2]; - std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz,baseid,len,n,extralen = 0; uint64_t ccenables[256]; + std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256]; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); memset(ccenables,0,sizeof(ccenables)); memset(disablebits,0,sizeof(disablebits)); From 2933c4d2a9220576e0fc5766c50c006374282827 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 14 Feb 2019 22:08:20 +0000 Subject: [PATCH 02/56] modified: assetchains.json modified: assetchains.old --- src/assetchains.json | 9 ++++++++- src/assetchains.old | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/assetchains.json b/src/assetchains.json index 2775f5db3..c4e61d395 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -240,5 +240,12 @@ "217.182.129.38", "37.187.225.231" ] - } + }, + { + "ac_name": "ILN", + "ac_supply": "10000000000", + "ac_cc": "2", + "addnode": ["51.75.122.83"] + } + ] diff --git a/src/assetchains.old b/src/assetchains.old index 41cbbdae1..c1b2594fe 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -47,4 +47,5 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=ZEX -ac_cc=2 -ac_founders=1 -ac_halving=525600 -ac_reward=13000000000 -ac_pubkey=039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af -addnode=5.9.102.210 & ./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 & From 8702ec813060035217711e4d8b1bbb2409968ad8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 14 Feb 2019 22:34:38 +0000 Subject: [PATCH 03/56] new file: ac/ilien new file: fiat/ilien --- src/ac/ilien | 3 +++ src/fiat/ilien | 3 +++ 2 files changed, 6 insertions(+) create mode 100755 src/ac/ilien create mode 100755 src/fiat/ilien diff --git a/src/ac/ilien b/src/ac/ilien new file mode 100755 index 000000000..53e571661 --- /dev/null +++ b/src/ac/ilien @@ -0,0 +1,3 @@ +#!/bin/bash +./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 + diff --git a/src/fiat/ilien b/src/fiat/ilien new file mode 100755 index 000000000..53e571661 --- /dev/null +++ b/src/fiat/ilien @@ -0,0 +1,3 @@ +#!/bin/bash +./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 + From b97f4e091ec7fdc60fd88cb3c93c86dfe87c1bf1 Mon Sep 17 00:00:00 2001 From: blackjok3rtt <30971146+blackjok3rtt@users.noreply.github.com> Date: Thu, 14 Mar 2019 16:47:09 +0800 Subject: [PATCH 04/56] fix 100% PoS chain (#1332) --- src/komodo_bitcoind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index c530db4fb..ae9a9360b 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1527,7 +1527,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ fprintf(stderr,"ht.%d isPoS.%d utxo not validated -> must be PoW fake\n",height,isPoS); isPoS = 0; } - else + else if ( ASSETCHAINS_STAKED != 100 ) { bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); if ( bhash < bnTarget ) From 314b66513926a864514eb16cf5d4d01121c5f2c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihail=20=C2=ABKolo=C2=BB=20Fedorov?= Date: Thu, 21 Mar 2019 10:01:53 +0300 Subject: [PATCH 05/56] RICK & MORTY (#1341) --- src/ac/morty | 2 ++ src/ac/rick | 2 ++ src/assetchains.json | 15 +++++++++++++++ src/assetchains.old | 3 ++- src/fiat/morty | 2 ++ src/fiat/rick | 2 ++ 6 files changed, 25 insertions(+), 1 deletion(-) create mode 100755 src/ac/morty create mode 100755 src/ac/rick create mode 100755 src/fiat/morty create mode 100755 src/fiat/rick diff --git a/src/ac/morty b/src/ac/morty new file mode 100755 index 000000000..4579324b7 --- /dev/null +++ b/src/ac/morty @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6 diff --git a/src/ac/rick b/src/ac/rick new file mode 100755 index 000000000..b68bd56ab --- /dev/null +++ b/src/ac/rick @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6 diff --git a/src/assetchains.json b/src/assetchains.json index dfc352a2f..a37e13208 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -243,6 +243,21 @@ "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"] } + ] diff --git a/src/assetchains.old b/src/assetchains.old index cc85f1cd1..d200d26bd 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -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 & diff --git a/src/fiat/morty b/src/fiat/morty new file mode 100755 index 000000000..99cfa9a09 --- /dev/null +++ b/src/fiat/morty @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/rick b/src/fiat/rick new file mode 100755 index 000000000..99cfa9a09 --- /dev/null +++ b/src/fiat/rick @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 From 5caf0cb306a00980cf11994d458aa6cbdd67677b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihail=20=C2=ABKolo=C2=BB=20Fedorov?= Date: Thu, 21 Mar 2019 15:36:40 +0300 Subject: [PATCH 06/56] fix rick & morty (#1342) * RICK & MORTY * fix --- src/fiat/morty | 2 +- src/fiat/rick | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fiat/morty b/src/fiat/morty index 99cfa9a09..4579324b7 100755 --- a/src/fiat/morty +++ b/src/fiat/morty @@ -1,2 +1,2 @@ #!/bin/bash -./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 +./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/rick b/src/fiat/rick index 99cfa9a09..b68bd56ab 100755 --- a/src/fiat/rick +++ b/src/fiat/rick @@ -1,2 +1,2 @@ #!/bin/bash -./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 +./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6 From b8cdcb25ba1676c60f39a14595e44d57ca7224dc Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 1 Apr 2019 05:37:46 -1100 Subject: [PATCH 07/56] 150000 activation --- src/komodo_bitcoind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index e76da09ec..d5d44bb3d 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1234,7 +1234,7 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; j 100000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) + if ( height > 150000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) break; //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); if ( i != 0 || j != 1 ) From bed1dd2d1ffc9eaaf96b0d37784a193c0963a61e Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 1 Apr 2019 05:38:52 -1100 Subject: [PATCH 08/56] 225k activation --- src/komodo_bitcoind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index d5d44bb3d..d23dac77a 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1234,7 +1234,7 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; j 150000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) + if ( height > 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) break; //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); if ( i != 0 || j != 1 ) From 7b0a4efdca711257d1ce34cb80f43e10fdd216f0 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 1 Apr 2019 05:39:18 -1100 Subject: [PATCH 09/56] 225k activation --- src/komodo_bitcoind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index e76da09ec..d23dac77a 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1234,7 +1234,7 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; j 100000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) + if ( height > 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) break; //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); if ( i != 0 || j != 1 ) From 497038ca05656d6da82985dc7c99e91e27c4535b Mon Sep 17 00:00:00 2001 From: zatJUM <45312760+zatJUM@users.noreply.github.com> Date: Tue, 9 Apr 2019 16:59:41 +0000 Subject: [PATCH 10/56] Updates returned strings for cleanwallettransactions --- src/wallet/rpcwallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index da9afc215..860333b83 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -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", "") From 2872c88795f76019ca7b783910220b259a43db1c Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Wed, 10 Apr 2019 13:09:11 +0200 Subject: [PATCH 11/56] Adding dual daemon import and gateway import. (#21) --- src/Makefile.am | 1 + src/cc/CCGateways.h | 1 - src/cc/CCImportGateway.h | 38 ++ src/cc/CCcustom.cpp | 22 +- src/cc/CCinclude.h | 14 +- src/cc/CCutils.cpp | 89 +++ src/cc/dapps/oraclefeed.c | 77 ++- src/cc/eval.h | 3 +- src/cc/gateways.cpp | 187 ++---- src/cc/import.cpp | 589 ++++++++++++----- src/cc/importgateway.cpp | 1292 +++++++++++++++++++++++++++++++++++++ src/cc/oracles.cpp | 3 +- src/importcoin.cpp | 83 ++- src/importcoin.h | 11 +- src/rpc/crosschain.cpp | 357 +++++++++- src/rpc/server.cpp | 15 + src/rpc/server.h | 13 +- src/wallet/rpcwallet.cpp | 14 +- 18 files changed, 2440 insertions(+), 369 deletions(-) create mode 100644 src/cc/CCImportGateway.h create mode 100644 src/cc/importgateway.cpp diff --git a/src/Makefile.am b/src/Makefile.am index ce7fd1731..248f9aa27 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -288,6 +288,7 @@ libbitcoin_server_a_SOURCES = \ bloom.cpp \ cc/eval.cpp \ cc/import.cpp \ + cc/importgateway.cpp \ cc/CCassetsCore.cpp \ cc/CCcustom.cpp \ cc/CCtx.cpp \ diff --git a/src/cc/CCGateways.h b/src/cc/CCGateways.h index 1f594e38b..8dfed186f 100644 --- a/src/cc/CCGateways.h +++ b/src/cc/CCGateways.h @@ -18,7 +18,6 @@ #define CC_GATEWAYS_H #include "CCinclude.h" -#include "../merkleblock.h" bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4); diff --git a/src/cc/CCImportGateway.h b/src/cc/CCImportGateway.h new file mode 100644 index 000000000..995cde460 --- /dev/null +++ b/src/cc/CCImportGateway.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + +#ifndef CC_IMPORTGATEWAY_H +#define CC_IMPORTGATEWAY_H + +#include "CCinclude.h" + +// CCcustom +bool ImportGatewayValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn); +bool ImportGatewayExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid); +std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector 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::vectorproof,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 \ No newline at end of file diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 3a00e0c98..6c66b3599 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -31,6 +31,7 @@ #include "CCPayments.h" #include "CCGateways.h" #include "CCtokens.h" +#include "CCImportGateway.h" /* CCcustom has most of the functions that need to be extended to create a new CC contract. @@ -63,7 +64,6 @@ const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6"; const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u"; char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" }; uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 }; - #include "CCcustom.inc" #undef FUNCNAME #undef EVALCODE @@ -75,7 +75,6 @@ const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC"; const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk"; char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" }; uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 }; - #include "CCcustom.inc" #undef FUNCNAME #undef EVALCODE @@ -243,6 +242,17 @@ uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f #undef FUNCNAME #undef EVALCODE +// ImportGateway +#define FUNCNAME IsImportGatewayInput +#define EVALCODE EVAL_IMPORTGATEWAY +const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ"; +const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y"; +char ImportGatewayCChexstr[67] = { "0397231cfe04ea32d5fafb2206773ec9fba6e15c5a4e86064468bca195f7542714" }; +uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0xae, 0x0f, 0xbc, 0x77, 0xdb, 0xf8, 0x40, 0x48, 0x90, 0x52, 0x20, 0x9e, 0x45, 0x3b, 0x49, 0xd8, 0x97, 0x60, 0x8c, 0x27, 0x4c, 0x59, 0x46, 0xe1, 0xdf }; +#include "CCcustom.inc" +#undef FUNCNAME +#undef EVALCODE + int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode) { CPubKey pk; int32_t i; uint8_t pub33[33],check33[33],hash[32]; char CCaddr[64],checkaddr[64],str[67]; @@ -425,6 +435,14 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = TokensValidate; cp->ismyvin = IsTokensInput; break; + case EVAL_IMPORTGATEWAY: + strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr); + strcpy(cp->normaladdr, ImportGatewayNormaladdr); + strcpy(cp->CChexstr, ImportGatewayCChexstr); + memcpy(cp->CCpriv, ImportGatewayCCpriv, 32); + cp->validate = ImportGatewayValidate; + cp->ismyvin = IsImportGatewayInput; + break; default: if ( CClib_initcp(cp,evalcode) < 0 ) return(0); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 12b4a6d12..d1fda0154 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -51,6 +51,7 @@ one other technical note is that komodod has the insight-explorer extensions bui #include "../komodo_defs.h" #include "../utlist.h" #include "../uthash.h" +#include "merkleblock.h" #define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead" #define CC_MAXVINS 1024 @@ -185,9 +186,12 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, CTransaction &txOut, std::vector> &preConditions, std::vector> ¶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::vectorpublishers); 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 &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 &vinPubkeys); -uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector &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 &voutPubkeys, std::vector &vopret1, std::vector &vopret2); @@ -270,6 +269,9 @@ bool GetCustomscriptaddress(char *destaddr,const CScript &scriptPubKey,uint8_t t std::vector 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 &proofData, std::vector &txids); bool komodo_txnotarizedconfirmed(uint256 txid); CPubKey check_signing_pubkey(CScript scriptSig); // CCtx diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 887550a0c..9a68c2456 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -532,6 +532,95 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) return(duration); } +uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid) +{ + CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts; + int64_t val,merkleht; CPubKey pk; std::vectordata; 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 > addressIndex; + CCtxidaddr(txidaddr,cointxid); + SetCCtxids(addressIndex,txidaddr); + for (std::vector >::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 &proofData, std::vector &txids) +{ + CMerkleBlock merkleBlock; + if (!E_UNMARSHAL(proofData, ss >> merkleBlock)) + return uint256(); + return merkleBlock.txn.ExtractMatches(txids); +} + bool komodo_txnotarizedconfirmed(uint256 txid) { char str[65]; diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index cf7a2eacb..6ac014ad1 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -450,10 +450,12 @@ int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *m return(0); } -cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr) +cJSON *get_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr) { - cJSON *retjson; char *retstr; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspendingwithdraws",bindtxidstr,refcoin,"","")) != 0 ) + cJSON *retjson; char *retstr; char function[64]; + if (type==0) sprintf(function,"%s","gatewayspendingwithdraws"); + else if (type==1) sprintf(function,"%s","importgatewaypendingwithdraws"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 ) { //printf("pending.(%s)\n",jprint(retjson,0)); return(retjson); @@ -466,10 +468,13 @@ cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr) return(0); } -cJSON *get_gatewaysprocessed(char *refcoin,char *acname,char *bindtxidstr) +cJSON *get_gatewaysprocessed(int8_t type,char *refcoin,char *acname,char *bindtxidstr) { cJSON *retjson; char *retstr; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysprocessed",bindtxidstr,refcoin,"","")) != 0 ) + char function[64]; + if (type==0) sprintf(function,"%s","gatewaysprocessed"); + else if (type==1) sprintf(function,"%s","importgatewayprocessed"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 ) { //printf("pending.(%s)\n",jprint(retjson,0)); return(retjson); @@ -692,10 +697,12 @@ cJSON *addsignature(char *refcoin,char *acname,char *rawtx, int M) return(0); } -bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex) +bits256 gatewayspartialsign(int8_t type,char *refcoin,char *acname,bits256 txid,char *hex) { - char str[65],*retstr; cJSON *retjson; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspartialsign",bits256_str(str,txid),refcoin,hex,"")) != 0 ) + char str[65],*retstr; cJSON *retjson; char function[64]; + if (type==0) sprintf(function,"%s","gatewayspartialsign"); + else if (type==1) sprintf(function,"%s","importgatewaypartialsign"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,txid),refcoin,hex,"")) != 0 ) { if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); else printf("%s\n",jstr(retjson,"error")); @@ -710,10 +717,13 @@ bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex) return (zeroid); } -bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char *hex) +bits256 gatewayscompletesigning(int8_t type,char *refcoin,char *acname,bits256 withtxid,char *hex) { - char str[65],*retstr; cJSON *retjson; bits256 txid; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayscompletesigning",bits256_str(str,withtxid),refcoin,hex,"")) != 0 ) + char str[65],*retstr; cJSON *retjson; bits256 txid; char function[64]; + + if (type==0) sprintf(function,"%s","gatewayscompletesigning"); + else if (type==1) sprintf(function,"%s","importgatewaycompletesigning"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,hex,"")) != 0 ) { if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); else printf("%s\n",jstr(retjson,"error")); @@ -728,10 +738,13 @@ bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char return (zeroid); } -bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid) +bits256 gatewaysmarkdone(int8_t type,char *refcoin,char *acname,bits256 withtxid) { - char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,withtxid),refcoin,"","")) != 0 ) + char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid; ; char function[64]; + + if (type==0) sprintf(function,"%s","gatewaysmarkdone"); + else if (type==1) sprintf(function,"%s","importgatewaymarkdone"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,"","")) != 0 ) { if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); else printf("%s\n",jstr(retjson,"error")); @@ -746,10 +759,13 @@ bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid) return (zeroid); } -int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys) +int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys) { - char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n; - if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysinfo",bindtxidstr,"","","")) != 0 ) + char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n; char function[64]; + + if (type==0) sprintf(function,"%s","gatewaysinfo"); + else if (type==1) sprintf(function,"%s","importgatewayinfo"); + if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,"","","")) != 0 ) { if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 ) { @@ -774,7 +790,6 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M strcat(*pubkeys,temp); } } - else printf("%s != %s\n",oracle,oraclestr); free_json(retjson); } else if ( retstr != 0 ) @@ -851,7 +866,7 @@ int32_t markerexists(char *refcoin,char *acname,char *coinaddr) } -void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N) +void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N) { // check queue to prevent duplicate // check KMD chain and mempool for txidaddr @@ -864,7 +879,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t int32_t i,j,n,K,retval,processed = 0; bits256 txid,cointxid,withdrawtxid,lasttxid,completetxid; int64_t satoshis; memset(&zeroid,0,sizeof(zeroid)); - if ( (retjson= get_gatewayspending(refcoin,acname,bindtxidstr)) != 0 ) + if ( (retjson= get_gatewayspending(type,refcoin,acname,bindtxidstr)) != 0 ) { if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 ) { @@ -888,7 +903,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t { if ( (clijson=addsignature(refcoin,"",rawtx,M)) != 0 && is_cJSON_True(jobj(clijson,"complete")) != 0) { - txid=gatewayscompletesigning(refcoin,acname,withdrawtxid,jstr(clijson,"hex")); + txid=gatewayscompletesigning(type,refcoin,acname,withdrawtxid,jstr(clijson,"hex")); if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s 1of1\n",bits256_str(str,withdrawtxid)); else fprintf(stderr,"### SIGNING error broadcasting tx on %s",acname); free_json(clijson); @@ -910,13 +925,13 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t { if ( is_cJSON_True(jobj(clijson,"complete")) != 0 ) { - txid=gatewayscompletesigning(refcoin,acname,lasttxid,jstr(clijson,"hex")); + txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex")); if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N); else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname); } else if ( jint(clijson,"partialtx") != 0 ) { - txid=gatewayspartialsign(refcoin,acname,lasttxid,jstr(clijson,"hex")); + txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex")); if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N); else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname); } @@ -932,7 +947,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t } free_json(retjson); } - if ( (retjson= get_gatewaysprocessed(refcoin,acname,bindtxidstr)) != 0 ) + if ( (retjson= get_gatewaysprocessed(type,refcoin,acname,bindtxidstr)) != 0 ) { if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 ) { @@ -954,7 +969,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t { withdrawaddr = jstr(item,"withdrawaddr"); fprintf(stderr,"### WITHDRAW %.8f %s sent to %s\n",amount,refcoin,withdrawaddr); - txid=gatewaysmarkdone(refcoin,acname,completetxid); + txid=gatewaysmarkdone(type,refcoin,acname,completetxid); if (txid.txid!=zeroid.txid) fprintf(stderr,"### MARKDONE withdraw %s\n",bits256_str(str,withdrawtxid)); else fprintf(stderr,"### MARKDONE error broadcasting tx on %s\n",refcoin); } @@ -1024,7 +1039,7 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034 int32_t main(int32_t argc,char **argv) { - cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid; + cJSON *clijson,*clijson2,*regjson,*item; int32_t type,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid; if ( argc < 6 ) { printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n"); @@ -1044,8 +1059,7 @@ int32_t main(int32_t argc,char **argv) printf("only formats of L and Ihh are supported now\n"); return(-1); } - M = N = 1; - acheight = 0; + M = N = 0; refcoin[0] = 0; while ( 1 ) { @@ -1061,7 +1075,9 @@ int32_t main(int32_t argc,char **argv) exit(0); } pubkeys=0; - if ( get_gatewaysinfo(refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) < 0 ) + if ( get_gatewaysinfo(0,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=0; + else if ( get_gatewaysinfo(1,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=1; + else { printf("cant find bindtxid.(%s)\n",bindtxidstr); exit(0); @@ -1089,9 +1105,8 @@ int32_t main(int32_t argc,char **argv) if ( bits256_nonz(txid) != 0 ) { prevheight = height; - acheight = get_coinheight(refcoin,""); printf("%s ht.%d <- %s\n",refcoin,height,hexstr); - update_gatewayspending(refcoin,acname,bindtxidstr,M,N); + update_gatewayspending(type,refcoin,acname,bindtxidstr,M,N); } free_json(clijson2); } diff --git a/src/cc/eval.h b/src/cc/eval.h index a42bbdb2f..1324d5e21 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -56,7 +56,8 @@ EVAL(EVAL_MARMARA, 0xef) \ EVAL(EVAL_PAYMENTS, 0xf0) \ EVAL(EVAL_GATEWAYS, 0xf1) \ - EVAL(EVAL_TOKENS, 0xf2) + EVAL(EVAL_TOKENS, 0xf2) \ + EVAL(EVAL_IMPORTGATEWAY, 0xf3) \ // evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 3c1a49194..1039e9176 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -412,91 +412,6 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti else return(true); } -static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr) -{ - int32_t i,n; char destaddr[64]; - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - if ( (n= tx.vout.size()) > 0 ) - { - const uint256 &txid = tx.GetHash(); - for (i=0; idata; - 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 > addressIndex; - CCtxidaddr(txidaddr,cointxid); - SetCCtxids(addressIndex,txidaddr); - for (std::vector >::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 &proofData, std::vector &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::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2) { std::vector 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 >::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 -//#define LEV_INFO 0 -//#define LEV_DEBUG1 1 -//#define LOGSTREAM(category, level, logoperator) { std::ostringstream stream; logoperator; for(int i = 0; i < level; i ++) if( LogAcceptCategory( (std::string(category) + (level > 0 ? std::string("-")+std::to_string(level) : std::string("") )).c_str() ) ) LogPrintStr(stream.str()); } - -/* - * CC Eval method for import coin. - * - * This method should control every parameter of the ImportCoin transaction, since it has no signature - * to protect it from malleability. - - ##### 0xffffffff is a special CCid for single chain/dual daemon imports - */ +#include "key_io.h" +#define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; @@ -41,10 +32,97 @@ extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &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 &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 &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); + +char *nonportable_path(char *str) +{ + int32_t i; + for (i=0; str[i]!=0; i++) + if ( str[i] == '/' ) + str[i] = '\\'; + return(str); +} + +char *portable_path(char *str) +{ +#ifdef _WIN32 + return(nonportable_path(str)); +#else +#ifdef __PNACL + /*int32_t i,n; + if ( str[0] == '/' ) + return(str); + else + { + n = (int32_t)strlen(str); + for (i=n; i>0; i--) + str[i] = str[i-1]; + str[0] = '/'; + str[n+1] = 0; + }*/ +#endif + return(str); +#endif +} + +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + //printf("loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +void *filestr(long *allocsizep,char *_fname) +{ + long filesize = 0; char *fname,*buf = 0; void *retptr; + *allocsizep = 0; + fname = (char *)malloc(strlen(_fname)+1); + strcpy(fname,_fname); + retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); + free(fname); + return(retptr); +} // ac_import=chain support: // encode opret for gateways import +CScript EncodeImportTxOpRet(uint32_t targetCCid, std::string coin, std::vector publishers, std::vectortxids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vectorproof, 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 publishers, std::vectortxids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vectorproof, CPubKey destpub, int64_t amount) { CScript opret; @@ -52,169 +130,132 @@ CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint2 return(opret); } -bool ImportCoinGatewaysVerify(char *refdepositaddr, uint256 oracletxid, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vectorproof, 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::vectorproof, uint256 merkleroot) { std::vector 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; iproof, 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 pubkeys, publishers; - std::vectortxids; - char depositaddr[64], txidaddr[64]; +// std::string MakeGatewaysImportTx(uint64_t txfee, uint256 oracletxid, int32_t height, std::string refcoin, std::vector 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 vouts; +// std::vector pubkeys; std::vectortxids; +// char markeraddr[64]; int64_t datafee; +// std::vector > 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 leaftxids; - BitcoinGetProofMerkleRoot(proof, leaftxids); - MerkleBranch newBranch(0, leaftxids); - TxProof txProof = std::make_pair(burntxid, newBranch); - - std::vector 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 >::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 leaftxids; +// BitcoinGetProofMerkleRoot(proof, leaftxids); +// MerkleBranch newBranch(0, leaftxids); +// TxProof txProof = std::make_pair(burntxid, newBranch); +// CTxDestination dest = DecodeDestination(destaddr.c_str()); +// CScript scriptPubKey = GetScriptForDestination(dest); +// vouts.push_back(CTxOut(amount,scriptPubKey)); +// return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts))); +// } // makes source tx for self import tx std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx) @@ -332,6 +373,90 @@ int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript return 0; } +// make import tx with burntx and dual daemon +std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector vouts) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk; uint256 codaburntxid; std::vector 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 rawproof,CTransaction burnTx,std::vector payouts) @@ -340,17 +465,135 @@ int32_t CheckBEAMimport(TxProof proof,std::vector rawproof,CTransaction return(-1); } -int32_t CheckCODAimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) +int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector 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 rawproof,CTransaction burnTx,std::vector payouts) +int32_t CheckGATEWAYimport(CTransaction importTx,CTransaction burnTx,std::string refcoin,std::vector proof, + uint256 bindtxid,std::vector publishers,std::vector 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 vouts; + // std::vector pubkeys; std::vectortxids; + // char markeraddr[64]; int64_t datafee; + // std::vector > 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 >::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 rawproof,CTransaction burnTx,std::vector payouts) @@ -404,10 +647,20 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector 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 params,const CTransaction &importTx,unsigned int nIn) { - TxProof proof; CTransaction burnTx; std::vector payouts; uint64_t txfee = 10000; - uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector rawproof; + TxProof proof; CTransaction burnTx; std::vector payouts; uint64_t txfee = 10000; int32_t height,burnvout; std::vector publishers; + uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid; std::vector rawproof; + std::vector txids; CPubKey destpub; + if ( importTx.vout.size() < 2 ) return Invalid("too-few-vouts"); // params @@ -458,7 +711,7 @@ bool Eval::ImportCoin(const std::vector params,const CTransaction &impo { if ( ASSETCHAINS_CODAPORT == 0 ) return Invalid("CODA-import-without-port"); - else if ( CheckCODAimport(proof,rawproof,burnTx,payouts) < 0 ) + else if ( UnmarshalBurnTx(burnTx,srcaddr,receipt)==0 || CheckCODAimport(importTx,burnTx,payouts,srcaddr,receipt) < 0 ) return Invalid("CODA-import-failure"); } else if ( targetSymbol == "PUBKEY" ) @@ -472,7 +725,7 @@ bool Eval::ImportCoin(const std::vector 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"); } } diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp new file mode 100644 index 000000000..4e943b472 --- /dev/null +++ b/src/cc/importgateway.cpp @@ -0,0 +1,1292 @@ +/****************************************************************************** + * Copyright © 2014-2019 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. * + * * + ******************************************************************************/ + +#include "CCImportGateway.h" +#include "key_io.h" +#include "../importcoin.h" + +// start of consensus code + +#define KMD_PUBTYPE 60 +#define KMD_P2SHTYPE 85 +#define KMD_WIFTYPE 188 +#define KMD_TADDR 0 +#define CC_MARKER_VALUE 10000 + +CScript EncodeImportGatewayBindOpRet(uint8_t funcid,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector importgatewaypubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2,uint8_t wiftype) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << oracletxid << M << N << importgatewaypubkeys << taddr << prefix << prefix2 << wiftype); + return(opret); +} + +uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype) +{ + std::vector vopret; uint8_t *script,e,f; std::vector pubkeys; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + burnaddr[0] = 0; + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> oracletxid; ss >> M; ss >> N; ss >> importgatewaypubkeys; ss >> taddr; ss >> prefix; ss >> prefix2; ss >> wiftype) != 0 ) + { + if ( prefix == KMD_PUBTYPE && prefix2 == KMD_P2SHTYPE ) + { + if ( N > 1 ) + { + strcpy(burnaddr,CBitcoinAddress(CScriptID(GetScriptForMultisig(M,importgatewaypubkeys))).ToString().c_str()); + LOGSTREAM("importgateway", CCLOG_DEBUG1, stream << "f." << f << " M." << (int)M << " of N." << (int)N << " size." << (int32_t)importgatewaypubkeys.size() << " -> " << burnaddr << std::endl); + } else Getscriptaddress(burnaddr,CScript() << ParseHex(HexStr(importgatewaypubkeys[0])) << OP_CHECKSIG); + } + else + { + if ( N > 1 ) strcpy(burnaddr,CCustomBitcoinAddress(CScriptID(GetScriptForMultisig(M,importgatewaypubkeys)),taddr,prefix,prefix2).ToString().c_str()); + else GetCustomscriptaddress(burnaddr,CScript() << ParseHex(HexStr(importgatewaypubkeys[0])) << OP_CHECKSIG,taddr,prefix,prefix2); + } + return(f); + } else LOGSTREAM("importgateway",CCLOG_DEBUG1, stream << "error decoding bind opret" << std::endl); + return(0); +} + +CScript EncodeImportGatewayDepositOpRet(uint8_t funcid,uint256 bindtxid,std::string refcoin,std::vector publishers,std::vectortxids,int32_t height,uint256 burntxid,int32_t claimvout,std::string deposithex,std::vectorproof,CPubKey destpub,int64_t amount) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << refcoin << bindtxid << publishers << txids << height << burntxid << claimvout << deposithex << proof << destpub << amount); + return(opret); +} + +uint8_t DecodeImportGatewayDepositOpRet(const CScript &scriptPubKey,uint256 &bindtxid,std::string &refcoin,std::vector&publishers,std::vector&txids,int32_t &height,uint256 &burntxid, int32_t &claimvout,std::string &deposithex,std::vector &proof,CPubKey &destpub,int64_t &amount) +{ + std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> refcoin; ss >> bindtxid; ss >> publishers; ss >> txids; ss >> height; ss >> burntxid; ss >> claimvout; ss >> deposithex; ss >> proof; ss >> destpub; ss >> amount) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeImportGatewayWithdrawOpRet(uint8_t funcid,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << bindtxid << refcoin << withdrawpub << amount); + return(opret); +} + +uint8_t DecodeImportGatewayWithdrawOpRet(const CScript &scriptPubKey,uint256 &bindtxid,std::string &refcoin,CPubKey &withdrawpub,int64_t &amount) +{ + std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> bindtxid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeImportGatewayPartialOpRet(uint8_t funcid, uint256 withdrawtxid,std::string refcoin,uint8_t K, CPubKey signerpk,std::string hex) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << withdrawtxid << refcoin << K << signerpk << hex); + return(opret); +} + +uint8_t DecodeImportGatewayPartialOpRet(const CScript &scriptPubKey,uint256 &withdrawtxid,std::string &refcoin,uint8_t &K,CPubKey &signerpk,std::string &hex) +{ + std::vector vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> withdrawtxid; ss >> refcoin; ss >> K; ss >> signerpk; ss >> hex) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeImportGatewayCompleteSigningOpRet(uint8_t funcid,uint256 withdrawtxid,std::string refcoin,uint8_t K,std::string hex) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << withdrawtxid << refcoin << K << hex); + return(opret); +} + +uint8_t DecodeImportGatewayCompleteSigningOpRet(const CScript &scriptPubKey,uint256 &withdrawtxid,std::string &refcoin,uint8_t &K,std::string &hex) +{ + std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> withdrawtxid; ss >> refcoin; ss >> K; ss >> hex) != 0 ) + { + return(f); + } + return(0); +} + +CScript EncodeImportGatewayMarkDoneOpRet(uint8_t funcid,uint256 withdrawtxid,std::string refcoin,uint256 completetxid) +{ + CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; + + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << withdrawtxid << refcoin << completetxid); + return(opret); +} + +uint8_t DecodeImportGatewayMarkDoneOpRet(const CScript &scriptPubKey, uint256 &withdrawtxid, std::string &refcoin, uint256 &completetxid) +{ + std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> withdrawtxid; ss >> refcoin; ss >> completetxid;) != 0 ) + { + return(f); + } + return(0); +} + +uint8_t DecodeImportGatewayOpRet(const CScript &scriptPubKey) +{ + std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && script[0] == EVAL_IMPORTGATEWAY) + { + f=script[1]; + if (f == 'B' || f == 'D' || f == 'C' || f == 'W' || f == 'P' || f == 'S' || f == 'M') + return(f); + } + return(0); +} + +int64_t IsImportGatewayvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +{ + char destaddr[64]; + + if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) + { + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) + return(tx.vout[v].nValue); + } + return(0); +} + +int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2) +{ + std::vector txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format; + char destaddr[64],destpubaddr[64],claimaddr[64]; int32_t i,numvouts; int64_t nValue = 0; + + if ( myGetTransaction(oracletxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify cant find oracletxid " << oracletxid.GetHex() << std::endl); + return(0); + } + if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin ) + { + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify mismatched oracle name " << name << " != " << refcoin << std::endl); + return(0); + } + proofroot = BitcoinGetProofMerkleRoot(proof,txids); + if ( proofroot != merkleroot ) + { + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify mismatched merkleroot " << proofroot.GetHex() << " != " << merkleroot.GetHex() << std::endl); + return(0); + } + if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) + { + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify invalid proof for this burntxid" << std::endl); + return 0; + } + if ( DecodeHexTx(tx,deposithex) != 0 ) + { + GetCustomscriptaddress(claimaddr,tx.vout[claimvout].scriptPubKey,taddr,prefix,prefix2); + GetCustomscriptaddress(destpubaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG,taddr,prefix,prefix2); + if ( strcmp(claimaddr,destpubaddr) == 0 ) + { + for (i=0; i publishers; std::vectortxids; uint256 bindtxid,burntxid; std::vector proof; CPubKey claimpubkey; + if ( (numvouts= tx.vout.size()) > 0 ) + { + if ( DecodeImportGatewayDepositOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxid,coin,publishers,txids,height,burntxid,claimvout,deposithex,proof,claimpubkey,amount) == 'D' && claimpubkey == mypk ) + { + return(amount); + } + } + return(0); +} + +int32_t ImportGatewayBindExists(struct CCcontract_info *cp,CPubKey importgatewaypk,std::string refcoin) +{ + char markeraddr[64],burnaddr[64]; std::string coin; int32_t numvouts; int64_t totalsupply; uint256 tokenid,oracletxid,hashBlock; + uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; CTransaction tx; + std::vector > addressIndex; + + _GetCCaddress(markeraddr,EVAL_IMPORTGATEWAY,importgatewaypk); + SetCCtxids(addressIndex,markeraddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + if ( myGetTransaction(it->first.txhash,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 && DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey)=='B' ) + { + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) == 'B' ) + { + if ( coin == refcoin ) + { + LOGSTREAM("importgateway",CCLOG_INFO, stream << "trying to bind an existing import for coin" << std::endl); + return(1); + } + } + } + } + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) + { + const CTransaction &txmempool = e.GetTx(); + const uint256 &hash = txmempool.GetHash(); + + if ((numvouts=txmempool.vout.size()) > 0 && DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey)=='B') + if (DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) == 'B') + return(1); + } + + return(0); +} + +bool ImportGatewayValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn) +{ + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks,height,claimvout; bool retval; uint8_t funcid,hash[32],K,M,N,taddr,prefix,prefix2,wiftype; + char str[65],destaddr[65],burnaddr[65],importgatewayaddr[65],validationError[512]; + std::vector txids; std::vector pubkeys,publishers,tmppublishers; std::vector proof; int64_t amount,tmpamount; + uint256 hashblock,txid,bindtxid,deposittxid,withdrawtxid,completetxid,tmptokenid,oracletxid,bindtokenid,burntxid,tmptxid,merkleroot,mhash; CTransaction bindtx,tmptx; + std::string refcoin,tmprefcoin,hex,name,description,format; CPubKey pubkey,tmppubkey,importgatewaypk; + + return (true); + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + preventCCvins = preventCCvouts = -1; + if ( numvouts < 1 ) + return eval->Invalid("no vouts"); + else + { + //LogPrint("importgateway-1","check amounts\n"); + // if ( ImportGatewayExactAmounts(cp,eval,tx,1,10000) == false ) + // { + // return eval->Invalid("invalid inputs vs. outputs!"); + // } + // else + // { + importgatewaypk = GetUnspendable(cp,0); + GetCCaddress(cp, importgatewayaddr, importgatewaypk); + if ( (funcid = DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey)) != 0) + { + switch ( funcid ) + { + case 'B': + //vin.0: normal input + //vout.0: CC vout marker + //vout.n-1: opreturn - 'B' coin oracletxid M N pubkeys taddr prefix prefix2 wiftype + return eval->Invalid("unexpected ImportGatewayValidate for gatewaysbind!"); + break; + case 'W': + //vin.0: normal input + //vin.1: CC input of tokens + //vout.0: CC vout marker to gateways CC address + //vout.1: CC vout of gateways tokens back to gateways tokens CC address + //vout.2: CC vout change of tokens back to owners pubkey (if any) + //vout.n-1: opreturn - 'W' bindtxid refcoin withdrawpub amount + return eval->Invalid("unexpected ImportGatewayValidate for gatewaysWithdraw!"); + break; + case 'P': + //vin.0: normal input + //vin.1: CC input of marker from previous tx (withdraw or partialsing) + //vout.0: CC vout marker to gateways CC address + //vout.n-1: opreturn - 'P' withdrawtxid refcoin number_of_signs mypk hex + if ((numvouts=tx.vout.size()) > 0 && DecodeImportGatewayPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,K,pubkey,hex)!='P') + return eval->Invalid("invalid gatewaysPartialSign OP_RETURN data!"); + else if (myGetTransaction(withdrawtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid withdraw txid!"); + else if ((numvouts=tmptx.vout.size()) > 0 && DecodeImportGatewayWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,bindtxid,tmprefcoin,pubkey,amount)!='W') + return eval->Invalid("invalid gatewayswithdraw OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for gatewaysWithdraw!"); + else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for gatewaysWithdraw!"); + else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0) + return eval->Invalid("invalid marker vout for gatewaysWithdraw!"); + else if ( ConstrainVout(tmptx.vout[1],1,importgatewayaddr,amount)==0) + return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!"); + else if (tmptx.vout[1].nValue!=amount) + return eval->Invalid("amount in opret not matching tx tokens amount!"); + else if (komodo_txnotarizedconfirmed(withdrawtxid) == false) + return eval->Invalid("gatewayswithdraw tx is not yet confirmed(notarised)!"); + else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid gatewaysbind txid!"); + else if ((numvouts=tmptx.vout.size()) < 1 || DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,tmprefcoin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B') + return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if (komodo_txnotarizedconfirmed(bindtxid) == false) + return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); + else if (IsCCInput(tx.vin[0].scriptSig) != 0) + return eval->Invalid("vin.0 is normal for gatewayspartialsign!"); + else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin.1 is CC marker for gatewayspartialsign or invalid marker amount!"); + else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 ) + return eval->Invalid("vout.0 invalid marker for gatewayspartialsign!"); + else if (K>M) + return eval->Invalid("invalid number of signs!"); + break; + case 'S': + //vin.0: normal input + //vin.1: CC input of marker from previous tx (withdraw or partialsing) + //vout.0: CC vout marker to gateways CC address + //vout.n-1: opreturn - 'S' withdrawtxid refcoin hex + if ((numvouts=tx.vout.size()) > 0 && DecodeImportGatewayCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,K,hex)!='S') + return eval->Invalid("invalid gatewayscompletesigning OP_RETURN data!"); + else if (myGetTransaction(withdrawtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid withdraw txid!"); + else if ((numvouts=tmptx.vout.size()) > 0 && DecodeImportGatewayWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,bindtxid,tmprefcoin,pubkey,amount)!='W') + return eval->Invalid("invalid gatewayswithdraw OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for gatewaysWithdraw!"); + else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 ) + return eval->Invalid("vin.1 is CC for gatewaysWithdraw!"); + else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0) + return eval->Invalid("invalid marker vout for gatewaysWithdraw!"); + else if ( ConstrainVout(tmptx.vout[1],1,importgatewayaddr,amount)==0) + return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!"); + else if (tmptx.vout[1].nValue!=amount) + return eval->Invalid("amount in opret not matching tx tokens amount!"); + else if (komodo_txnotarizedconfirmed(withdrawtxid) == false) + return eval->Invalid("gatewayswithdraw tx is not yet confirmed(notarised)!"); + else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid gatewaysbind txid!"); + else if ((numvouts=tmptx.vout.size()) < 1 || DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,tmprefcoin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B') + return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if (komodo_txnotarizedconfirmed(bindtxid) == false) + return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); + else if (IsCCInput(tx.vin[0].scriptSig) != 0) + return eval->Invalid("vin.0 is normal for gatewayscompletesigning!"); + else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin.1 is CC marker for gatewayscompletesigning or invalid marker amount!"); + else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 ) + return eval->Invalid("vout.0 invalid marker for gatewayscompletesigning!"); + else if (KInvalid("invalid number of signs!"); + break; + case 'M': + //vin.0: normal input + //vin.1: CC input of gatewayscompletesigning tx marker to gateways CC address + //vout.0: opreturn - 'M' withdrawtxid refcoin completetxid + if ((numvouts=tx.vout.size()) > 0 && DecodeImportGatewayMarkDoneOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,completetxid)!='M') + return eval->Invalid("invalid gatewaysmarkdone OP_RETURN data!"); + else if (myGetTransaction(completetxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid gatewayscompletesigning txid!"); + else if ((numvouts=tmptx.vout.size()) > 0 && DecodeImportGatewayCompleteSigningOpRet(tmptx.vout[numvouts-1].scriptPubKey,withdrawtxid,tmprefcoin,K,hex)!='S') + return eval->Invalid("invalid gatewayscompletesigning OP_RETURN data!"); + else if (komodo_txnotarizedconfirmed(completetxid) == false) + return eval->Invalid("gatewayscompletesigning tx is not yet confirmed(notarised)!"); + else if (myGetTransaction(withdrawtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid withdraw txid!"); + else if ((numvouts=tmptx.vout.size()) > 0 && DecodeImportGatewayWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,bindtxid,tmprefcoin,pubkey,amount)!='W') + return eval->Invalid("invalid gatewayswithdraw OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if (komodo_txnotarizedconfirmed(withdrawtxid) == false) + return eval->Invalid("gatewayswithdraw tx is not yet confirmed(notarised)!"); + else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0) + return eval->Invalid("invalid gatewaysbind txid!"); + else if ((numvouts=tmptx.vout.size()) < 1 || DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,tmprefcoin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B') + return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); + else if (tmprefcoin!=refcoin) + return eval->Invalid("refcoin different than in bind tx"); + else if (komodo_txnotarizedconfirmed(bindtxid) == false) + return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); + else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + return eval->Invalid("vin.0 is normal for gatewaysmarkdone!"); + else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin.1 is CC marker for gatewaysmarkdone or invalid marker amount!"); + else if (KInvalid("invalid number of signs!"); + break; + } + } + retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); + if ( retval != 0 ) + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGateway tx validated" << std::endl); + else fprintf(stderr,"ImportGateway tx invalid\n"); + return(retval); + // } + } +} +// end of consensus code + +// helper functions for rpc calls in rpcwallet.cpp + +std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction oracletx; uint8_t taddr,prefix,prefix2,wiftype; CPubKey mypk,importgatewaypk; CScript opret; uint256 hashBlock; + struct CCcontract_info *cp,*cpTokens,C,CTokens; std::string name,description,format; int32_t i,numvouts; + char destaddr[64],coinaddr[64],myTokenCCaddr[64],str[65],*fstr; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + cpTokens = CCinit(&CTokens,EVAL_TOKENS); + if (coin=="KMD") + { + prefix = KMD_PUBTYPE; + prefix2 = KMD_P2SHTYPE; + wiftype = KMD_WIFTYPE; + taddr = KMD_TADDR; + } + else + { + prefix = p1; + prefix2 = p2; + wiftype = p3; + taddr = p4; + LOGSTREAM("importgateway",CCLOG_DEBUG1, stream << "set prefix " << prefix << ", prefix2 " << prefix2 << ", wiftype " << wiftype << ", taddr " << taddr << " for " << coin << std::endl); + } + if ( N == 0 || N > 15 || M > N ) + { + CCerror = strprintf("illegal M.%d or N.%d",M,N); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( pubkeys.size() != N ) + { + CCerror = strprintf("M.%d N.%d but pubkeys[%d]",M,N,(int32_t)pubkeys.size()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + for (i=0; i 0 ) + { + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,importgatewaypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeImportGatewayBindOpRet('B',coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype))); + } + CCerror = strprintf("cant find enough inputs"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); +} + +std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t claimvout,std::string rawburntx,std::vectorproof,CPubKey destpub) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()), burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction bindtx; CPubKey mypk; uint256 oracletxid,merkleroot,mhash,hashBlock,txid; std::vector vouts; + int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::string coin; struct CCcontract_info *cp,C; + std::vector pubkeys,publishers; std::vector txids; char str[128],burnaddr[64]; int64_t amount; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx)) + { + return std::string(""); + } + amount=burntx.vout[0].nValue; + LOGSTREAM("importgateway",CCLOG_DEBUG1, stream << "ImportGatewayDeposit ht." << height << " " << refcoin << " " << (double)amount/COIN << " numpks." << (int32_t)pubkeys.size() << std::endl); + if ( GetTransaction(bindtxid,bindtx,hashBlock,false) == 0 || (numvouts= bindtx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,bindtx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin ) + { + CCerror = strprintf("invalid coin - bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (komodo_txnotarizedconfirmed(bindtxid)==false) + { + CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + n = (int32_t)pubkeys.size(); + merkleroot = zeroid; + for (i=m=0; i leaftxids; + BitcoinGetProofMerkleRoot(proof, leaftxids); + MerkleBranch newBranch(0, leaftxids); + TxProof txProof = std::make_pair(burntxid, newBranch); + return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts))); +} + +std::string ImportGatewayWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction tx; CPubKey mypk,importgatewaypk,signerpk; uint256 txid,hashBlock,oracletxid,tmptokenid,tmpbindtxid,withdrawtxid; int32_t vout,numvouts; + int64_t nValue,inputs,CCchange=0,tmpamount; uint8_t funcid,K,M,N,taddr,prefix,prefix2,wiftype; std::string coin,hex; + std::vector msigpubkeys; char burnaddr[64],str[65],coinaddr[64]; struct CCcontract_info *cp,C; + std::vector > unspentOutputs; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp, 0); + + if( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || coin != refcoin ) + { + CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (komodo_txnotarizedconfirmed(bindtxid)==false) + { + CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + _GetCCaddress(coinaddr,EVAL_IMPORTGATEWAY,importgatewaypk); + SetCCunspents(unspentOutputs,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second.satoshis; + K=0; + if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && + (funcid=DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey))!=0 && (funcid=='W' || funcid=='P')) + { + if (funcid=='W' && DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmpbindtxid,coin,withdrawpub,tmpamount)=='W' + && refcoin==coin && tmpbindtxid==bindtxid) + { + CCerror = strprintf("unable to create withdraw, another withdraw pending"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + + else if (funcid=='P' && DecodeImportGatewayPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,hex)=='P' && + GetTransaction(withdrawtxid,tx,hashBlock,false)!=0 && (numvouts=tx.vout.size())>0 && DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmpbindtxid,coin,withdrawpub,tmpamount)=='W' + && refcoin==coin && tmpbindtxid==bindtxid) + { + CCerror = strprintf("unable to create withdraw, another withdraw pending"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + } + } + if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE+amount, 64) > 0 ) + { + mtx.vout.push_back(MakeCC1vout(EVAL_IMPORTGATEWAY,CC_MARKER_VALUE,importgatewaypk)); + mtx.vout.push_back(MakeCC1vout(EVAL_IMPORTGATEWAY,amount,importgatewaypk)); + return(FinalizeCCTx(0, cp, mtx, mypk, txfee,EncodeImportGatewayWithdrawOpRet('W',bindtxid,refcoin,withdrawpub,amount))); + } + CCerror = strprintf("cant find enough normal inputs"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); +} + +std::string ImportGatewayPartialSign(uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk,withdrawpub,signerpk,importgatewaypk; struct CCcontract_info *cp,C; CTransaction tx,tmptx; + std::vector > unspentOutputs; char funcid,str[65],burnaddr[64]; + int32_t numvouts; uint256 withdrawtxid,hashBlock,bindtxid,tokenid,oracletxid; std::string coin,tmphex; int64_t amount; + uint8_t K=0,M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp,0); + if (GetTransaction(lasttxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())<=0 + || (funcid=DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P')) + { + CCerror = strprintf("can't find last tx %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (funcid=='W') + { + withdrawtxid=lasttxid; + if (DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin) + { + CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (komodo_txnotarizedconfirmed(withdrawtxid)==false) + { + CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0) + { + CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' + || refcoin!=coin) + { + CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + } + else if (funcid=='P') + { + if (DecodeImportGatewayPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin) + { + CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(withdrawtxid,tmptx,hashBlock,false)==0 || (numvouts= tmptx.vout.size())<=0) + { + CCerror = strprintf("can't find withdraw tx %s",uint256_str(str,withdrawtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount)!='W' + || refcoin!=coin) + { + CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (komodo_txnotarizedconfirmed(withdrawtxid)==false) + { + CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0) + { + CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' + || refcoin!=coin) + { + CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + } + if (AddNormalinputs(mtx,mypk,txfee,3)!=0) + { + mtx.vin.push_back(CTxIn(tx.GetHash(),0,CScript())); + mtx.vout.push_back(MakeCC1vout(EVAL_IMPORTGATEWAY,CC_MARKER_VALUE,importgatewaypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeImportGatewayPartialOpRet('P',withdrawtxid,refcoin,K+1,mypk,hex))); + } + CCerror = strprintf("error adding funds for partialsign"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); +} + +std::string ImportGatewayCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk,importgatewaypk,signerpk,withdrawpub; struct CCcontract_info *cp,C; char funcid,str[65],burnaddr[64]; int64_t amount; + std::string coin,tmphex; CTransaction tx,tmptx; uint256 withdrawtxid,hashBlock,tokenid,bindtxid,oracletxid; int32_t numvouts; + uint8_t K=0,M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp,0); + if ( txfee == 0 ) + txfee = 10000; + if (GetTransaction(lasttxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())<=0 + || (funcid=DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P')) + { + CCerror = strprintf("invalid last txid %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (funcid=='W') + { + withdrawtxid=lasttxid; + if (DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin) + { + CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0) + { + CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (komodo_txnotarizedconfirmed(withdrawtxid)==false) + { + CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' + || refcoin!=coin) + { + CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + } + else if (funcid=='P') + { + if (DecodeImportGatewayPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin) + { + CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(withdrawtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())==0) + { + CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin) + { + CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,withdrawtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (komodo_txnotarizedconfirmed(withdrawtxid)==false) + { + CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0) + { + CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayBindOpRet(burnaddr,tmptx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' + || refcoin!=coin) + { + CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + } + if (AddNormalinputs(mtx,mypk,txfee,3)!=0) + { + mtx.vin.push_back(CTxIn(lasttxid,0,CScript())); + mtx.vout.push_back(MakeCC1vout(EVAL_IMPORTGATEWAY,CC_MARKER_VALUE,importgatewaypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeImportGatewayCompleteSigningOpRet('S',withdrawtxid,refcoin,K+1,hex))); + } + CCerror = strprintf("error adding funds for completesigning"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); +} + +std::string ImportGatewayMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk; struct CCcontract_info *cp,C; char str[65],burnaddr[64]; CTransaction tx; int32_t numvouts; + uint256 withdrawtxid,bindtxid,oracletxid,tokenid,hashBlock; std::string coin,hex; + uint8_t K,M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; int64_t amount; CPubKey withdrawpub; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + mypk = pubkey2pk(Mypubkey()); + if ( txfee == 0 ) + txfee = 10000; + if (GetTransaction(completetxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())<=0) + { + CCerror = strprintf("invalid completesigning txid %s",uint256_str(str,completetxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,hex)!='S' || refcoin!=coin) + { + CCerror = strprintf("cannot decode completesigning tx opret %s",uint256_str(str,completetxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (komodo_txnotarizedconfirmed(completetxid)==false) + { + CCerror = strprintf("gatewayscompletesigning tx not yet confirmed/notarized"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(withdrawtxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())==0) + { + CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin) + { + CCerror = strprintf("cannot decode withdraw tx opret %s\n",uint256_str(str,withdrawtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (GetTransaction(bindtxid,tx,hashBlock,false)==0 || (numvouts=tx.vout.size())<=0) + { + CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + else if (DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' + || refcoin!=coin) + { + CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if (AddNormalinputs(mtx,mypk,txfee,3)!=0) + { + mtx.vin.push_back(CTxIn(completetxid,0,CScript())); + mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeImportGatewayMarkDoneOpRet('M',withdrawtxid,refcoin,completetxid))); + } + CCerror = strprintf("error adding funds for markdone"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); +} + +UniValue ImportGatewayPendingDeposits(uint256 bindtxid,std::string refcoin) +{ + UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,hex,pub; + CPubKey mypk,importgatewaypk,destpub; std::vector pubkeys,publishers; std::vector txids; + uint256 tmpbindtxid,hashBlock,txid,oracletxid,burntxid; uint8_t M,N,taddr,prefix,prefix2,wiftype; + char burnaddr[65],coinaddr[65],str[65],destaddr[65],txidaddr[65]; std::vector proof; + int32_t numvouts,vout,claimvout,height; int64_t nValue,amount; struct CCcontract_info *cp,C; + std::vector > unspentOutputs; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp,0); + _GetCCaddress(coinaddr,EVAL_IMPORTGATEWAY,mypk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,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("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + SetCCunspents(unspentOutputs,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second.satoshis; + if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size())>0 && + DecodeImportGatewayDepositOpRet(tx.vout[numvouts-1].scriptPubKey,tmpbindtxid,coin,publishers,txids,height,burntxid,claimvout,hex,proof,destpub,amount) == 'D' + && tmpbindtxid==bindtxid && refcoin == coin && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0) + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("burntxid",uint256_str(str,burntxid))); + obj.push_back(Pair("deposittxid",uint256_str(str,txid))); + CCtxidaddr(txidaddr,txid); + obj.push_back(Pair("deposittxidaddr",txidaddr)); + _GetCCaddress(destaddr,EVAL_TOKENS,destpub); + obj.push_back(Pair("depositaddr",burnaddr)); + obj.push_back(Pair("tokens_destination_address",destaddr)); + pub=HexStr(destpub); + obj.push_back(Pair("claim_pubkey",pub)); + obj.push_back(Pair("amount",(double)amount/COIN)); + obj.push_back(Pair("confirmed_or_notarized",komodo_txnotarizedconfirmed(txid))); + pending.push_back(obj); + } + } + result.push_back(Pair("coin",refcoin)); + result.push_back(Pair("pending",pending)); + return(result); +} + +UniValue ImportGatewayPendingWithdraws(uint256 bindtxid,std::string refcoin) +{ + UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,hex; CPubKey mypk,importgatewaypk,withdrawpub,signerpk; + std::vector msigpubkeys; uint256 hashBlock,txid,tmpbindtxid,tmptokenid,oracletxid,withdrawtxid; uint8_t K,M,N,taddr,prefix,prefix2,wiftype; + char funcid,burnaddr[65],coinaddr[65],destaddr[65],str[65],withaddr[65],numstr[32],signeraddr[65],txidaddr[65]; + int32_t i,n,numvouts,vout,queueflag; int64_t amount,nValue; struct CCcontract_info *cp,C; + std::vector > unspentOutputs; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp,0); + _GetCCaddress(coinaddr,EVAL_IMPORTGATEWAY,importgatewaypk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,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("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + n = msigpubkeys.size(); + queueflag = 0; + for (i=0; i >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second.satoshis; + K=0; + if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && + (funcid=DecodeImportGatewayOpRet(tx.vout[numvouts-1].scriptPubKey))!=0 && (funcid=='W' || funcid=='P') && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0) + { + if (funcid=='W') + { + if (DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmpbindtxid,coin,withdrawpub,amount)==0 || refcoin!=coin || tmpbindtxid!=bindtxid) continue; + } + else if (funcid=='P') + { + if (DecodeImportGatewayPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,hex)!='P' || GetTransaction(withdrawtxid,tx,hashBlock,false)==0 + || (numvouts=tx.vout.size())<=0 || DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmpbindtxid,coin,withdrawpub,amount)!='W' + || refcoin!=coin || tmpbindtxid!=bindtxid) + continue; + } + Getscriptaddress(destaddr,tx.vout[1].scriptPubKey); + GetCustomscriptaddress(withaddr,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG,taddr,prefix,prefix2); + if ( strcmp(destaddr,coinaddr) == 0 ) + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("withdrawtxid",uint256_str(str,tx.GetHash()))); + CCCustomtxidaddr(txidaddr,tx.GetHash(),taddr,prefix,prefix2); + obj.push_back(Pair("withdrawtxidaddr",txidaddr)); + obj.push_back(Pair("withdrawaddr",withaddr)); + sprintf(numstr,"%.8f",(double)tx.vout[1].nValue/COIN); + obj.push_back(Pair("amount",numstr)); + obj.push_back(Pair("confirmed_or_notarized",komodo_txnotarizedconfirmed(tx.GetHash()))); + if ( queueflag != 0 ) + { + obj.push_back(Pair("depositaddr",burnaddr)); + GetCustomscriptaddress(signeraddr,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG,taddr,prefix,prefix2); + obj.push_back(Pair("signeraddr",signeraddr)); + } + if (N>1) + { + obj.push_back(Pair("number_of_signs",K)); + obj.push_back(Pair("last_txid",uint256_str(str,txid))); + if (K>0) obj.push_back(Pair("hex",hex)); + } + pending.push_back(obj); + } + } + } + result.push_back(Pair("coin",refcoin)); + result.push_back(Pair("pending",pending)); + result.push_back(Pair("queueflag",queueflag)); + return(result); +} + +UniValue ImportGatewayProcessedWithdraws(uint256 bindtxid,std::string refcoin) +{ + UniValue result(UniValue::VOBJ),processed(UniValue::VARR); CTransaction tx; std::string coin,hex; + CPubKey mypk,importgatewaypk,withdrawpub; std::vector msigpubkeys; + uint256 withdrawtxid,hashBlock,txid,tmptokenid,oracletxid; uint8_t K,M,N,taddr,prefix,prefix2,wiftype; + char burnaddr[65],coinaddr[65],str[65],numstr[32],withaddr[65],txidaddr[65]; + int32_t i,n,numvouts,vout,queueflag; int64_t nValue,amount; struct CCcontract_info *cp,C; + std::vector > unspentOutputs; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + mypk = pubkey2pk(Mypubkey()); + importgatewaypk = GetUnspendable(cp,0); + _GetCCaddress(coinaddr,EVAL_IMPORTGATEWAY,importgatewaypk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,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("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + n = msigpubkeys.size(); + queueflag = 0; + for (i=0; i >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second.satoshis; + if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && + DecodeImportGatewayCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,hex) == 'S' && refcoin == coin && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0) + { + if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 + && DecodeImportGatewayWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxid,coin,withdrawpub,amount) == 'W' || refcoin!=coin) + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("completesigningtxid",uint256_str(str,txid))); + obj.push_back(Pair("withdrawtxid",uint256_str(str,withdrawtxid))); + CCCustomtxidaddr(txidaddr,withdrawtxid,taddr,prefix,prefix2); + obj.push_back(Pair("withdrawtxidaddr",txidaddr)); + GetCustomscriptaddress(withaddr,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG,taddr,prefix,prefix2); + obj.push_back(Pair("withdrawaddr",withaddr)); + obj.push_back(Pair("confirmed_or_notarized",komodo_txnotarizedconfirmed(txid))); + sprintf(numstr,"%.8f",(double)tx.vout[1].nValue/COIN); + obj.push_back(Pair("amount",numstr)); + obj.push_back(Pair("hex",hex)); + processed.push_back(obj); + } + } + } + result.push_back(Pair("coin",refcoin)); + result.push_back(Pair("processed",processed)); + result.push_back(Pair("queueflag",queueflag)); + return(result); +} + +UniValue ImportGatewayList() +{ + UniValue result(UniValue::VARR); std::vector > addressIndex; + struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid; CTransaction vintx; std::string coin; + char str[65],burnaddr[64]; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + SetCCtxids(addressIndex,cp->unspendableCCaddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + txid = it->first.txhash; + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + { + if ( vintx.vout.size() > 0 && DecodeImportGatewayBindOpRet(burnaddr,vintx.vout[vintx.vout.size()-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 0 ) + { + result.push_back(uint256_str(str,txid)); + } + } + } + return(result); +} + +UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey) +{ + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid; CTransaction tx; + std::string coin; int64_t numvouts; char str[65],addr[65],burnaddr[65]; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector msigpubkeys; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B') + { + CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + GetCustomscriptaddress(addr,CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG,taddr,prefix,prefix2); + result.push_back(Pair("result","success")); + result.push_back(Pair("address",addr)); + return(result); +} + +UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key) +{ + UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid; CTransaction tx; + std::string coin,priv; int64_t numvouts; char str[65],addr[65],burnaddr[65]; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector msigpubkeys; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B') + { + CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + + priv=EncodeCustomSecret(key,wiftype); + result.push_back(Pair("result","success")); + result.push_back(Pair("privkey",priv.c_str())); + return(result); +} + +UniValue ImportGatewayInfo(uint256 bindtxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],burnaddr[64],gatewaystokens[64]; + uint8_t M,N; std::vector pubkeys; uint8_t taddr,prefix,prefix2,wiftype; uint256 oracletxid,hashBlock; CTransaction tx; + CPubKey ImportGatewaypk; struct CCcontract_info *cp,C; int32_t i; int64_t numvouts,remaining; std::vector msigpubkeys; + + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + ImportGatewaypk = GetUnspendable(cp,0); + GetTokensCCaddress(cp,gatewaystokens,ImportGatewaypk); + if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + { + CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid)); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( DecodeImportGatewayBindOpRet(burnaddr,tx.vout[numvouts-1].scriptPubKey,coin,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B') + { + CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str()); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(""); + } + if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 ) + { + result.push_back(Pair("result","success")); + result.push_back(Pair("name","ImportGateway")); + burnaddr[0] = 0; + if ( tx.vout.size() > 0 && DecodeImportGatewayBindOpRet(burnaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 0 && M <= N && N > 0 ) + { + result.push_back(Pair("M",M)); + result.push_back(Pair("N",N)); + for (i=0; i > 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 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 data; cp = CCinit(&C,EVAL_ORACLES); CCtxidaddr(markeraddr,origtxid); if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 ) diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 018025e5a..051129020 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -35,8 +35,7 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction b mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload)); mtx.vout = payouts; auto importData = E_MARSHAL(ss << proof; ss << burnTx); - mtx.vout.insert(mtx.vout.begin(), CTxOut(0, CScript() << OP_RETURN << importData)); - + mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << importData)); if (nExpiryHeightOverride != 0) mtx.nExpiryHeight = nExpiryHeightOverride; //this is for construction of the tx used for validating importtx return CTransaction(mtx); @@ -53,29 +52,97 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb return CTxOut(value, CScript() << OP_RETURN << opret); } +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, + uint256 bindtxid,std::vector publishers,std::vector txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub) +{ + std::vector 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 payouts,std::vector rawproof,std::string srcaddr, + std::string receipt) +{ + std::vector 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 &payouts) { std::vector 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(importTx.vout.begin()+1, importTx.vout.end()); + payouts = std::vector(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&rawproof) +bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector&rawproof) { - std::vector burnOpret; uint32_t ccid = 0; + std::vector 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 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 &publishers,std::vector &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub) +{ + std::vector 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)); } diff --git a/src/importcoin.h b/src/importcoin.h index 947debcd8..8cb8dbc58 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -29,10 +29,15 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof); +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, + uint256 bindtxid,std::vector publishers,std::vectortxids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub); +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof,std::string srcaddr, + std::string receipt); -bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector &rawproof); -bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx, - std::vector &payouts); +bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector &rawproof); +bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt); +bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub); +bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,std::vector &payouts); bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state); diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 710f99f09..fa795e0e5 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -24,6 +24,7 @@ #include "consensus/validation.h" #include "cc/eval.h" #include "cc/utils.h" +#include "cc/CCinclude.h" #include "main.h" #include "primitives/transaction.h" #include "rpc/server.h" @@ -35,6 +36,7 @@ #include "script/standard.h" #include "key_io.h" +#include "cc/CCImportGateway.h" #include #include @@ -42,19 +44,23 @@ using namespace std; +#define RETURN_IF_ERROR(CCerror) if ( CCerror != "" ) { ERR_RESULT(CCerror); return(result); } +#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x)); + +extern std::string CCerror; extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; +int32_t ensure_CCrequirements(uint8_t evalcode); int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); extern std::string ASSETCHAINS_SELFIMPORT; -uint256 Parseuint256(char *hexstr); std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx); int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount); -std::string MakeGatewaysImportTx(uint64_t txfee, uint256 bindtxid, int32_t height, std::string refcoin, std::vectorproof, std::string rawburntx, int32_t ivout, uint256 burntxid); +std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector vouts); UniValue assetchainproof(const UniValue& params, bool fHelp) { @@ -338,7 +344,6 @@ UniValue selfimport(const UniValue& params, bool fHelp) source = params[5].get_str(); } */ - if (source == "BEAM") { if (ASSETCHAINS_BEAMPORT == 0) @@ -398,14 +403,348 @@ UniValue selfimport(const UniValue& params, bool fHelp) // source is external coin is the assetchains symbol in the burnTx OP_RETURN // burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent - std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, sourcetxid); + //std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, ""); - result.push_back(Pair("hex", hextx)); - result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx + // result.push_back(Pair("hex", hextx)); + // result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx } return result; } +UniValue importdual(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); + CMutableTransaction mtx; + std::string hex,source,sourceaddr,destaddr,burntxid; uint64_t burnAmount; + CPubKey destpub; std::vector 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 pubkey; + std::string hex,coin; int32_t i,M,N; std::vector 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 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 rawproof; + std::string hex,coin,rawburntx; int32_t height,burnvout; + CPubKey destpub; std::vector 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 rawproof; + std::string hex,coin,rawburntx; int64_t amount; int32_t height,burnvout; + CPubKey destpub; std::vector 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(&dest); + if (!keyID) { + throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); + } + CKey vchSecret; + // if (!pwalletMain->GetKey(*keyID, vchSecret)) { + // throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); + //} + return(ImportGatewayDumpPrivKey(bindtxid,vchSecret)); +} + UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -536,9 +875,9 @@ UniValue getimports(const UniValue& params, bool fHelp) UniValue objTx(UniValue::VOBJ); objTx.push_back(Pair("txid",tx.GetHash().ToString())); TxProof proof; CTransaction burnTx; std::vector 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())); } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index a48ef6cb1..fc34a2a3f 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -354,6 +354,21 @@ static const CRPCCommand vRPCCommands[] = { "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true }, { "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true }, { "crosschain", "selfimport", &selfimport, true }, + { "crosschain", "importdual", &importdual, true }, + //ImportGateway + { "crosschain", "importgatewayddress", &importgatewayaddress, true }, + { "crosschain", "importgatewayinfo", &importgatewayinfo, true }, + { "crosschain", "importgatewaybind", &importgatewaybind, true }, + { "crosschain", "importgatewaydeposit", &importgatewaydeposit, true }, + { "crosschain", "importgatewaywithdraw", &importgatewaywithdraw, true }, + { "crosschain", "importgatewaypartialsign", &importgatewaypartialsign, true }, + { "crosschain", "importgatewaycompletesigning", &importgatewaycompletesigning, true }, + { "crosschain", "importgatewaymarkdone", &importgatewaymarkdone, true }, + { "crosschain", "importgatewaypendingdeposits", &importgatewaypendingdeposits, true }, + { "crosschain", "importgatewaypendingwithdraws", &importgatewaypendingwithdraws, true }, + { "crosschain", "importgatewayprocessed", &importgatewayprocessed, true }, + + /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 79a12bb7b..d8fd0e736 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -314,7 +314,6 @@ extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp); extern UniValue channelsclose(const UniValue& params, bool fHelp); extern UniValue channelsrefund(const UniValue& params, bool fHelp); - //extern UniValue tokenswapask(const UniValue& params, bool fHelp); //extern UniValue tokenfillswap(const UniValue& params, bool fHelp); extern UniValue faucetfund(const UniValue& params, bool fHelp); @@ -435,6 +434,18 @@ extern UniValue invalidateblock(const UniValue& params, bool fHelp); extern UniValue reconsiderblock(const UniValue& params, bool fHelp); extern UniValue getspentinfo(const UniValue& params, bool fHelp); extern UniValue selfimport(const UniValue& params, bool fHelp); +extern UniValue importdual(const UniValue& params, bool fHelp); +extern UniValue importgatewayaddress(const UniValue& params, bool fHelp); +extern UniValue importgatewayinfo(const UniValue& params, bool fHelp); +extern UniValue importgatewaybind(const UniValue& params, bool fHelp); +extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp); +extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp); +extern UniValue importgatewaypartialsign(const UniValue& params, bool fHelp); +extern UniValue importgatewaycompletesigning(const UniValue& params, bool fHelp); +extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp); +extern UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp); +extern UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp); +extern UniValue importgatewayprocessed(const UniValue& params, bool fHelp); extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d720cf33f..77b2fb62d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5858,6 +5858,19 @@ UniValue tokenaddress(const UniValue& params, bool fHelp) return(CCaddress(cp,(char *)"Tokens", pubkey)); } +UniValue importgatewayaddress(const UniValue& params, bool fHelp) +{ + struct CCcontract_info *cp,C; std::vector pubkey; + cp = CCinit(&C,EVAL_IMPORTGATEWAY); + if ( fHelp || params.size() > 1 ) + throw runtime_error("importgatewayddress [pubkey]\n"); + if ( ensure_CCrequirements(0) < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + if ( params.size() == 1 ) + pubkey = ParseHex(params[0].get_str().c_str()); + return(CCaddress(cp,(char *)"ImportGateway", pubkey)); +} + UniValue marmara_poolpayout(const UniValue& params, bool fHelp) { int32_t firstheight; double perc; char *jsonstr; @@ -7994,7 +8007,6 @@ UniValue test_heirmarker(const UniValue& params, bool fHelp) return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); } - UniValue test_burntx(const UniValue& params, bool fHelp) { // make fake token tx: From ba0fda90b278fd51cf1b2b444ea6bea6916dc9a8 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:09:18 -1100 Subject: [PATCH 12/56] Small changes --- src/komodo_gateway.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index ba15746e0..5aabbffd5 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1551,7 +1551,7 @@ void komodo_passport_iteration() extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_MAXCHANGE (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 issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) @@ -1815,7 +1815,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i break; } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(1,block.GetHash(),i,prevbits[i]); break; + } } else if ( maxflag < 0 && localbits[i] > prevbits[i] ) { @@ -1828,7 +1831,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i break; } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(-1,block.GetHash(),i,prevbits[i]); break; + } } } } From ae7c5ee027aa4db23e7b919f77d413bc9506655e Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:13:07 -1100 Subject: [PATCH 13/56] Fix declaration --- src/komodo_gateway.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5aabbffd5..44ec7c9f3 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1720,11 +1720,10 @@ 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,uint256 blockhash,int32_t ind,uint32_t pricebits) +{ + +} int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { @@ -1816,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block.GetHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block.GetBlockHash(),i,prevbits[i]); break; } } @@ -1832,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block.GetHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block.GetBlockHash(),i,prevbits[i]); break; } } From 6618a43e8a8e137243572ccfd8d2b10dec1d49c2 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:14:07 -1100 Subject: [PATCH 14/56] -> --- src/komodo_gateway.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 44ec7c9f3..82491941f 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1815,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block.GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block->GetBlockHash(),i,prevbits[i]); break; } } @@ -1831,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block.GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block->GetBlockHash(),i,prevbits[i]); break; } } From 137f51651603c5a681699c6d3c9cd7202a55f9c1 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:16:07 -1100 Subject: [PATCH 15/56] GetHash() --- src/komodo_gateway.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 82491941f..3db8bfb1a 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1815,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block->GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block->GetHash(),i,prevbits[i]); break; } } @@ -1831,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block->GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block->GetHash(),i,prevbits[i]); break; } } From a2cdadf17de5e7c0b06e69f21ee3612075d52ff5 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:43:11 -1100 Subject: [PATCH 16/56] Add auto resync for local prices --- src/komodo_gateway.h | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 3db8bfb1a..70a69ebc8 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1720,17 +1720,33 @@ 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. */ -void komodo_queuelocalprice(int32_t dir,uint256 blockhash,int32_t ind,uint32_t pricebits) + +struct komodo_extremeprice { - + uint256 blockhash; + uint32_t pricebits,timestamp; + int32_t height; + int16_t dir,ind; +} ExtremePrice; + +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 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 vopret; char maxflags[KOMODO_MAXPRICES]; uint245 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 ) { @@ -1815,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block->GetHash(),i,prevbits[i]); + komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); break; } } @@ -1831,7 +1847,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block->GetHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,nHeight,block->nTime,bhash,i,prevbits[i]); break; } } @@ -1849,6 +1865,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); @@ -2129,7 +2150,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 ) @@ -2187,6 +2208,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 ht.%d\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits,height); + if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) + pindex->nStatus &= ~BLOCK_FAILED_MASK; + else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex()); + } + } // 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 From 43b18d52599059914b249e9c62a74c68cd02ec77 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:47:17 -1100 Subject: [PATCH 17/56] Fix --- src/komodo_gateway.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 70a69ebc8..9afc9845c 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1742,7 +1742,7 @@ void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint25 int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { int32_t testchain_exemption = 0; - std::vector vopret; char maxflags[KOMODO_MAXPRICES]; uint245 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; + std::vector 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 ) { @@ -1867,7 +1867,7 @@ 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); + 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); @@ -2212,10 +2212,10 @@ void komodo_cbopretupdate(int32_t forceflag) { 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 ht.%d\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits,height); + 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()); + 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 From cd8d41c5f8301a7f8dba1056168926562135d7a2 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Wed, 10 Apr 2019 18:07:53 +0200 Subject: [PATCH 18/56] Fix broken build --- src/cc/import.cpp | 84 +++-------------------------------------------- 1 file changed, 4 insertions(+), 80 deletions(-) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 157fa6888..14f359398 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -33,86 +33,10 @@ uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::ve 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,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); - -char *nonportable_path(char *str) -{ - int32_t i; - for (i=0; str[i]!=0; i++) - if ( str[i] == '/' ) - str[i] = '\\'; - return(str); -} - -char *portable_path(char *str) -{ -#ifdef _WIN32 - return(nonportable_path(str)); -#else -#ifdef __PNACL - /*int32_t i,n; - if ( str[0] == '/' ) - return(str); - else - { - n = (int32_t)strlen(str); - for (i=n; i>0; i--) - str[i] = str[i-1]; - str[0] = '/'; - str[n+1] = 0; - }*/ -#endif - return(str); -#endif -} - -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - //printf("loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} - -void *filestr(long *allocsizep,char *_fname) -{ - long filesize = 0; char *fname,*buf = 0; void *retptr; - *allocsizep = 0; - fname = (char *)malloc(strlen(_fname)+1); - strcpy(fname,_fname); - retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); - free(fname); - return(retptr); -} +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 From 2056c8727be31a38ae563bc207e4b3b8df26e1ae Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 05:14:54 -1100 Subject: [PATCH 19/56] Token peg ideas --- src/cc/pegs.cpp | 6 ++++++ src/cc/prices.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 00d76d8fd..38933ebdc 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -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 "BTCUSD, 1" + that will specify using the BTCUSD price, so now we need to create a based way to do tokenbid/tokenask. For a 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 */ diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index ce257d33f..19194d16f 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -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 + */ From 9b62776a8be938892056378868a4d2ff9f7d6d77 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 05:27:06 -1100 Subject: [PATCH 20/56] -conflict --- src/rpc/crosschain.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 74ac53c44..0feb5173c 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -413,9 +413,9 @@ UniValue selfimport(const UniValue& params, bool fHelp) return result; } -<<<<<<< HEAD bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); -======= + + UniValue importdual(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); @@ -749,7 +749,6 @@ UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp) //} return(ImportGatewayDumpPrivKey(bindtxid,vchSecret)); } ->>>>>>> FSM UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { From 2993a76b3050cd885a9f58f614264f9b665eb941 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 20:39:55 -1100 Subject: [PATCH 21/56] komodo_pricesinit --- src/komodo_defs.h | 1 + src/komodo_gateway.h | 16 ++++++++++++++++ src/komodo_utils.h | 1 + 3 files changed, 18 insertions(+) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 9377ea276..31dde4a24 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -85,5 +85,6 @@ int tx_height( const uint256 &hash ); extern std::vector vWhiteListAddress; void komodo_netevent(std::vector payload); int32_t komodo_priceind(char *symbol); +void komodo_pricesinit(); #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 9afc9845c..2098d30c2 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2526,3 +2526,19 @@ int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprice return(price); } +void komodo_pricesinit() +{ + FILE *fp; char symbol[65]; int32_t i; + boost::filesystem::path pricefname,pricesdir = GetDataDir() / "prices"; + if (!boost::filesystem::exists(pricesdir)) + { + boost::filesystem::create_directories(pricesdir); + for (i=0; i Date: Wed, 10 Apr 2019 20:53:00 -1100 Subject: [PATCH 22/56] Make fp for each file --- src/komodo_gateway.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 2098d30c2..5ac8ea540 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1549,10 +1549,11 @@ void komodo_passport_iteration() } extern std::vector 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 13 #define KOMODO_MAXPRICES 2048 +#define PRICES_SMOOTHWIDTH 1 #define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) @@ -1696,10 +1697,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()); } @@ -1788,7 +1789,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 Date: Wed, 10 Apr 2019 20:59:20 -1100 Subject: [PATCH 23/56] Fputc --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5ac8ea540..5f9a2b8b4 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2541,7 +2541,7 @@ void komodo_pricesinit() pricefname = pricesdir / symbol; fp = fopen(pricefname.string().c_str(), "wb+"); fseek(fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(int64_t) * 3,SEEK_SET); - fputc(fp,0); + fputc(0,fp); fflush(fp); } } From 169bffa3e4231ab06172df5cd6e0892f2e98d248 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 21:06:56 -1100 Subject: [PATCH 24/56] +print --- src/komodo_gateway.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5f9a2b8b4..f5ee16f7b 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2530,7 +2530,8 @@ int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprice void komodo_pricesinit() { FILE *fp; char symbol[65]; int32_t i; - boost::filesystem::path pricefname,pricesdir = GetDataDir() / ASSETCHAINS_SYMBOL / "prices"; + 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); From 027662268df016a645de71a6c5ff21dd3db4da4c Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 21:11:27 -1100 Subject: [PATCH 25/56] Move pricesinit --- src/bitcoind.cpp | 2 ++ src/komodo_utils.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 4e010d28e..68e0da8b3 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -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"); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 700615ee1..043d7282e 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2082,7 +2082,6 @@ void komodo_args(char *argv0) extralen += symbol.size(); } } - komodo_pricesinit(); komodo_cbopretupdate(1); // will set Mineropret fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n"); } From 8f5feded98166b02b00a18e488a31c5a0bdc1884 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 22:46:42 -1100 Subject: [PATCH 26/56] fp0 --- src/komodo_gateway.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index f5ee16f7b..e128043ff 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2529,7 +2529,7 @@ int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprice void komodo_pricesinit() { - FILE *fp; char symbol[65]; int32_t i; + FILE *fp,*fp0 = 0; char symbol[65]; int32_t i; boost::filesystem::path pricefname,pricesdir = GetDataDir() / "prices"; fprintf(stderr,"pricesinit (%s)\n",pricesdir.string().c_str()); if (!boost::filesystem::exists(pricesdir)) @@ -2539,11 +2539,21 @@ void komodo_pricesinit() { if ( komodo_pricename(symbol,i) == 0 ) break; + if ( i == 0 ) + strcpy(symbol,"rawprices"); pricefname = pricesdir / symbol; fp = fopen(pricefname.string().c_str(), "wb+"); + if ( i == 0 ) + fp0 = fp; fseek(fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(int64_t) * 3,SEEK_SET); fputc(0,fp); fflush(fp); } + if ( fp0 != 0 && i > 0 ) + { + fseek(fp0,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); + fputc(0,fp0); + fflush(fp0); + } } } From 6178eb87c47e643f73f7918ed120e162c342ae91 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Thu, 11 Apr 2019 18:13:39 +0800 Subject: [PATCH 27/56] fix dpow --- src/komodo.h | 4 ++-- src/main.cpp | 57 ++++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/komodo.h b/src/komodo.h index 3ceb29cc3..15c1e5c02 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -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 ) diff --git a/src/main.cpp b/src/main.cpp index faa9e6a9c..47b089ca8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4239,37 +4239,36 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // 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"); + + 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; + } + 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. From a766a16bb34ee2cb50fa657ab6cc2fa879a5db4b Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Thu, 11 Apr 2019 19:13:37 +0800 Subject: [PATCH 28/56] fix better --- src/main.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 47b089ca8..3d155feb3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4233,22 +4233,22 @@ 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->GetHeight() < notarizedht ) + { + fprintf(stderr,"pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexFork->GetHeight(),notarizedht); + return false; + } // - 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"); - - 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; - } - - if (reorgLength > MAX_REORG_LENGTH) + if ( reorgLength > MAX_REORG_LENGTH) { auto msg = strprintf(_( "A block chain reorganization has been detected that would roll back %d blocks! " From 0ac427ee97842283e3369278f61ab998f12dfd8e Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 00:28:35 -1100 Subject: [PATCH 29/56] Prices update --- src/komodo_defs.h | 3 ++ src/komodo_gateway.h | 92 +++++++++++++++++++++++++++++--------------- src/main.cpp | 2 + 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 31dde4a24..d1749def8 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -84,7 +84,10 @@ extern char NOTARYADDRS[64][64]; int tx_height( const uint256 &hash ); extern std::vector vWhiteListAddress; void komodo_netevent(std::vector payload); + +#define PRICES_SMOOTHWIDTH 1 int32_t komodo_priceind(char *symbol); void komodo_pricesinit(); +void komodo_pricesupdate(int32_t height,CBlock *pblock); #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index e128043ff..fac601fbc 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1548,6 +1548,7 @@ void komodo_passport_iteration() } } + extern std::vector Mineropret; // opreturn data set by the data gathering code #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 @@ -1563,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); @@ -1575,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 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 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); @@ -1722,13 +1744,6 @@ CScript komodo_mineropret(int32_t nHeight) */ -struct komodo_extremeprice -{ - uint256 blockhash; - uint32_t pricebits,timestamp; - int32_t height; - int16_t dir,ind; -} ExtremePrice; void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits) { @@ -2529,7 +2544,7 @@ int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprice void komodo_pricesinit() { - FILE *fp,*fp0 = 0; char symbol[65]; int32_t i; + int32_t i; boost::filesystem::path pricefname,pricesdir = GetDataDir() / "prices"; fprintf(stderr,"pricesinit (%s)\n",pricesdir.string().c_str()); if (!boost::filesystem::exists(pricesdir)) @@ -2537,23 +2552,38 @@ void komodo_pricesinit() boost::filesystem::create_directories(pricesdir); for (i=0; i 0 ) + if ( i > 0 && PRICES[0].fp != 0 ) { - fseek(fp0,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); - fputc(0,fp0); - fflush(fp0); + 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; + int32_t i; uint64_t seed; uint32_t rawprices[KOMODO_MAXPRICES]; + if ( numprices == 0 ) + numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); + if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) + { + for (i=0; iGetHeight(),pblock); if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 ) komodo_activate_sapling(pindexNew); return true; From c8d0608674d460bc9542a774891748594401afbd Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 00:35:13 -1100 Subject: [PATCH 30/56] PRICES[i]. --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index fac601fbc..27eda9d5c 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2556,7 +2556,7 @@ void komodo_pricesinit() break; if ( i == 0 ) strcpy(PRICES[i].symbol,"rawprices"); - pricefname = pricesdir / symbol; + pricefname = pricesdir / PRICES[i].symbol; PRICES[i].fp = fopen(pricefname.string().c_str(), "wb+"); fseek(PRICES[i].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(int64_t) * 3,SEEK_SET); fputc(0,PRICES[i].fp); From 348c7a970cc71d58055c6ed9d75af1de13e2a9c0 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 00:42:31 -1100 Subject: [PATCH 31/56] Update raw prices --- src/komodo_defs.h | 1 - src/komodo_gateway.h | 6 ++++++ src/main.cpp | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index d1749def8..ebfadee69 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -88,6 +88,5 @@ void komodo_netevent(std::vector payload); #define PRICES_SMOOTHWIDTH 1 int32_t komodo_priceind(char *symbol); void komodo_pricesinit(); -void komodo_pricesupdate(int32_t height,CBlock *pblock); #endif diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 27eda9d5c..625cdc6b5 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2582,6 +2582,12 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) for (i=0; i Date: Thu, 11 Apr 2019 02:48:20 -1100 Subject: [PATCH 32/56] Calc correlated and smoothed each block --- src/komodo_gateway.h | 66 +++++++++++++++++++++++++++++++++++------- src/rpc/blockchain.cpp | 23 ++++++++------- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 625cdc6b5..837a82570 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2516,9 +2516,11 @@ 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 }; + +int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip) { - //const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 }; int32_t i; int64_t sum=0,nonzprice,price; if ( PRICES_DAYWINDOW < 2 ) return(0); @@ -2533,12 +2535,9 @@ 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 sum += nonzprice; } price = sum / PRICES_DAYWINDOW; - // improve smoothing with correlated2 processing - // price = smooth(correlated2,PRICES_DAYWINDOW,price/daywindow) * PRICES_DAYWINDOW; return(price); } @@ -2573,20 +2572,67 @@ void komodo_pricesinit() void komodo_pricesupdate(int32_t height,CBlock *pblock) { - static int numprices; - int32_t i; uint64_t seed; uint32_t rawprices[KOMODO_MAXPRICES]; + static int numprices; static uint32_t *ptr32,*ptr64; + int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[4]; + width = (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); + } if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) { - for (i=0; i width ) + { + 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 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 + { + fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * 3 * sizeof(int64_t),SEEK_SET); + if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*3,PRICES[ind].fp) == PRICES_DAYWINDOW*3 ) + { + if ( (smoothed= komodo_pricesmoothed(&ptr64[PRICES_DAYWINDOW*3-1],-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 + { + fprintf(stderr,"%.4f ",(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,"numprices mismatch\n"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index fc9a71fe2..87f2658cd 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -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_pricesmoothed(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,7 +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; + int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; uint32_t rawprices[1440*6],*ptr; //daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1; //pricedata = (uint32_t *)calloc(sizeof(*prices)*3,numblocks + daywindow*2 + PRICES_SMOOTHWIDTH); width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH; @@ -1205,20 +1205,21 @@ 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); + //correlated2 = (int64_t *)calloc(sizeof(*correlated2),width); for (i=0; i2; i++,ht--) @@ -1287,14 +1288,14 @@ UniValue prices(const UniValue& params, bool fHelp) { offset = j*width + i; rngval = (rngval*11109 + 13849); - correlated2[i] = prices[offset]; + //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"); } for (i=0; i Date: Thu, 11 Apr 2019 02:49:33 -1100 Subject: [PATCH 33/56] Int64 --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 837a82570..8bc639050 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2572,7 +2572,7 @@ void komodo_pricesinit() void komodo_pricesupdate(int32_t height,CBlock *pblock) { - static int numprices; static uint32_t *ptr32,*ptr64; + static int numprices; static uint32_t *ptr32; static int64_t *ptr64; int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[4]; width = (2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); if ( numprices == 0 ) From 1862321861e745a1dfa3ed50d5366e299cbfc1ef Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 02:52:49 -1100 Subject: [PATCH 34/56] Priceave --- src/komodo_gateway.h | 4 ++-- src/rpc/blockchain.cpp | 19 +++---------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 8bc639050..ce89cea35 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2519,7 +2519,7 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters) // http://www.holoborodko.com/pavel/numerical-methods/noise-robust-smoothing-filter/ //const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 }; -int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip) +int64_t komodo_priceave(int64_t *correlated,int32_t cskip) { int32_t i; int64_t sum=0,nonzprice,price; if ( PRICES_DAYWINDOW < 2 ) @@ -2615,7 +2615,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * 3 * sizeof(int64_t),SEEK_SET); if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*3,PRICES[ind].fp) == PRICES_DAYWINDOW*3 ) { - if ( (smoothed= komodo_pricesmoothed(&ptr64[PRICES_DAYWINDOW*3-1],-3)) > 0 ) + if ( (smoothed= komodo_priceave(&ptr64[PRICES_DAYWINDOW*3-1],-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) ) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 87f2658cd..07cb8a26d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -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 komodo_priceave(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); @@ -1186,8 +1186,6 @@ 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; uint32_t rawprices[1440*6],*ptr; - //daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1; - //pricedata = (uint32_t *)calloc(sizeof(*prices)*3,numblocks + daywindow*2 + PRICES_SMOOTHWIDTH); width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH; komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1); if ( firstheight < width ) @@ -1205,21 +1203,15 @@ 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; i2; i++,ht--) { @@ -1288,14 +1278,13 @@ 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"); } for (i=0; i Date: Thu, 11 Apr 2019 21:59:04 +0800 Subject: [PATCH 35/56] add node ban for pushing attacking chain --- src/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3d155feb3..5964b33d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3904,7 +3904,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. @@ -4240,7 +4241,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo if ( pindexFork->GetHeight() < notarizedht ) { fprintf(stderr,"pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexFork->GetHeight(),notarizedht); - return false; + 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, From 11d424de8167c9229844b7bdd3957401680cb07e Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 03:20:04 -1100 Subject: [PATCH 36/56] +print --- src/komodo_gateway.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index ce89cea35..5d96eea06 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2580,12 +2580,13 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) 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); + fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); } if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) { - //for (i=0; i Date: Thu, 11 Apr 2019 03:23:38 -1100 Subject: [PATCH 37/56] Open files always --- src/komodo_gateway.h | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5d96eea06..7442bc2eb 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2543,30 +2543,31 @@ int64_t komodo_priceave(int64_t *correlated,int32_t cskip) void komodo_pricesinit() { - int32_t i; + 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 0 && PRICES[0].fp != 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); - } + } + 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); } } From 900ba27f11878e509fb627e78cf46d101d35e0e9 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 03:24:38 -1100 Subject: [PATCH 38/56] Ind --- src/komodo_gateway.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 7442bc2eb..a3d3628b3 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2585,8 +2585,8 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) } if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) { - for (i=0; i Date: Thu, 11 Apr 2019 03:34:39 -1100 Subject: [PATCH 39/56] Null pindexFork case --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 593a41e3f..0ebc5c892 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4241,7 +4241,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // stay on the same chain tip! int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid; notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid); - if ( pindexFork->GetHeight() < notarizedht ) + 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), From 4f478650b89d1a22aa1760a8bc971454859833d9 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 03:46:04 -1100 Subject: [PATCH 40/56] +print --- src/komodo_gateway.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index a3d3628b3..86ab82583 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2356,6 +2356,9 @@ int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int mult = PriceMult[ind]; if ( nonzprices != 0 ) memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); + for (i=0; i width ) + 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 ) @@ -2612,7 +2615,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) 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 + 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,PRICES[ind].fp) == PRICES_DAYWINDOW*3 ) From 1065ccd67af9f6f8d6412758674a5d8c06a3d9ae Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:05:04 -1100 Subject: [PATCH 41/56] Sort trick --- src/komodo_gateway.h | 71 ++++++++++++++++++++++++++++++++++++------ src/rpc/blockchain.cpp | 14 ++++++--- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 86ab82583..ee7480c48 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2353,12 +2353,12 @@ 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 *(int64_t *)b) return 1; + return 0; +} + +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; + if(*(int64_t *)a > *(int64_t *)b) return -1; + return 0; +} + +static int64_t revsort64(int64_t *l, int32_t llen) +{ + heapsort(l,llen,sizeof(uint64_t),cmp_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,decayprice; if ( PRICES_DAYWINDOW < 2 ) return(0); for (i=0; i price ) // rising prices + { + sort64(buf,PRICES_DAYWINDOW); + decayprice = buf[0]; + for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); + } + else + { + revsort64(buf,PRICES_DAYWINDOW); + decayprice = buf[0]; + for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); + } + return(decayprice); } void komodo_pricesinit() @@ -2576,7 +2626,7 @@ void komodo_pricesinit() void komodo_pricesupdate(int32_t height,CBlock *pblock) { - static int numprices; static uint32_t *ptr32; static int64_t *ptr64; + 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 ) @@ -2584,6 +2634,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) 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),PRICES_DAYWINDOW); fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); } if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) @@ -2620,7 +2671,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * 3 * sizeof(int64_t),SEEK_SET); if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*3,PRICES[ind].fp) == PRICES_DAYWINDOW*3 ) { - if ( (smoothed= komodo_priceave(&ptr64[PRICES_DAYWINDOW*3-1],-3)) > 0 ) + if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[PRICES_DAYWINDOW*3-1],-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) ) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 07cb8a26d..0d1e7acb3 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -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_priceave(int64_t *correlated,int32_t cskip); +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,7 +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; uint32_t rawprices[1440*6],*ptr; + 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 ) @@ -1210,8 +1210,10 @@ int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks, if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 ) return(-3); } + tmpbuf = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW); for (i=0; i Date: Thu, 11 Apr 2019 04:15:41 -1100 Subject: [PATCH 42/56] Fix nondeterministic qsorts --- src/cc/dilithium.c | 5 +++-- src/cryptoconditions/src/asn/constr_SET_OF.c | 3 +++ src/cryptoconditions/src/threshold.c | 15 ++++++++++++--- src/komodo_gateway.h | 18 +++++++++++------- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/cc/dilithium.c b/src/cc/dilithium.c index 7ba522f0f..087dfd9f5 100644 --- a/src/cc/dilithium.c +++ b/src/cc/dilithium.c @@ -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) diff --git a/src/cryptoconditions/src/asn/constr_SET_OF.c b/src/cryptoconditions/src/asn/constr_SET_OF.c index 2dbc6e518..25e80cc30 100644 --- a/src/cryptoconditions/src/asn/constr_SET_OF.c +++ b/src/cryptoconditions/src/asn/constr_SET_OF.c @@ -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; diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 82f0e1b0a..7fc801897 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -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); } diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index ee7480c48..c7a203c3e 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2524,8 +2524,10 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters) 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 ) // jl777 prevent nondeterminism + return(-1); + else return(1); } static int64_t sort64(int64_t *l, int32_t llen) @@ -2536,13 +2538,15 @@ static int64_t sort64(int64_t *l, int32_t llen) static int revcmp_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 ) // jl777 prevent nondeterminism + return(-1); + else return(1); } static int64_t revsort64(int64_t *l, int32_t llen) { - heapsort(l,llen,sizeof(uint64_t),cmp_llu); + qsort(l,llen,sizeof(uint64_t),revcmp_llu); } int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) @@ -2575,7 +2579,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) decayprice = buf[0]; for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); @@ -2586,7 +2590,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) decayprice = buf[0]; for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); From 91dacca39b9a0062f422694bae4572ee819c5a7b Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:15:52 -1100 Subject: [PATCH 43/56] Fix qsorts --- src/pow/tromp/equi.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pow/tromp/equi.h b/src/pow/tromp/equi.h index f6d8803c2..84e566e1a 100644 --- a/src/pow/tromp/equi.h +++ b/src/pow/tromp/equi.h @@ -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 Date: Thu, 11 Apr 2019 04:17:55 -1100 Subject: [PATCH 44/56] Fix --- src/komodo_gateway.h | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index c7a203c3e..45e8b7fe9 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2574,27 +2574,15 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) if ( halfave == price ) return(price); else if ( halfave > price ) // rising prices - { sort64(buf,PRICES_DAYWINDOW); - decayprice = buf[0]; - for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); - } - else + else revsort64(buf,PRICES_DAYWINDOW); + decayprice = buf[0]; + for (i=0; i %.4f\n",(double)halfprice/COIN,(double)price/COIN,(double)decayprice/COIN); + decayprice = ((decayprice * 9) + (buf[i] * 1)) / 10; + fprintf(stderr,"%.4f ",(double)buf[i]/COIN); } + fprintf(stderr,"%ssort half %.4f vs %.4f -> %.4f\n",halfave Date: Thu, 11 Apr 2019 04:22:23 -1100 Subject: [PATCH 45/56] Off by 1 --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 45e8b7fe9..953947072 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2661,7 +2661,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) 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,PRICES[ind].fp) == PRICES_DAYWINDOW*3 ) + 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-1],-3)) > 0 ) { From 00f7ff6f41e9c93f2af745fdb081953f1183b61a Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:27:10 -1100 Subject: [PATCH 46/56] Another off by 1 --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 953947072..d3a9cb350 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2663,7 +2663,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) 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-1],-3)) > 0 ) + 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) ) From ad9adcf27382187c84abf98b090f5fda3bbec12b Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:30:45 -1100 Subject: [PATCH 47/56] .8f --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index d3a9cb350..92296a66c 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2670,7 +2670,7 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); else { - fprintf(stderr,"%.4f ",(double)smoothed/COIN); + fprintf(stderr,"%.8f ",(double)smoothed/COIN); fflush(PRICES[ind].fp); } } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); From 3898bb8b2aef62f8e6bf862d739e845cee58e266 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:33:12 -1100 Subject: [PATCH 48/56] +print --- src/komodo_gateway.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 92296a66c..0de71291f 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2670,7 +2670,8 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); else { - fprintf(stderr,"%.8f ",(double)smoothed/COIN); + 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); From 4255005f4de9980c4f5a62d2a743c084d1e79b1f Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:42:00 -1100 Subject: [PATCH 49/56] Tweak prices --- src/komodo_gateway.h | 13 +++++++------ src/rpc/blockchain.cpp | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 0de71291f..cf6f13174 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2565,11 +2565,12 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) { if ( (price= correlated[i*cskip]) != 0 ) nonzprice = price; - buf[i] = nonzprice; + buf[PRICES_DAYWINDOW+i] = nonzprice; sum += nonzprice; if ( i == PRICES_DAYWINDOW/2 ) halfave = (sum / (PRICES_DAYWINDOW/2)); } + memcp(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf)); price = sum / PRICES_DAYWINDOW; if ( halfave == price ) return(price); @@ -2579,11 +2580,11 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) decayprice = buf[0]; for (i=0; i %.4f\n",halfave %.4f\n",halfave Date: Thu, 11 Apr 2019 04:42:47 -1100 Subject: [PATCH 50/56] memcpy --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index cf6f13174..5641a1ffc 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2570,7 +2570,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) if ( i == PRICES_DAYWINDOW/2 ) halfave = (sum / (PRICES_DAYWINDOW/2)); } - memcp(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf)); + memcpy(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf)); price = sum / PRICES_DAYWINDOW; if ( halfave == price ) return(price); From 19b8685c211620e3a1cb0137afbf50dff56270dd Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 04:48:31 -1100 Subject: [PATCH 51/56] 19 --- src/komodo_gateway.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5641a1ffc..f8bfaf048 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2551,7 +2551,7 @@ static int64_t revsort64(int64_t *l, int32_t llen) 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,decayprice; + 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 %.4f\n",halfave Date: Thu, 11 Apr 2019 04:49:43 -1100 Subject: [PATCH 52/56] Halfave --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index f8bfaf048..92e0226b4 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2588,7 +2588,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) //fprintf(stderr,"%.4f ",(double)buf[i]/COIN); } //fprintf(stderr,"%ssort half %.4f vs %.4f -> %.4f\n",halfave Date: Thu, 11 Apr 2019 04:55:56 -1100 Subject: [PATCH 53/56] +print --- src/komodo_gateway.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 92e0226b4..555696d56 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2587,7 +2587,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) decayprice = ((decayprice * 97) + (buf[i] * 3)) / 100; //fprintf(stderr,"%.4f ",(double)buf[i]/COIN); } - //fprintf(stderr,"%ssort half %.4f vs %.4f -> %.4f\n",halfave %.8f\n",halfave Date: Thu, 11 Apr 2019 04:59:59 -1100 Subject: [PATCH 54/56] /19 --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 555696d56..3c7027e13 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2587,7 +2587,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) 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 %.8f\n",halfave Date: Thu, 11 Apr 2019 08:07:14 -1100 Subject: [PATCH 55/56] Smaller --- src/komodo_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 3c7027e13..a4a1b78e3 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2576,7 +2576,7 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) } memcpy(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf)); price = sum / PRICES_DAYWINDOW; - if ( halfave == price ) + //if ( halfave == price ) return(price); else if ( halfave > price ) // rising prices sort64(buf,PRICES_DAYWINDOW); From 11694fc7e74dfb1d62937aadf81eb303059ec5b1 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 11 Apr 2019 08:08:09 -1100 Subject: [PATCH 56/56] return(price); --- src/komodo_gateway.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index a4a1b78e3..6bd03ccfb 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -2576,7 +2576,8 @@ int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) } memcpy(buf,&buf[PRICES_DAYWINDOW],PRICES_DAYWINDOW*sizeof(*buf)); price = sum / PRICES_DAYWINDOW; - //if ( halfave == price ) + return(price); + if ( halfave == price ) return(price); else if ( halfave > price ) // rising prices sort64(buf,PRICES_DAYWINDOW);