]>
Commit | Line | Data |
---|---|---|
194ad5b8 | 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 "CCinclude.h" | |
17 | ||
18 | /* | |
19 | */ | |
20 | ||
194ad5b8 | 21 | extern const char *RewardsCCaddr; |
22 | extern char RewardsCChexstr[67]; | |
5b79a0e1 | 23 | bool IsRewardsInput(CScript const& scriptSig); |
194ad5b8 | 24 | |
25 | uint64_t RewardsCalc(uint64_t claim,uint256 txid) | |
26 | { | |
27 | uint64_t reward = 0; | |
28 | return(reward); | |
29 | } | |
30 | ||
db3b8abe | 31 | /*CC *MakeRewardsCond(CPubKey pk) |
194ad5b8 | 32 | { |
33 | std::vector<CC*> pks; uint8_t evalcode = EVAL_REWARDS; | |
34 | pks.push_back(CCNewSecp256k1(pk)); | |
35 | CC *rewardsCC = CCNewEval(E_MARSHAL(ss << evalcode)); | |
36 | CC *Sig = CCNewThreshold(1, pks); | |
37 | return CCNewThreshold(2, {rewardsCC, Sig}); | |
38 | } | |
39 | ||
40 | CTxOut MakeRewardsVout(CAmount nValue,CPubKey pk) | |
41 | { | |
42 | CTxOut vout; | |
db3b8abe | 43 | CC *payoutCond = MakeCCcond1(EVAL_REWARDS,pk); |
194ad5b8 | 44 | vout = CTxOut(nValue,CCPubKey(payoutCond)); |
45 | cc_free(payoutCond); | |
46 | return(vout); | |
db3b8abe | 47 | }*/ |
194ad5b8 | 48 | |
49 | uint64_t IsRewardsvout(const CTransaction& tx,int32_t v) | |
50 | { | |
51 | char destaddr[64]; | |
52 | if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) | |
53 | { | |
54 | if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,RewardsCCaddr) == 0 ) | |
55 | return(tx.vout[v].nValue); | |
56 | } | |
57 | return(0); | |
58 | } | |
59 | ||
60 | bool RewardsExactAmounts(Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) | |
61 | { | |
62 | static uint256 zerohash; | |
63 | CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; | |
64 | numvins = tx.vin.size(); | |
65 | numvouts = tx.vout.size(); | |
66 | for (i=0; i<numvins; i++) | |
67 | { | |
68 | if ( IsRewardsInput(tx.vin[i].scriptSig) != 0 ) | |
69 | { | |
70 | if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) | |
71 | return eval->Invalid("always should find vin, but didnt"); | |
72 | else | |
73 | { | |
74 | if ( hashBlock == zerohash ) | |
75 | return eval->Invalid("cant rewards from mempool"); | |
76 | if ( (assetoshis= IsRewardsvout(vinTx,tx.vin[i].prevout.n)) != 0 ) | |
77 | inputs += assetoshis; | |
78 | } | |
79 | } | |
80 | } | |
81 | for (i=0; i<numvouts; i++) | |
82 | { | |
83 | //fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts); | |
84 | if ( (assetoshis= IsRewardsvout(tx,i)) != 0 ) | |
85 | outputs += assetoshis; | |
86 | } | |
87 | if ( inputs != outputs+COIN+txfee ) | |
88 | { | |
89 | fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs); | |
90 | return eval->Invalid("mismatched inputs != outputs + COIN + txfee"); | |
91 | } | |
92 | else return(true); | |
93 | } | |
94 | ||
95 | bool RewardsValidate(Eval* eval,const CTransaction &tx) | |
96 | { | |
97 | int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; | |
98 | numvins = tx.vin.size(); | |
99 | numvouts = tx.vout.size(); | |
100 | preventCCvins = preventCCvouts = -1; | |
101 | if ( numvouts < 1 ) | |
102 | return eval->Invalid("no vouts"); | |
103 | else | |
104 | { | |
105 | for (i=0; i<numvins; i++) | |
106 | { | |
107 | if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) | |
108 | return eval->Invalid("illegal normal vini"); | |
109 | } | |
110 | if ( RewardsExactAmounts(eval,tx,1,10000) == false ) | |
111 | return false; | |
112 | else | |
113 | { | |
114 | preventCCvouts = 1; | |
115 | if ( IsRewardsvout(tx,0) != 0 ) | |
116 | { | |
117 | preventCCvouts++; | |
118 | i = 1; | |
119 | } else i = 0; | |
120 | if ( tx.vout[i].nValue != COIN ) | |
121 | return eval->Invalid("invalid rewards output"); | |
122 | return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); | |
123 | } | |
124 | } | |
125 | return(true); | |
126 | } | |
127 | ||
128 | bool ProcessRewards(Eval* eval, std::vector<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn) | |
129 | { | |
723ae0ea | 130 | static uint256 prevtxid; uint256 txid; |
131 | txid = ctx.GetHash(); | |
132 | if ( txid == prevtxid ) | |
133 | return(true); | |
ff780022 | 134 | fprintf(stderr,"ProcessRewards\n"); |
194ad5b8 | 135 | if ( paramsNull.size() != 0 ) // Don't expect params |
136 | return eval->Invalid("Cannot have params"); | |
137 | else if ( ctx.vout.size() == 0 ) | |
138 | return eval->Invalid("no-vouts"); | |
139 | if ( RewardsValidate(eval,ctx) != 0 ) | |
723ae0ea | 140 | { |
ff780022 | 141 | fprintf(stderr,"ProcessRewards valid\n"); |
723ae0ea | 142 | prevtxid = txid; |
194ad5b8 | 143 | return(true); |
723ae0ea | 144 | } |
ff780022 | 145 | fprintf(stderr,"ProcessRewards failed\n"); |
146 | return(false); | |
194ad5b8 | 147 | } |
148 | ||
149 | uint64_t AddRewardsInputs(CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs) | |
150 | { | |
151 | char coinaddr[64]; uint64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0; | |
152 | std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; | |
153 | GetCCaddress(EVAL_REWARDS,coinaddr,pk); | |
154 | SetCCunspents(unspentOutputs,coinaddr); | |
155 | for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) | |
156 | { | |
157 | txid = it->first.txhash; | |
158 | if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) | |
159 | { | |
160 | if ( (nValue= IsRewardsvout(vintx,(int32_t)it->first.index)) > 0 ) | |
161 | { | |
162 | if ( total != 0 && maxinputs != 0 ) | |
163 | mtx.vin.push_back(CTxIn(txid,(int32_t)it->first.index,CScript())); | |
164 | nValue = it->second.satoshis; | |
165 | totalinputs += nValue; | |
166 | n++; | |
167 | if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) | |
168 | break; | |
169 | } | |
170 | } | |
171 | } | |
172 | return(totalinputs); | |
173 | } | |
174 | ||
175 | // 0.834% every 60 days, min 100, capped at 0.834% | |
176 | ||
177 | std::string RewardsFund(uint64_t txfee,uint64_t funds,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit) | |
178 | { | |
179 | CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; | |
180 | if ( txfee == 0 ) | |
181 | txfee = 10000; | |
182 | mypk = pubkey2pk(Mypubkey()); | |
183 | rewardspk = GetUnspendable(EVAL_REWARDS,0); | |
184 | if ( AddNormalinputs(mtx,mypk,funds+2*txfee,64) > 0 ) | |
185 | { | |
db3b8abe | 186 | mtx.vout.push_back(MakeCC1vout(EVAL_REWARDS,funds,rewardspk)); |
194ad5b8 | 187 | mtx.vout.push_back(CTxOut(APR,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); |
188 | mtx.vout.push_back(CTxOut(minseconds,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); | |
189 | mtx.vout.push_back(CTxOut(maxseconds,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); | |
190 | mtx.vout.push_back(CTxOut(mindeposit,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG)); | |
191 | return(FinalizeCCTx(EVAL_REWARDS,mtx,mypk,txfee,opret)); | |
192 | } | |
193 | return(0); | |
194 | } | |
195 | ||
196 | std::string RewardsLock(uint64_t txfee,uint64_t amount) | |
197 | { | |
198 | CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; | |
199 | if ( txfee == 0 ) | |
200 | txfee = 10000; | |
201 | rewardspk = GetUnspendable(EVAL_REWARDS,0); | |
202 | mypk = pubkey2pk(Mypubkey()); | |
203 | if ( AddNormalinputs(mtx,mypk,amount+2*txfee,64) > 0 ) | |
204 | { | |
db3b8abe | 205 | mtx.vout.push_back(MakeCC1vout(EVAL_REWARDS,amount,rewardspk)); |
194ad5b8 | 206 | // specify destination pubkey, funding txid |
5b79a0e1 | 207 | //opret = ;// |
208 | return(FinalizeCCTx(EVAL_REWARDS,mtx,mypk,txfee,opret)); | |
194ad5b8 | 209 | } else fprintf(stderr,"cant find rewards inputs\n"); |
210 | return(0); | |
211 | } | |
212 | ||
213 | std::string RewardsUnlock(uint64_t txfee) | |
214 | { | |
215 | CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t reward,claim,inputs,CCchange=0; | |
216 | if ( txfee == 0 ) | |
217 | txfee = 10000; | |
218 | rewardspk = GetUnspendable(EVAL_REWARDS,0); | |
219 | mypk = pubkey2pk(Mypubkey()); | |
220 | if ( (claim= AddRewardsInputs(mtx,mypk,(1LL << 30),1)) > 0 && (reward= RewardsCalc(claim,mtx.vin[0].prevout.hash)) > txfee ) | |
221 | { | |
222 | if ( (inputs= AddRewardsInputs(mtx,mypk,reward+txfee,30)) > 0 ) | |
223 | { | |
224 | if ( inputs > (reward+txfee) ) | |
225 | CCchange = (inputs - reward - txfee); | |
226 | if ( CCchange != 0 ) | |
db3b8abe | 227 | mtx.vout.push_back(MakeCC1vout(EVAL_REWARDS,CCchange,rewardspk)); |
194ad5b8 | 228 | mtx.vout.push_back(CTxOut(claim+reward,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); |
229 | return(FinalizeCCTx(EVAL_REWARDS,mtx,mypk,txfee,opret)); | |
230 | } | |
231 | } else fprintf(stderr,"cant find rewards inputs\n"); | |
232 | return(0); | |
233 | } | |
234 |