]> Git Repo - VerusCoin.git/blame - src/cc/gateways.cpp
Ensure export finalization edge case
[VerusCoin.git] / src / cc / gateways.cpp
CommitLineData
c926780f 1/******************************************************************************
2 * Copyright © 2014-2018 The SuperNET Developers. *
3 * *
4 * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
5 * the top-level directory of this distribution for the individual copyright *
6 * holder information and the developer policies on copyright and licensing. *
7 * *
8 * Unless otherwise agreed in a custom licensing agreement, no part of the *
9 * SuperNET software, including this file may be copied, modified, propagated *
10 * or distributed except according to the terms contained in the LICENSE file *
11 * *
12 * Removal or modification of this copyright notice is prohibited. *
13 * *
14 ******************************************************************************/
15
16#include "CCGateways.h"
17
7f9283e5 18/*
5955955d 19 prevent duplicate bindtxid via mempool scan
3f4351c9 20 wait for notarization for oraclefeed and validation of gatewaysdeposit
3f4351c9 21
22 validation
23
7f9283e5 24string oracles
25 */
26
c926780f 27/*
366625ca 28 Uses MofN CC's normal msig handling to create automated deposits -> token issuing. And partial signing by the selected pubkeys for releasing the funds. A user would be able to select which pubkeys to use to construct the automated deposit/redeem multisigs.
29
30 the potential pubkeys to be used would be based on active oracle data providers with recent activity.
31
3515c101 32 bind asset <-> KMD gateway deposit address
33 KMD deposit -> globally spendable marker utxo
34 spend marker utxo and spend linked/locked asset to user's CC address
35
36 redeem -> asset to global CC address with withdraw address -> gateway spendable marker utxo
37 spend market utxo and withdraw from gateway deposit address
38
39 rpc calls:
40 GatewayList
41 GatewayInfo bindtxid
42 GatewayBind coin tokenid M N pubkey(s)
43 external: deposit to depositaddr with claimpubkey
44 GatewayDeposit coin tokenid external.deposittxid -> markertxid
45 GatewayClaim coin tokenid external.deposittxid markertxid -> spend marker and deposit asset
46
47 GatewayWithdraw coin tokenid withdrawaddr
48 external: do withdraw to withdrawaddr and spend marker, support for partial signatures and autocomplete
49
50 deposit addr can be 1 to MofN pubkeys
51 1:1 gateway with native coin
366625ca 52
2e338e79 53 In order to create a new gateway it is necessary to follow some strict steps.
54 1. create a token with the max possible supply that will be issued
55 2. transfer 100% of them to the gateways CC's global pubkey's asset CC address. (yes it is a bit confusing)
56 3. create an oracle with the identical name, ie. KMD and format must start with Ihh (height, blockhash, merkleroot)
57 4. register a publisher and fund it with a subscribe. there will be a special client app that will automatically publish the merkleroots.
9a63c0cf 58 5. Now a gatewaysbind can bind an external coin to an asset, along with the oracle for the merkleroots. the txid from the bind is used in most of the other gateways CC calls
2e338e79 59
77fad432 60 usage:
61 ./c tokencreate KMD 1000000 KMD_equivalent_token_for_gatewaysCC
62 a7398a8748354dd0a3f8d07d70e65294928ecc3674674bb2d9483011ccaa9a7a
63
64 transfer to gateways pubkey: 03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40 RDMqGyREkP1Gwub1Nr5Ye8a325LGZsWBCb
65 ./c tokentransfer a7398a8748354dd0a3f8d07d70e65294928ecc3674674bb2d9483011ccaa9a7a 03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40 100000000000000
66 2206fc39c0f384ca79819eb491ddbf889642cbfe4d0796bb6a8010ed53064a56
67
68 ./c oraclescreate KMD blockheaders Ihh
69 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808
70
71 ./c oraclesregister 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 1000000
72 83b59eac238cbe54616ee13b2fdde85a48ec869295eb04051671a1727c9eb402
73
74 ./c oraclessubscribe 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 1000
75 f9499d8bb04ffb511fcec4838d72e642ec832558824a2ce5aed87f1f686f8102
76
77 ./c gatewaysbind a7398a8748354dd0a3f8d07d70e65294928ecc3674674bb2d9483011ccaa9a7a 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 KMD 100000000000000 1 1 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92
98c80286 78 e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e
79
80 ./c gatewaysinfo e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e
81 {
82 "result": "success",
83 "name": "Gateways",
84 "pubkey": "02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92",
85 "coin": "KMD",
86 "oracletxid": "1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808",
87 "taddr": 0,
88 "prefix": 60,
89 "prefix2": 85,
90 "deposit": "",
91 "tokenid": "a7398a8748354dd0a3f8d07d70e65294928ecc3674674bb2d9483011ccaa9a7a",
92 "totalsupply": "1000000.00000000",
93 "remaining": "1000000.00000000",
94 "issued": "0.00000000"
95 }
96
d73f18f5 97 To make a gateway deposit, send the funds to the "deposit" address, along with any amount to the same pubkey address you want to get the assetized KMD to appear in.
98
e2d99d8d 99 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 pubkey for RFpxgqff7FDHFuHa3jSX5NzqqWCcELz8ha
d73f18f5 100 ./komodo-cli z_sendmany "<funding addr>" '[{"address":"RFpxgqff7FDHFuHa3jSX5NzqqWCcELz8ha","amount":0.0001},{"address":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","amount":7.6999}]'
7f9283e5 101 bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009 height.1003776 merkle.90aedc2f19200afc9aca2e351438d011ebae8264a58469bf225883045f61917f
d73f18f5 102
103 ./komodo-cli gettxoutproof '["bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009"]'
104 04000000232524ea04b54489eb222f8b3f566ed35504e3050488a63f0ab7b1c2030000007f91615f04835822bf6984a56482aeeb11d03814352eca9afc0a20192fdcae900000000000000000000000000000000000000000000000000000000000000000268e965ba608071d0800038e16762900000000000000000000000000000000000000000042008dd6fd4005016b4292b05df6dfd316c458c53e28fb2befb96e4870a40c6c04e733d75d8a7a18cce34fe326005efdc403bfa4644e30eeafdaeff34419edc591299e6cc5933cb2eeecbab5c4dfe97cd413b75215999a3dd02b540373581e81d8512bff1640590a6b4da4aaa9b8adc0102c38ca0022daed997b53ed192ba326e212fba5e505ce29e3ad149cef7f48d0e00948a1acd81731d84008760759211eb4abbc7b037939a7964182edb59cf9065357e864188ee5fc7316e8796963036bb99eeb9f06c95d64f78749ecec7181c12eb5d83a3b9b1c1e8a0aae9a20ce04a250b28216620bfc99bb81a6de4db80b93a5aea916de97c1a272e26644abdd683f19c5e3174a2e4513ed767d8f11a4c3074295f697839c5d9139676a813451cc7da38f68cbae5d990a79075f98903233ca04fe1b4b099e433585e5adcc45d41d54a9c648179297359c75950a5e574f13f70b728bbbf552770256315cd0a00139d6ab6934cb5ed70a4fc01a92611b096dd0028f17f4cc687b75f37dca530aa47a18321c50528dbd9272eabb3e13a87021a05918a6d2627e2caba6d7cf1a9f0b831ea3337b9a6af92746d83140078d60c72b6beacf91c9e68a34cee209e08670be1d17ff8d80b7a2285b1325461a2e33f2ee675593f1900e066a5d212615cd8da18749b0e684eee73edcc9031709be715b889c6d015cf4bd4ad5ab7e21bd3492c208930a54d353ef36a437f507ead38855633c1b88d060d9e4221ca8ce2f698e8a6ae0d41e9ace3cbd401f1e0f07650e9c126d4ef20278c8be6e85c7637513643f8d02d7ad64c09da11c16429d60e5160c345844b8158ece62794e8ad280d4e4664150e74978609ece431e51a9f9e1ce8aa49c16f36c7fd12b71acc42d893e18476b8b1e144a8175519612efc93e0aecc61f3b21212c958b0e2331d76aaa62faf11a58fe2bd91ab9ab01b906406c9bbc02df2a106e67182aae0a20b538bf19f09c57f9de5e198ba254580fb1b11e22ad526550093420cb7c68628d4c3ad329c8acc6e219093d277810ed016b6099b7e3781de412a22dacedaa2acf29e8062debcd85c7b9529a20b2782a2470763ac27cf89611a527d43ac89b8063ffb93b6ed993425194f8ee821a8493a563072c896f9584f95db28e3f2fc5fb4a6f3c39d615cd563641717cd50afb73ed3989cbf504b2043882993ce9575f56402534173b1396fbc13df80920b46788ae340ad5a91f25177cc74aa69024d76f56166199d2e4d50a053555256c4e3137ea1cee1130e916a88b6ee5cf2c85652fb8824d5dacfa485e3ef6190591ac0c2fcacc4fc7deb65aca4b0b89b76e35a46b0627e2e967cc63a5d606a984c8e63eabb98fde3e69114340ae524c974cb936e57690e98a7a74533f6f7d1d0496976496b54d14a8163efb32b70dfbb79d80a3022c4f53571c08bf044270565716b435084376714b224ab23e9817c05af8223723afc0577af5c8fc28f71036ca82528aaa4ca9bcd18a50e25d2a528f183d3a2074d968d170876d8dce434c5937261b55173ab87e03d5632ca0834fdc5387c15ab3a17d75c0f274004f289ff1bf7d14e97fdf4172eb49adfb418cc2f4794806ae7c0111c97df4d65d38679ec93fea3ef738ed565e8906a8fe1861cafe3938c772fedcfab40159938e06ef414fd299f2355c6d3369bc1bd3c4db64ce205f0a1b70a40030f505b736e28230de82e97776b5ee7b10708bb3020d28cec7a8e124549ec80c547ac4e7b52bf397c72bcfce30820554ab8fb4d1f73b209bc32a0e7e878843cdbf5f01222728ccea7e6ab7cb5e3fee3234f5b85d1985f91492f6ceaa6454a658dab5074f163ce26ed753137fa61c940679de13bd7b212cd3cf2b334f5201cecbc7473342bd7a239e09169bccd56d03000000037a9068df0625e548e71263c8361b4e904c998378f6b9e32729c3f19b10ad752e093013788222f5c26bfc5da4eeb7d32f01486a54179f19c341b79d420ea041bc8878d22fad4692b2d609c3cf190903874d3682a714c7483518c9392e07c25035010b
105
106 ./komodo-cli getrawtransaction bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009
107 010000000149964cdcd17fe9b1cae4d0f3b5f5db301d9b4f54099fdf4d34498df281757094010000006a4730440220594f3a630dd73c123f44621aa8bb9968ab86734833453dd479af6d79ae6f584202207bb5e35f13b337ccc8a88d9a006c8c5ddb016c0a6f4f2dc44357a8128623d85d01210223154bf53cd3a75e64d86697070d6437c8f0010a09c1df35b659e31ce3d79b5dffffffff0310270000000000001976a91447d2e323a14b0c3be08698aa46a9b91489b189d688ac701de52d000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688acb0a86a00000000001976a914f9a9daf5519dae38b8b61d945f075da895df441d88ace18d965b
108
e5a5dadb 109 gatewaysdeposit bindtxid height coin cointxid claimvout deposithex proof destpub amount
110./komodo-cli -ac_name=AT5 gatewaysdeposit e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e 1003776 KMD bc41a00e429db741c3199f17546a48012fd3b7eea45dfc6bc2f5228278133009 0 010000000149964cdcd17fe9b1cae4d0f3b5f5db301d9b4f54099fdf4d34498df281757094010000006a4730440220594f3a630dd73c123f44621aa8bb9968ab86734833453dd479af6d79ae6f584202207bb5e35f13b337ccc8a88d9a006c8c5ddb016c0a6f4f2dc44357a8128623d85d01210223154bf53cd3a75e64d86697070d6437c8f0010a09c1df35b659e31ce3d79b5dffffffff0310270000000000001976a91447d2e323a14b0c3be08698aa46a9b91489b189d688ac701de52d000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688acb0a86a00000000001976a914f9a9daf5519dae38b8b61d945f075da895df441d88ace18d965b 04000000232524ea04b54489eb222f8b3f566ed35504e3050488a63f0ab7b1c2030000007f91615f04835822bf6984a56482aeeb11d03814352eca9afc0a20192fdcae900000000000000000000000000000000000000000000000000000000000000000268e965ba608071d0800038e16762900000000000000000000000000000000000000000042008dd6fd4005016b4292b05df6dfd316c458c53e28fb2befb96e4870a40c6c04e733d75d8a7a18cce34fe326005efdc403bfa4644e30eeafdaeff34419edc591299e6cc5933cb2eeecbab5c4dfe97cd413b75215999a3dd02b540373581e81d8512bff1640590a6b4da4aaa9b8adc0102c38ca0022daed997b53ed192ba326e212fba5e505ce29e3ad149cef7f48d0e00948a1acd81731d84008760759211eb4abbc7b037939a7964182edb59cf9065357e864188ee5fc7316e8796963036bb99eeb9f06c95d64f78749ecec7181c12eb5d83a3b9b1c1e8a0aae9a20ce04a250b28216620bfc99bb81a6de4db80b93a5aea916de97c1a272e26644abdd683f19c5e3174a2e4513ed767d8f11a4c3074295f697839c5d9139676a813451cc7da38f68cbae5d990a79075f98903233ca04fe1b4b099e433585e5adcc45d41d54a9c648179297359c75950a5e574f13f70b728bbbf552770256315cd0a00139d6ab6934cb5ed70a4fc01a92611b096dd0028f17f4cc687b75f37dca530aa47a18321c50528dbd9272eabb3e13a87021a05918a6d2627e2caba6d7cf1a9f0b831ea3337b9a6af92746d83140078d60c72b6beacf91c9e68a34cee209e08670be1d17ff8d80b7a2285b1325461a2e33f2ee675593f1900e066a5d212615cd8da18749b0e684eee73edcc9031709be715b889c6d015cf4bd4ad5ab7e21bd3492c208930a54d353ef36a437f507ead38855633c1b88d060d9e4221ca8ce2f698e8a6ae0d41e9ace3cbd401f1e0f07650e9c126d4ef20278c8be6e85c7637513643f8d02d7ad64c09da11c16429d60e5160c345844b8158ece62794e8ad280d4e4664150e74978609ece431e51a9f9e1ce8aa49c16f36c7fd12b71acc42d893e18476b8b1e144a8175519612efc93e0aecc61f3b21212c958b0e2331d76aaa62faf11a58fe2bd91ab9ab01b906406c9bbc02df2a106e67182aae0a20b538bf19f09c57f9de5e198ba254580fb1b11e22ad526550093420cb7c68628d4c3ad329c8acc6e219093d277810ed016b6099b7e3781de412a22dacedaa2acf29e8062debcd85c7b9529a20b2782a2470763ac27cf89611a527d43ac89b8063ffb93b6ed993425194f8ee821a8493a563072c896f9584f95db28e3f2fc5fb4a6f3c39d615cd563641717cd50afb73ed3989cbf504b2043882993ce9575f56402534173b1396fbc13df80920b46788ae340ad5a91f25177cc74aa69024d76f56166199d2e4d50a053555256c4e3137ea1cee1130e916a88b6ee5cf2c85652fb8824d5dacfa485e3ef6190591ac0c2fcacc4fc7deb65aca4b0b89b76e35a46b0627e2e967cc63a5d606a984c8e63eabb98fde3e69114340ae524c974cb936e57690e98a7a74533f6f7d1d0496976496b54d14a8163efb32b70dfbb79d80a3022c4f53571c08bf044270565716b435084376714b224ab23e9817c05af8223723afc0577af5c8fc28f71036ca82528aaa4ca9bcd18a50e25d2a528f183d3a2074d968d170876d8dce434c5937261b55173ab87e03d5632ca0834fdc5387c15ab3a17d75c0f274004f289ff1bf7d14e97fdf4172eb49adfb418cc2f4794806ae7c0111c97df4d65d38679ec93fea3ef738ed565e8906a8fe1861cafe3938c772fedcfab40159938e06ef414fd299f2355c6d3369bc1bd3c4db64ce205f0a1b70a40030f505b736e28230de82e97776b5ee7b10708bb3020d28cec7a8e124549ec80c547ac4e7b52bf397c72bcfce30820554ab8fb4d1f73b209bc32a0e7e878843cdbf5f01222728ccea7e6ab7cb5e3fee3234f5b85d1985f91492f6ceaa6454a658dab5074f163ce26ed753137fa61c940679de13bd7b212cd3cf2b334f5201cecbc7473342bd7a239e09169bccd56d03000000037a9068df0625e548e71263c8361b4e904c998378f6b9e32729c3f19b10ad752e093013788222f5c26bfc5da4eeb7d32f01486a54179f19c341b79d420ea041bc8878d22fad4692b2d609c3cf190903874d3682a714c7483518c9392e07c25035010b 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999
0b62b807 111 -> 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6
f81291ae 112
c434b250 113 to get the merkleroots onchain, from the multisig signers nodes run the oraclefeed program with acname oracletxid pubkey Ihh
114 ./oraclefeed AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh
115
7f9283e5 116 gatewaysclaim bindtxid coin deposittxid destpub amount
0b62b807 117./c gatewaysclaim e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 9d80ea79a65aaa0d464f8b762356fa01047e16e9793505a22ca04559f81a6eb6 0223d114dededb04f253816d6ad0ce78dd08c617c94ce3c53bf50dc74a5157bef8 7.6999
9d860bd9 118
119 now the asset is in the pubkey's asset address!
120 it can be used, traded freely and any node who has the asset can do a gatewayswithdraw
121
122 gatewayswithdraw bindtxid coin withdrawpub amount
123 ./c gatewayswithdraw e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD 03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828 1
5955955d 124 ef3cc452da006eb2edda6b6ed3d3347664be51260f3e91f59ec44ec9701367f0
125
126 Now there is a withdraw pending, so it needs to be processed by the signing nodes on the KMD side
e3cd34a4 127
128 gatewayspending bindtxid coin
129 gatewayspending will display all pending withdraws and if it is done on one of the msigpubkeys, then it will queue it for processing
130 ./c gatewayspending e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e KMD
131
c926780f 132*/
133
5955955d 134
1e7f6843
D
135/*
136int32_t GatewaysAddQueue(std::string coin,uint256 txid,CScript scriptPubKey,int64_t nValue) // commented, bcz unused
5955955d 137{
138 char destaddr[64],str[65];
d808ad8e 139 Getscriptaddress(destaddr,scriptPubKey);
5955955d 140 fprintf(stderr,"GatewaysAddQueue: %s %s %s %.8f\n",coin.c_str(),uint256_str(str,txid),destaddr,(double)nValue/COIN);
141}
1e7f6843 142*/
5955955d 143
c926780f 144// start of consensus code
145
3515c101 146CScript EncodeGatewaysBindOpRet(uint8_t funcid,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
147{
148 CScript opret; uint8_t evalcode = EVAL_GATEWAYS;
2e338e79 149 opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << prefix << prefix2 << taddr << tokenid << totalsupply << M << N << pubkeys << oracletxid);
3515c101 150 return(opret);
151}
152
7f9283e5 153CScript EncodeGatewaysOpRet(uint8_t funcid,std::string coin,uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256>txids,int32_t height,uint256 cointxid,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
3515c101 154{
155 CScript opret; uint8_t evalcode = EVAL_GATEWAYS;
7f9283e5 156 opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << bindtxid << publishers << txids << height << cointxid << deposithex << proof << destpub << amount);
3515c101 157 return(opret);
158}
159
7f9283e5 160uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey,std::string &coin,uint256 &bindtxid,std::vector<CPubKey>&publishers,std::vector<uint256>&txids,int32_t &height,uint256 &cointxid,std::string &deposithex,std::vector<uint8_t> &proof,CPubKey &destpub,int64_t &amount)
3515c101 161{
162 std::vector<uint8_t> vopret; uint8_t *script,e,f;
163 GetOpReturnData(scriptPubKey, vopret);
164 script = (uint8_t *)vopret.data();
7f9283e5 165 if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> bindtxid; ss >> publishers; ss >> txids; ss >> height; ss >> cointxid; ss >> deposithex; ss >> proof; ss >> destpub; ss >> amount) != 0 )
3515c101 166 {
167 return(f);
168 }
169 return(0);
170}
171
172uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &tokenid,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &pubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2)
173{
174 std::vector<uint8_t> vopret; uint8_t *script,e,f;
175 GetOpReturnData(scriptPubKey, vopret);
176 script = (uint8_t *)vopret.data();
177 depositaddr[0] = 0;
2e338e79 178 if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> coin; ss >> prefix; ss >> prefix2; ss >> taddr; ss >> tokenid; ss >> totalsupply; ss >> M; ss >> N; ss >> pubkeys; ss >> oracletxid) != 0 )
3515c101 179 {
180 if ( prefix == 60 )
181 {
182 if ( N > 1 )
183 Getscriptaddress(depositaddr,GetScriptForMultisig(M,pubkeys));
cd936644 184 else Getscriptaddress(depositaddr,CScript() << ParseHex(HexStr(pubkeys[0])) << OP_CHECKSIG);
3515c101 185 }
186 else
187 {
9a63c0cf 188 fprintf(stderr,"need to generate non-KMD addresses prefix.%d\n",prefix);
3515c101 189 }
190 return(f);
9a63c0cf 191 } else fprintf(stderr,"error decoding bind opret\n");
3515c101 192 return(0);
193}
194
c926780f 195int64_t IsGatewaysvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
196{
197 char destaddr[64];
198 if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
199 {
200 if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
201 return(tx.vout[v].nValue);
202 }
203 return(0);
204}
205
206bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
207{
208 static uint256 zerohash;
209 CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
210 numvins = tx.vin.size();
211 numvouts = tx.vout.size();
212 for (i=0; i<numvins; i++)
213 {
214 //fprintf(stderr,"vini.%d\n",i);
215 if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
216 {
217 //fprintf(stderr,"vini.%d check mempool\n",i);
218 if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
219 return eval->Invalid("cant find vinTx");
220 else
221 {
222 //fprintf(stderr,"vini.%d check hash and vout\n",i);
223 if ( hashBlock == zerohash )
224 return eval->Invalid("cant Gateways from mempool");
225 if ( (assetoshis= IsGatewaysvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
226 inputs += assetoshis;
227 }
228 }
229 }
230 for (i=0; i<numvouts; i++)
231 {
232 //fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
233 if ( (assetoshis= IsGatewaysvout(cp,tx,i)) != 0 )
234 outputs += assetoshis;
235 }
236 if ( inputs != outputs+txfee )
237 {
238 fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
239 return eval->Invalid("mismatched inputs != outputs + txfee");
240 }
241 else return(true);
242}
243
4ecaf167 244bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn, bool fulfilled)
c926780f 245{
246 int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
c926780f 247 std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
48bde33c 248 fprintf(stderr,"return true without gateways validation\n");
c742ef4c 249 return(true);
c926780f 250 numvins = tx.vin.size();
251 numvouts = tx.vout.size();
252 preventCCvins = preventCCvouts = -1;
253 if ( numvouts < 1 )
254 return eval->Invalid("no vouts");
255 else
256 {
257 for (i=0; i<numvins; i++)
258 {
259 if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
260 {
261 return eval->Invalid("illegal normal vini");
262 }
263 }
264 //fprintf(stderr,"check amounts\n");
265 if ( GatewaysExactAmounts(cp,eval,tx,1,10000) == false )
266 {
267 fprintf(stderr,"Gatewaysget invalid amount\n");
268 return false;
269 }
270 else
271 {
272 txid = tx.GetHash();
273 memcpy(hash,&txid,sizeof(hash));
274 retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
275 if ( retval != 0 )
276 fprintf(stderr,"Gatewaysget validated\n");
277 else fprintf(stderr,"Gatewaysget invalid\n");
278 return(retval);
279 }
280 }
281}
282// end of consensus code
283
284// helper functions for rpc calls in rpcwallet.cpp
285
286int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
287{
288 char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
289 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
290 GetCCaddress(cp,coinaddr,pk);
291 SetCCunspents(unspentOutputs,coinaddr);
292 for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
293 {
294 txid = it->first.txhash;
295 vout = (int32_t)it->first.index;
296 // no need to prevent dup
297 if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
298 {
3515c101 299 if ( (nValue= IsGatewaysvout(cp,vintx,vout)) > 10000 && myIsutxo_spentinmempool(txid,vout) == 0 )
c926780f 300 {
301 if ( total != 0 && maxinputs != 0 )
302 mtx.vin.push_back(CTxIn(txid,vout,CScript()));
303 nValue = it->second.satoshis;
304 totalinputs += nValue;
305 n++;
306 if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
307 break;
308 }
309 }
310 }
311 return(totalinputs);
312}
313
612f676a 314int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256 reftokenid) // dont forget to check mempool!
315{
8c4abc12 316 char markeraddr[64],depositaddr[64]; std::string coin; int32_t numvouts; int64_t totalsupply; uint256 tokenid,oracletxid,hashBlock; uint8_t M,N,taddr,prefix,prefix2; std::vector<CPubKey> pubkeys; CTransaction tx;
612f676a 317 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
318 _GetCCaddress(markeraddr,EVAL_GATEWAYS,gatewayspk);
319 fprintf(stderr,"bind markeraddr.(%s) need to scan mempool also\n",markeraddr);
320 SetCCtxids(addressIndex,markeraddr);
321 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
322 {
323 if ( GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
324 {
8c4abc12 325 if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) == 'B' )
612f676a 326 {
327 if ( tokenid == reftokenid )
328 {
329 fprintf(stderr,"trying to bind an existing tokenid\n");
330 return(1);
331 }
332 }
333 }
334 }
335 return(0);
336}
337
5955955d 338static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr)
339{
340 int32_t i,n; char destaddr[64];
341 BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx)
342 {
343 const CTransaction &tx = e.GetTx();
344 if ( (n= tx.vout.size()) > 0 )
345 {
346 const uint256 &txid = tx.GetHash();
347 for (i=0; i<n; i++)
348 {
d808ad8e 349 Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
5955955d 350 if ( strcmp(destaddr,coinaddr) == 0 )
351 {
d808ad8e 352 fprintf(stderr,"found (%s) vout in mempool\n",coinaddr);
5955955d 353 return(1);
354 }
355 }
356 }
357 }
358 return(0);
359}
360
612f676a 361int32_t GatewaysCointxidExists(struct CCcontract_info *cp,uint256 cointxid) // dont forget to check mempool!
362{
363 char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
364 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
365 CCtxidaddr(txidaddr,cointxid);
612f676a 366 SetCCtxids(addressIndex,txidaddr);
367 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
368 {
369 return(-1);
370 }
5955955d 371 return(myIs_coinaddr_inmempoolvout(txidaddr));
612f676a 372}
373
3515c101 374UniValue GatewaysInfo(uint256 bindtxid)
375{
5fca6e7e 376 UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int32_t i; int64_t totalsupply,remaining;
3515c101 377 result.push_back(Pair("result","success"));
378 result.push_back(Pair("name","Gateways"));
379 cp = CCinit(&C,EVAL_GATEWAYS);
380 Gatewayspk = GetUnspendable(cp,0);
5fca6e7e 381 _GetCCaddress(gatewaysassets,EVAL_ASSETS,Gatewayspk);
3515c101 382 if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )
383 {
9a63c0cf 384 depositaddr[0] = 0;
3515c101 385 if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 && M <= N && N > 0 )
386 {
3515c101 387 if ( N > 1 )
388 {
389 result.push_back(Pair("M",M));
390 result.push_back(Pair("N",N));
2e338e79 391 for (i=0; i<N; i++)
434e600c 392 a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
2e338e79 393 result.push_back(Pair("pubkeys",a));
434e600c 394 } else result.push_back(Pair("pubkey",pubkey33_str(str,(uint8_t *)&pubkeys[0])));
3515c101 395 result.push_back(Pair("coin",coin));
396 result.push_back(Pair("oracletxid",uint256_str(str,oracletxid)));
397 result.push_back(Pair("taddr",taddr));
398 result.push_back(Pair("prefix",prefix));
399 result.push_back(Pair("prefix2",prefix2));
400 result.push_back(Pair("deposit",depositaddr));
401 result.push_back(Pair("tokenid",uint256_str(str,tokenid)));
402 sprintf(numstr,"%.8f",(double)totalsupply/COIN);
403 result.push_back(Pair("totalsupply",numstr));
2e338e79 404 remaining = CCaddress_balance(gatewaysassets);
3515c101 405 sprintf(numstr,"%.8f",(double)remaining/COIN);
406 result.push_back(Pair("remaining",numstr));
407 sprintf(numstr,"%.8f",(double)(totalsupply - remaining)/COIN);
408 result.push_back(Pair("issued",numstr));
409 }
410 }
411 return(result);
412}
413
414UniValue GatewaysList()
415{
ea21fde9 416 UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock,oracletxid,tokenid; CTransaction vintx; std::string coin; int64_t totalsupply; char str[65],depositaddr[64]; uint8_t M,N,taddr,prefix,prefix2; std::vector<CPubKey> pubkeys;
3515c101 417 cp = CCinit(&C,EVAL_GATEWAYS);
418 SetCCtxids(addressIndex,cp->unspendableCCaddr);
419 for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
420 {
421 txid = it->first.txhash;
422 if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
423 {
424 if ( vintx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,vintx.vout[vintx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 )
425 {
426 result.push_back(uint256_str(str,txid));
427 }
428 }
429 }
430 return(result);
431}
432
433std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys)
c926780f 434{
ea21fde9 435 CMutableTransaction mtx; CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char destaddr[64],coinaddr[64],str[65],*fstr;
c926780f 436 cp = CCinit(&C,EVAL_GATEWAYS);
3515c101 437 if ( N == 0 || N > 15 || M > N )
438 {
439 fprintf(stderr,"illegal M.%d or N.%d\n",M,N);
440 return("");
441 }
442 if ( strcmp((char *)"KMD",coin.c_str()) != 0 )
443 {
444 fprintf(stderr,"only KMD supported for now\n");
445 return("");
446 }
447 taddr = 0;
448 prefix = 60;
449 prefix2 = 85;
450 if ( pubkeys.size() != N )
451 {
452 fprintf(stderr,"M.%d N.%d but pubkeys[%d]\n",M,N,(int32_t)pubkeys.size());
453 return("");
454 }
455 for (i=0; i<N; i++)
456 {
cd936644 457 Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pubkeys[i])) << OP_CHECKSIG);
ea21fde9 458 if ( CCaddress_balance(coinaddr) == 0 )
3515c101 459 {
460 fprintf(stderr,"M.%d N.%d but pubkeys[%d] has no balance\n",M,N,i);
461 return("");
462 }
463 }
c926780f 464 if ( txfee == 0 )
465 txfee = 10000;
c926780f 466 mypk = pubkey2pk(Mypubkey());
3515c101 467 gatewayspk = GetUnspendable(cp,0);
468 if ( _GetCCaddress(destaddr,EVAL_ASSETS,gatewayspk) == 0 )
469 {
f9e754a8 470 fprintf(stderr,"Gateway bind.%s (%s) cant create globaladdr\n",coin.c_str(),uint256_str(str,tokenid));
3515c101 471 return("");
472 }
ea21fde9 473 if ( (fullsupply= CCfullsupply(tokenid)) != totalsupply )
3515c101 474 {
382b39e2 475 fprintf(stderr,"Gateway bind.%s (%s) globaladdr.%s totalsupply %.8f != fullsupply %.8f\n",coin.c_str(),uint256_str(str,tokenid),cp->unspendableCCaddr,(double)totalsupply/COIN,(double)fullsupply/COIN);
3515c101 476 return("");
477 }
ea21fde9 478 if ( CCtoken_balance(destaddr,tokenid) != totalsupply )
3515c101 479 {
382b39e2 480 fprintf(stderr,"Gateway bind.%s (%s) globaladdr.%s token balance %.8f != %.8f\n",coin.c_str(),uint256_str(str,tokenid),cp->unspendableCCaddr,(double)CCtoken_balance(destaddr,tokenid)/COIN,(double)totalsupply/COIN);
3515c101 481 return("");
482 }
f9e754a8 483 if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= oracletx.vout.size()) <= 0 )
3515c101 484 {
485 fprintf(stderr,"cant find oracletxid %s\n",uint256_str(str,oracletxid));
486 return("");
487 }
488 if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' )
489 {
8096afff 490 fprintf(stderr,"mismatched oracle name %s != %s\n",name.c_str(),coin.c_str());
3515c101 491 return("");
492 }
493 if ( (fstr= (char *)format.c_str()) == 0 || strncmp(fstr,"Ihh",3) != 0 )
494 {
495 fprintf(stderr,"illegal format (%s) != (%s)\n",fstr,(char *)"Ihh");
496 return("");
497 }
612f676a 498 if ( GatewaysBindExists(cp,gatewayspk,tokenid) != 0 ) // dont forget to check mempool!
3515c101 499 {
8096afff 500 fprintf(stderr,"Gateway bind.%s (%s) already exists\n",coin.c_str(),uint256_str(str,tokenid));
3515c101 501 return("");
612f676a 502 }
3515c101 503 if ( AddNormalinputs(mtx,mypk,2*txfee,60) > 0 )
504 {
505 mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,gatewayspk));
506 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2)));
507 }
508 fprintf(stderr,"cant find enough inputs\n");
509 return("");
510}
511
512uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
513{
db6b7e17 514 CTransaction tx; uint256 hash,mhash,hashBlock,oracletxid; int64_t val; int32_t numvouts; int64_t merkleht; CPubKey pk; std::vector<uint8_t>data;
3515c101 515 txid = zeroid;
20007e86 516 char str[65]; fprintf(stderr,"reverse scan %s\n",uint256_str(str,batontxid));
3515c101 517 while ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
518 {
20007e86 519 fprintf(stderr,"reverse scan %s\n",uint256_str(str,batontxid));
3515c101 520 if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,hash,pk,data) == 'D' && oracletxid == reforacletxid )
521 {
522 if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
c926780f 523 {
3515c101 524 if ( oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size()) == sizeof(hash) &&
525 oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size()) == sizeof(hash) && mhash != zeroid )
c926780f 526 {
3515c101 527 txid = batontxid;
528 return(mhash);
529 } else return(zeroid);
c926780f 530 }
3515c101 531 batontxid = hash;
532 } else break;
533 }
534 return(zeroid);
535}
536
7f9283e5 537/* Get the block merkle root for a proof
538 * IN: proofData
539 * OUT: merkle root
540 * OUT: transaction IDS
541 */
542uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids)
543{
544 CMerkleBlock merkleBlock;
545 if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
546 return uint256();
547 return merkleBlock.txn.ExtractMatches(txids);
548}
549
550int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub)
3515c101 551{
159a3dfa 552 std::vector<uint256> txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format; char destaddr[64],destpubaddr[64],claimaddr[64],str[65],str2[65]; int32_t i,numvouts; int64_t nValue = 0;
3515c101 553 if ( GetTransaction(oracletxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
554 {
555 fprintf(stderr,"GatewaysVerify cant find oracletxid %s\n",uint256_str(str,oracletxid));
556 return(0);
557 }
558 if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin )
559 {
db6b7e17 560 fprintf(stderr,"GatewaysVerify mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str());
3515c101 561 return(0);
562 }
7f9283e5 563 proofroot = BitcoinGetProofMerkleRoot(proof,txids);
159a3dfa 564 if ( proofroot != merkleroot )
7f9283e5 565 {
566 fprintf(stderr,"GatewaysVerify mismatched merkleroot %s != %s\n",uint256_str(str,proofroot),uint256_str(str2,merkleroot));
567 return(0);
568 }
3515c101 569 if ( DecodeHexTx(tx,deposithex) != 0 )
570 {
7f9283e5 571 Getscriptaddress(claimaddr,tx.vout[claimvout].scriptPubKey);
572 Getscriptaddress(destpubaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
573 if ( strcmp(claimaddr,destpubaddr) == 0 )
3515c101 574 {
7f9283e5 575 for (i=0; i<numvouts; i++)
3515c101 576 {
7f9283e5 577 Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
578 if ( strcmp(refdepositaddr,destaddr) == 0 )
a609fa64 579 {
580 txid = tx.GetHash();
581 nValue = tx.vout[i].nValue;
582 break;
3242301d 583 }
7f9283e5 584 }
585 } else fprintf(stderr,"claimaddr.(%s) != destpubaddr.(%s)\n",claimaddr,destpubaddr);
3515c101 586 }
587 if ( txid == cointxid )
588 {
589 fprintf(stderr,"verify proof for cointxid in merkleroot\n");
590 return(nValue);
4ada5219 591 } else fprintf(stderr,"(%s) != (%s) or txid mismatch.%d or script mismatch\n",refdepositaddr,destaddr,txid != cointxid);
3515c101 592 return(0);
593}
594
595int64_t GatewaysDepositval(CTransaction tx)
596{
8571958e 597 int32_t numvouts,height; int64_t amount; std::string coin,deposithex; std::vector<CPubKey> publishers; std::vector<uint256>txids; uint256 bindtxid,cointxid; std::vector<uint8_t> proof; CPubKey claimpubkey;
3515c101 598 if ( (numvouts= tx.vout.size()) > 0 )
599 {
4df0d20a 600 if ( DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey,coin,bindtxid,publishers,txids,height,cointxid,deposithex,proof,claimpubkey,amount) == 'D' )
3515c101 601 {
602 // coin, bindtxid, publishers
603 fprintf(stderr,"need to validate deposittxid more\n");
604 return(amount);
c926780f 605 }
3515c101 606 }
607 return(0);
608}
609
e5a5dadb 610std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
3515c101 611{
20007e86 612 CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid; int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2; std::string coin; struct CCcontract_info *cp,C; std::vector<CPubKey> pubkeys,publishers; std::vector<uint256>txids; char str[67],depositaddr[64],txidaddr[64];
3515c101 613 cp = CCinit(&C,EVAL_GATEWAYS);
614 if ( txfee == 0 )
615 txfee = 10000;
616 mypk = pubkey2pk(Mypubkey());
617 gatewayspk = GetUnspendable(cp,0);
e1529dc1 618 //fprintf(stderr,"GatewaysDeposit ht.%d %s %.8f numpks.%d\n",height,refcoin.c_str(),(double)amount/COIN,(int32_t)pubkeys.size());
3515c101 619 if ( GetTransaction(bindtxid,bindtx,hashBlock,false) == 0 || (numvouts= bindtx.vout.size()) <= 0 )
620 {
621 fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
c926780f 622 return("");
3515c101 623 }
e5a5dadb 624 if ( DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B' || refcoin != coin )
3515c101 625 {
857346ef 626 fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
3515c101 627 return("");
628 }
629 n = (int32_t)pubkeys.size();
630 merkleroot = zeroid;
631 for (i=m=0; i<n; i++)
632 {
8b60ad59 633 fprintf(stderr,"pubkeys[%d] %s\n",i,pubkey33_str(str,(uint8_t *)&pubkeys[i]));
c66988d0 634 if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
3515c101 635 {
636 if ( merkleroot == zeroid )
637 merkleroot = mhash, m = 1;
638 else if ( mhash == merkleroot )
639 m++;
4df0d20a 640 publishers.push_back(pubkeys[i]);
641 txids.push_back(txid);
3515c101 642 }
643 }
20007e86 644 fprintf(stderr,"m.%d of n.%d\n",m,n);
7f9283e5 645 if ( merkleroot == zeroid || m < n/2 )
3515c101 646 {
b4df8470 647 //uint256 tmp;
648 //decode_hex((uint8_t *)&tmp,32,(char *)"90aedc2f19200afc9aca2e351438d011ebae8264a58469bf225883045f61917f");
649 //merkleroot = revuint256(tmp);
857346ef 650 fprintf(stderr,"couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d\n",height,coin.c_str(),uint256_str(str,oracletxid),m,n);
b4df8470 651 return("");
3515c101 652 }
87904dc9 653 if ( GatewaysCointxidExists(cp,cointxid) != 0 )
654 {
655 fprintf(stderr,"cointxid.%s already exists\n",uint256_str(str,cointxid));
656 return("");
657 }
7f9283e5 658 if ( GatewaysVerify(depositaddr,oracletxid,claimvout,coin,cointxid,deposithex,proof,merkleroot,destpub) != amount )
3515c101 659 {
660 fprintf(stderr,"deposittxid didnt validate\n");
661 return("");
662 }
612f676a 663 if ( AddNormalinputs(mtx,mypk,3*txfee,60) > 0 )
3515c101 664 {
665 mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk));
612f676a 666 mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
7f9283e5 667 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysOpRet('D',coin,bindtxid,publishers,txids,height,cointxid,deposithex,proof,destpub,amount)));
3515c101 668 }
669 fprintf(stderr,"cant find enough inputs\n");
c926780f 670 return("");
671}
672
7f9283e5 673std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount)
c926780f 674{
23e0b80b 675 CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector<CPubKey> msigpubkeys; int64_t totalsupply,depositamount,inputs,CCchange=0; int32_t numvouts; uint256 hashBlock,assetid,oracletxid; char str[65],depositaddr[64],coinaddr[64];
c926780f 676 cp = CCinit(&C,EVAL_GATEWAYS);
3515c101 677 assetscp = CCinit(&C2,EVAL_ASSETS);
c926780f 678 if ( txfee == 0 )
679 txfee = 10000;
680 mypk = pubkey2pk(Mypubkey());
3515c101 681 gatewayspk = GetUnspendable(cp,0);
dfac32e4 682 _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk);
683 CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr);
23e0b80b 684 Myprivkey(mypriv);
685 _GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
686 CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr);
3515c101 687 if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
c926780f 688 {
3515c101 689 fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
690 return("");
c926780f 691 }
3515c101 692 if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
693 {
857346ef 694 fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
3515c101 695 return("");
696 }
697 if ( GetTransaction(deposittxid,tx,hashBlock,false) == 0 )
698 {
699 fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
700 return("");
701 }
2f51e8fa 702 if ( (depositamount= GatewaysDepositval(tx)) != amount )
3515c101 703 {
2f51e8fa 704 fprintf(stderr,"invalid Gateways deposittxid %s %.8f != %.8f\n",uint256_str(str,deposittxid),(double)depositamount/COIN,(double)amount/COIN);
3515c101 705 return("");
706 }
bb81559f 707 //fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2);
3515c101 708 if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
709 {
23e0b80b 710 if ( (inputs= AddAssetInputs(assetscp,mtx,gatewayspk,assetid,amount,60)) > 0 )
3515c101 711 {
c66988d0 712 if ( inputs > amount )
713 CCchange = (inputs - amount);
3515c101 714 mtx.vin.push_back(CTxIn(deposittxid,0,CScript()));
2f51e8fa 715 mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk));
3515c101 716 if ( CCchange != 0 )
717 mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,gatewayspk));
23e0b80b 718 return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
3515c101 719 }
720 }
721 fprintf(stderr,"cant find enough inputs or mismatched total\n");
c926780f 722 return("");
723}
724
3515c101 725std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount)
c926780f 726{
f978cd48 727 CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C,*assetscp,C2; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2,mypriv[32]; std::string coin; std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64];
c926780f 728 cp = CCinit(&C,EVAL_GATEWAYS);
3515c101 729 assetscp = CCinit(&C2,EVAL_ASSETS);
730 if ( txfee == 0 )
731 txfee = 10000;
732 mypk = pubkey2pk(Mypubkey());
733 gatewayspk = GetUnspendable(cp,0);
3f4351c9 734 _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk);
735 CCaddr2set(assetscp,EVAL_ASSETS,gatewayspk,cp->CCpriv,coinaddr);
736 Myprivkey(mypriv);
737 _GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
738 CCaddr3set(assetscp,EVAL_GATEWAYS,mypk,mypriv,coinaddr);
3515c101 739 if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
740 {
741 fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
742 return("");
743 }
744 if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
745 {
857346ef 746 fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
3515c101 747 return("");
748 }
5955955d 749 if ( AddNormalinputs(mtx,mypk,3*txfee,3) > 0 )
3515c101 750 {
751 if ( (inputs= AddAssetInputs(assetscp,mtx,mypk,assetid,amount,60)) > 0 )
752 {
753 if ( inputs > amount )
754 CCchange = (inputs - amount);
755 mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,gatewayspk));
3f4351c9 756 mtx.vout.push_back(CTxOut(txfee,CScript() << withdrawpub << OP_CHECKSIG));
5955955d 757 mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG));
3515c101 758 if ( CCchange != 0 )
759 mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
2f51e8fa 760 return(FinalizeCCTx(0,assetscp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey())));
3515c101 761 }
762 }
763 fprintf(stderr,"cant find enough inputs or mismatched total\n");
764 return("");
c926780f 765}
766
6bde696a 767std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid)
768{
b31844cb 769 CMutableTransaction mtx; CScript opret; CPubKey mypk; struct CCcontract_info *cp,C;
6bde696a 770 cp = CCinit(&C,EVAL_GATEWAYS);
771 if ( txfee == 0 )
9f72c41a 772 txfee = 5000;
6bde696a 773 mypk = pubkey2pk(Mypubkey());
774 mtx.vin.push_back(CTxIn(withdrawtxid,2,CScript()));
9f72c41a 775 mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
6bde696a 776 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
777}
778
e3cd34a4 779UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
5955955d 780{
62f0cedd 781 UniValue result(UniValue::VOBJ),pending(UniValue::VARR),obj(UniValue::VOBJ); CTransaction tx; std::string coin; CPubKey mypk,gatewayspk; std::vector<CPubKey> msigpubkeys; uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; char depositaddr[64],withmarker[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],signeraddr[64]; int32_t i,n,numvouts,vout,numqueued,queueflag; int64_t totalsupply; struct CCcontract_info *cp,C;
5955955d 782 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
783 cp = CCinit(&C,EVAL_GATEWAYS);
784 mypk = pubkey2pk(Mypubkey());
785 gatewayspk = GetUnspendable(cp,0);
786 _GetCCaddress(coinaddr,EVAL_ASSETS,gatewayspk);
787 if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
788 {
789 fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid));
790 return(result);
791 }
792 if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin )
793 {
794 fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str());
795 return(result);
796 }
797 n = msigpubkeys.size();
798 queueflag = 0;
799 for (i=0; i<n; i++)
800 if ( msigpubkeys[i] == mypk )
801 {
802 queueflag = 1;
803 break;
804 }
805 Getscriptaddress(withmarker,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG);
806 SetCCunspents(unspentOutputs,withmarker);
807 numqueued = 0;
808 for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
809 {
810 txid = it->first.txhash;
811 vout = (int32_t)it->first.index;
812 if ( GetTransaction(txid,tx,hashBlock,false) != 0 )
813 {
814 Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
815 Getscriptaddress(withaddr,tx.vout[1].scriptPubKey);
816 if ( strcmp(destaddr,coinaddr) == 0 )
817 {
4f61de87 818 obj.push_back(Pair("txid",uint256_str(str,txid)));
2d16b4db 819 CCtxidaddr(txidaddr,txid);
820 obj.push_back(Pair("txidaddr",txidaddr));
4f61de87 821 obj.push_back(Pair("withdrawaddr",withaddr));
5955955d 822 sprintf(numstr,"%.8f",(double)tx.vout[0].nValue/COIN);
4f61de87 823 obj.push_back(Pair("amount",numstr));
62f0cedd 824 if ( queueflag != 0 )
825 {
826 obj.push_back(Pair("depositaddr",depositaddr));
827 Getscriptaddress(signeraddr,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG);
828 obj.push_back(Pair("signeraddr",signeraddr));
829 // numqueued += GatewaysAddQueue(refcoin,txid,tx.vout[1].scriptPubKey,tx.vout[0].nValue);
830 }
f602ac98 831 pending.push_back(obj);
5955955d 832 }
833 }
834 }
835 result.push_back(Pair("coin",refcoin));
836 result.push_back(Pair("pending",pending));
837 result.push_back(Pair("queueflag",queueflag));
838 return(result);
839}
3515c101 840
This page took 0.32294 seconds and 4 git commands to generate.