]>
Commit | Line | Data |
---|---|---|
1 | /******************************************************************** | |
2 | * (C) 2019 Michael Toutonghi | |
3 | * | |
4 | * Distributed under the MIT software license, see the accompanying | |
5 | * file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
6 | * | |
7 | * This defines the public blockchains as a service (PBaaS) notarization protocol, VerusLink. | |
8 | * VerusLink is a new distributed consensus protocol that enables multiple public blockchains | |
9 | * to operate as a decentralized ecosystem of chains, which can interact and easily engage in cross | |
10 | * chain transactions. | |
11 | * | |
12 | * In all notarization services, there is notarizing chain and a chain paying notarization rewards. They are not the same. | |
13 | * The notarizing chain earns the right to submit notarizations onto the paying chain, which uses provable Verus chain power | |
14 | * of each chain combined with a confirmation process to validate the correct version of one chain to another and vice versa. | |
15 | * Generally, the paying chain will be Verus, and the notarizing chain will be the PBaaS chain started with a root of Verus | |
16 | * notarization. | |
17 | * | |
18 | * On each chain, notarizations spend the output of the prior transaction that spent the notarization output, which has some spending | |
19 | * rules that create a thread of one attempted notarization per block, each of them properly representing the current chain, whether | |
20 | * the prior transaction represents a valid representation of the other chain or not. In order to move the notarization forward, | |
21 | * it must also be accepted onto the paying chain, then referenced to move confirmed notarization forward again on the current chain. | |
22 | * All notarization threads are started with a chain definition on the paying chain, or at block 1 on the PBaaS chain. | |
23 | * | |
24 | * Every notarization besides the chain definition is initiated on the PBaaS chain as an effort to create a notarization that is accepted | |
25 | * and confirmed on the paying chain by first being accepted by a Verus miner before a more valuable | |
26 | * notarization is completed and available for acceptance, then being confirmed by multiple cross notarizations. | |
27 | * | |
28 | * A notarization submission is earned when a block is won by staking or mining on the PBaaS chain. The miner puts a notarization | |
29 | * of the paying chain into the block mined, spending the notarization thread. In order for the miner to have a transaction output to spend from, | |
30 | * all PBaaS chains have a block 1 output of a small, transferable amount of Verus, which is only used as a notarization thread. | |
31 | * | |
32 | * After "n" blocks, currently 8, from the block won, the earned notarization may be submitted, proving the last notarization and | |
33 | * including an MMR root that is 8 blocks after the asserted winning block, which must also be proven along with at least one staked block. | |
34 | * Once accepted and confirmed, the notarization transaction itself may be used to spend from the pool of notarization rewards, | |
35 | * with an output that pays 50% to the notary and 50% to the block miner/staker recipient on the paying chain. | |
36 | * | |
37 | * A notarizaton must be either the first in the chain or refer to a prior notarization with which it agrees. If it skips existing | |
38 | * notarizations, referring to a prior notarization as valid, that is the same as asserting that the skipped notarizations are invalid. | |
39 | * In that case, the notarization and 2 after it must prove one additional block since the notarization skipped. | |
40 | * | |
41 | * The intent is to make it extremely improbable cryptographically to achieve full confirmation of any notarization unless an alternate | |
42 | * fork actually represents a valid chain with a majority of combined work and stake, even if more than the majority of notarizers are | |
43 | * attempting to notarize an invalid chain. | |
44 | * | |
45 | * to accept an earned notarization as valid on the Verus blockchain, it must prove a transaction on the alternate chain, which is | |
46 | * either the original chain definition transaction, which CAN and MUST be proven ONLY in block 1, or the latest notarization transaction | |
47 | * on the alternate chain that represents an accurate MMR for the accepting chain. | |
48 | * In addition, any accepted notarization must fullfill the following requirements: | |
49 | * 1) Must prove either a PoS block from the alternate chain or a merge mined | |
50 | * block that is owned by the submitter and exactly 8 blocks behind the submitted MMR, which is used for proof. | |
51 | * 2) must prove a chain definition tx and be block 1 or contain a notarization tx, which asserts a previous, valid MMR for this | |
52 | * chain and properly proves objects using that MMR, as well as has the proper notarization thread inputs and outputs. | |
53 | * 3) must spend the notarization thread to the specified chainID in a fee free transaction with notarization thread input and output | |
54 | * | |
55 | * to agree with a previous notarization, we must: | |
56 | * 1) agree that at the indicated block height, the MMR root is the root claimed, and is a correct representation of the best chain. | |
57 | * | |
58 | */ | |
59 | ||
60 | #ifndef PBAAS_NOTARIZATION_H | |
61 | #define PBAAS_NOTARIZATION_H | |
62 | ||
63 | #include "key_io.h" | |
64 | #include "pbaas/pbaas.h" | |
65 | ||
66 | class CObjectFinalization | |
67 | { | |
68 | public: | |
69 | static const int32_t UNCONFIRMED_INPUT = -1; | |
70 | enum { | |
71 | VERSION_INVALID = 0, | |
72 | VERSION_FIRST = 1, | |
73 | VERSION_LAST = 1, | |
74 | VERSION_CURRENT = 1 | |
75 | }; | |
76 | ||
77 | enum EFinalizationType { | |
78 | FINALIZE_INVALID = 0, | |
79 | FINALIZE_NOTARIZATION = 1, // confirmed when notarization is deemed correct / final | |
80 | FINALIZE_EXPORT = 2, // confirmed when export has no more work to do | |
81 | FINALIZE_CURRENCY_LAUNCH = 4, // confirmed on successful currency launch, rejected on refund | |
82 | FINALIZE_REJECTED = 0x40, // flag set when confirmation is rejected and/or proven false | |
83 | FINALIZE_CONFIRMED = 0x80, // flag set when object finalization is confirmed | |
84 | FINALIZE_TYPE_MASK = ~(FINALIZE_REJECTED | FINALIZE_CONFIRMED) | |
85 | }; | |
86 | ||
87 | uint8_t version; | |
88 | uint8_t finalizationType; | |
89 | uint32_t minFinalizationHeight; // to enable indexing/querying potential finalizations by height | |
90 | uint160 currencyID; // here when needed for indexing purposes | |
91 | CUTXORef output; // output/object to finalize | |
92 | std::vector<int32_t> evidenceInputs; // indexes into vin that are evidence to support the current state | |
93 | std::vector<int32_t> evidenceOutputs; // tx output indexes that are evidence to support the current state | |
94 | ||
95 | CObjectFinalization() : version(VERSION_INVALID), finalizationType(FINALIZE_INVALID) {} | |
96 | CObjectFinalization(uint8_t fType, const uint160 &curID, const uint256 &TxId, uint32_t outNum, uint32_t minFinalHeight=0) : | |
97 | version(VERSION_CURRENT), finalizationType(fType), minFinalizationHeight(minFinalHeight), currencyID(curID), output(TxId, outNum) {} | |
98 | CObjectFinalization(const std::vector<unsigned char> &vch) | |
99 | { | |
100 | ::FromVector(vch, *this); | |
101 | } | |
102 | CObjectFinalization(const CTransaction &tx, uint32_t *pEcode=nullptr, int32_t *pFinalizationOutNum=nullptr); | |
103 | CObjectFinalization(const CScript &script); | |
104 | ||
105 | ADD_SERIALIZE_METHODS; | |
106 | ||
107 | template <typename Stream, typename Operation> | |
108 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
109 | READWRITE(version); | |
110 | READWRITE(finalizationType); | |
111 | READWRITE(currencyID); | |
112 | READWRITE(output); | |
113 | if (IsConfirmed() || IsRejected()) | |
114 | { | |
115 | READWRITE(evidenceInputs); | |
116 | READWRITE(evidenceOutputs); | |
117 | } | |
118 | } | |
119 | ||
120 | bool IsValid() const | |
121 | { | |
122 | return version >= VERSION_FIRST && | |
123 | version <= VERSION_LAST && | |
124 | finalizationType != FINALIZE_INVALID && | |
125 | !currencyID.IsNull() && | |
126 | output.IsValid(); | |
127 | } | |
128 | ||
129 | EFinalizationType FinalizationType() const | |
130 | { | |
131 | return (EFinalizationType)(finalizationType & FINALIZE_TYPE_MASK); | |
132 | } | |
133 | ||
134 | bool IsPending() const | |
135 | { | |
136 | return !(finalizationType & FINALIZE_REJECTED || finalizationType & FINALIZE_CONFIRMED); | |
137 | } | |
138 | ||
139 | bool IsConfirmed() const | |
140 | { | |
141 | return finalizationType & FINALIZE_CONFIRMED; | |
142 | } | |
143 | ||
144 | void SetConfirmed(bool setTrue=true) | |
145 | { | |
146 | if (setTrue) | |
147 | { | |
148 | SetRejected(false); | |
149 | finalizationType |= FINALIZE_CONFIRMED; | |
150 | } | |
151 | else | |
152 | { | |
153 | finalizationType &= ~FINALIZE_CONFIRMED; | |
154 | } | |
155 | } | |
156 | ||
157 | bool IsRejected() const | |
158 | { | |
159 | return finalizationType & FINALIZE_REJECTED; | |
160 | } | |
161 | ||
162 | void SetRejected(bool setTrue=true) | |
163 | { | |
164 | if (setTrue) | |
165 | { | |
166 | SetConfirmed(false); | |
167 | finalizationType |= FINALIZE_REJECTED; | |
168 | } | |
169 | else | |
170 | { | |
171 | finalizationType &= ~FINALIZE_REJECTED; | |
172 | } | |
173 | } | |
174 | ||
175 | bool IsLaunchFinalization() const | |
176 | { | |
177 | return (finalizationType & FINALIZE_TYPE_MASK) == FINALIZE_CURRENCY_LAUNCH; | |
178 | } | |
179 | ||
180 | bool IsExportFinalization() const | |
181 | { | |
182 | return (finalizationType & FINALIZE_TYPE_MASK) == FINALIZE_EXPORT; | |
183 | } | |
184 | ||
185 | bool IsNotarizationFinalization() const | |
186 | { | |
187 | return (finalizationType & FINALIZE_TYPE_MASK) == FINALIZE_NOTARIZATION; | |
188 | } | |
189 | ||
190 | std::vector<unsigned char> AsVector() | |
191 | { | |
192 | return ::AsVector(*this); | |
193 | } | |
194 | ||
195 | bool GetOutputTransaction(const CTransaction &initialTx, CTransaction &tx, uint256 &blockHash) const; | |
196 | ||
197 | // Sign the output object with an ID or signing authority of the ID from the wallet. | |
198 | CNotaryEvidence SignConfirmed(const CWallet *pWallet, const CTransaction &initialTx, const CIdentityID &signatureID) const; | |
199 | CNotaryEvidence SignRejected(const CWallet *pWallet, const CTransaction &initialTx, const CIdentityID &signatureID) const; | |
200 | ||
201 | // Verify that the output object is signed with an ID or signing authority of the ID from the wallet. | |
202 | CIdentitySignature::ESignatureVerification VerifyOutputSignature(const CTransaction &initialTx, const CNotaryEvidence &signature, const COptCCParams &p, uint32_t height) const; | |
203 | CIdentitySignature::ESignatureVerification VerifyOutputSignature(const CTransaction &initialTx, const CNotaryEvidence &signature, uint32_t height) const; | |
204 | ||
205 | static std::vector<std::pair<uint32_t, CInputDescriptor>> GetUnspentConfirmedFinalizations(const uint160 ¤cyID); | |
206 | static std::vector<std::pair<uint32_t, CInputDescriptor>> GetUnspentPendingFinalizations(const uint160 ¤cyID); | |
207 | static std::vector<std::pair<uint32_t, CInputDescriptor>> GetUnspentEvidence(const uint160 ¤cyID, | |
208 | const uint256 ¬arizationTxId, | |
209 | int32_t notarizationOutNum); | |
210 | ||
211 | // enables easily finding all pending finalizations for a | |
212 | // currency, either notarizations or exports | |
213 | static std::string ObjectFinalizationPendingKeyName() | |
214 | { | |
215 | return "vrsc::system.finalization.pending"; | |
216 | } | |
217 | ||
218 | // enables easily finding all pending finalizations for a | |
219 | // currency, either notarizations or exports | |
220 | static std::string ObjectFinalizationPrelaunchKeyName() | |
221 | { | |
222 | return "vrsc::system.finalization.prelaunch"; | |
223 | } | |
224 | ||
225 | // enables easily finding all pending finalizations for a | |
226 | // currency, either notarizations or exports | |
227 | static std::string ObjectFinalizationNotarizationKeyName() | |
228 | { | |
229 | return "vrsc::system.finalization.notarization"; | |
230 | } | |
231 | ||
232 | // enables easily finding all pending finalizations for a | |
233 | // currency, either notarizations or exports | |
234 | static std::string ObjectFinalizationExportKeyName() | |
235 | { | |
236 | return "vrsc::system.finalization.export"; | |
237 | } | |
238 | ||
239 | // enables easily finding all confirmed finalizations | |
240 | static std::string ObjectFinalizationConfirmedKeyName() | |
241 | { | |
242 | return "vrsc::system.finalization.confirmed"; | |
243 | } | |
244 | ||
245 | // enables location of rejected finalizations | |
246 | static std::string ObjectFinalizationRejectedKeyName() | |
247 | { | |
248 | return "vrsc::system.finalization.rejected"; | |
249 | } | |
250 | ||
251 | static uint160 ObjectFinalizationPendingKey() | |
252 | { | |
253 | static uint160 nameSpace; | |
254 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationPendingKeyName(), nameSpace); | |
255 | return key; | |
256 | } | |
257 | ||
258 | static uint160 ObjectFinalizationPrelaunchKey() | |
259 | { | |
260 | static uint160 nameSpace; | |
261 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationPrelaunchKeyName(), nameSpace); | |
262 | return key; | |
263 | } | |
264 | ||
265 | static uint160 ObjectFinalizationNotarizationKey() | |
266 | { | |
267 | static uint160 nameSpace; | |
268 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationNotarizationKeyName(), nameSpace); | |
269 | return key; | |
270 | } | |
271 | ||
272 | static uint160 ObjectFinalizationExportKey() | |
273 | { | |
274 | static uint160 nameSpace; | |
275 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationExportKeyName(), nameSpace); | |
276 | return key; | |
277 | } | |
278 | ||
279 | static uint160 ObjectFinalizationConfirmedKey() | |
280 | { | |
281 | static uint160 nameSpace; | |
282 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationConfirmedKeyName(), nameSpace); | |
283 | return key; | |
284 | } | |
285 | ||
286 | static uint160 ObjectFinalizationRejectedKey() | |
287 | { | |
288 | static uint160 nameSpace; | |
289 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationRejectedKeyName(), nameSpace); | |
290 | return key; | |
291 | } | |
292 | ||
293 | UniValue ToUniValue() const; | |
294 | }; | |
295 | ||
296 | class CChainNotarizationData | |
297 | { | |
298 | public: | |
299 | static const int CURRENT_VERSION = PBAAS_VERSION; | |
300 | uint32_t version; | |
301 | ||
302 | std::vector<std::pair<CUTXORef, CPBaaSNotarization>> vtx; | |
303 | int32_t lastConfirmed; // last confirmed notarization | |
304 | std::vector<std::vector<int32_t>> forks; // chains that represent alternate branches from the last confirmed notarization | |
305 | int32_t bestChain; // index in forks of the chain, beginning with the last confirmed notarization, that has the most power | |
306 | ||
307 | CChainNotarizationData() : version(0), lastConfirmed(-1) {} | |
308 | ||
309 | CChainNotarizationData(const std::vector<std::pair<CUTXORef, CPBaaSNotarization>> &txes, | |
310 | int32_t lastConf=-1, | |
311 | const std::vector<std::vector<int32_t>> &Forks=std::vector<std::vector<int32_t>>(), | |
312 | int32_t Best=-1, | |
313 | uint32_t ver=CURRENT_VERSION) : | |
314 | version(ver), | |
315 | vtx(txes), | |
316 | lastConfirmed(lastConf), | |
317 | bestChain(Best), | |
318 | forks(Forks) {} | |
319 | ||
320 | CChainNotarizationData(std::vector<unsigned char> vch) | |
321 | { | |
322 | ::FromVector(vch, *this); | |
323 | } | |
324 | ||
325 | CChainNotarizationData(UniValue &obj); | |
326 | ||
327 | ADD_SERIALIZE_METHODS; | |
328 | ||
329 | template <typename Stream, typename Operation> | |
330 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
331 | READWRITE(version); | |
332 | READWRITE(vtx); | |
333 | READWRITE(bestChain); | |
334 | READWRITE(lastConfirmed); | |
335 | READWRITE(forks); | |
336 | } | |
337 | ||
338 | std::vector<unsigned char> AsVector() | |
339 | { | |
340 | return ::AsVector(*this); | |
341 | } | |
342 | ||
343 | bool IsValid() const | |
344 | { | |
345 | // this needs an actual check | |
346 | return version != 0; | |
347 | } | |
348 | ||
349 | bool IsConfirmed() const | |
350 | { | |
351 | return lastConfirmed != -1; | |
352 | } | |
353 | ||
354 | UniValue ToUniValue() const; | |
355 | }; | |
356 | ||
357 | std::vector<CNodeData> GetGoodNodes(int maxNum=CCurrencyDefinition::MAX_STARTUP_NODES); | |
358 | bool ValidateEarnedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); | |
359 | bool IsEarnedNotarizationInput(const CScript &scriptSig); | |
360 | bool ValidateAcceptedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); | |
361 | bool IsAcceptedNotarizationInput(const CScript &scriptSig); | |
362 | bool ValidateFinalizeNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); | |
363 | bool IsFinalizeNotarizationInput(const CScript &scriptSig); | |
364 | bool IsNotaryEvidenceInput(const CScript &scriptSig); | |
365 | extern string PBAAS_HOST, PBAAS_USERPASS, ASSETCHAINS_RPCHOST, ASSETCHAINS_RPCCREDENTIALS;; | |
366 | extern int32_t PBAAS_PORT; | |
367 | ||
368 | #endif |