]>
Commit | Line | Data |
---|---|---|
b2a98c42 MT |
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 | ||
a6e612cc MT |
60 | #ifndef PBAAS_NOTARIZATION_H |
61 | #define PBAAS_NOTARIZATION_H | |
b2a98c42 | 62 | |
b2a98c42 | 63 | #include "key_io.h" |
56fe75cb | 64 | #include "pbaas/pbaas.h" |
b2a98c42 | 65 | |
c8c684e9 | 66 | class CObjectFinalization |
b2a98c42 MT |
67 | { |
68 | public: | |
4a53088e | 69 | static const int32_t UNCONFIRMED_INPUT = -1; |
c8c684e9 | 70 | enum { |
71 | VERSION_INVALID = 0, | |
72 | VERSION_FIRST = 1, | |
73 | VERSION_LAST = 1, | |
74 | VERSION_CURRENT = 1 | |
75 | }; | |
76 | ||
77 | enum EFinalizationType { | |
2d8b9129 | 78 | FINALIZE_INVALID = 0, |
c8c684e9 | 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) | |
2d8b9129 | 85 | }; |
b2a98c42 | 86 | |
c8c684e9 | 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) {} | |
48ccc7f5 | 98 | CObjectFinalization(const std::vector<unsigned char> &vch) |
b2a98c42 MT |
99 | { |
100 | ::FromVector(vch, *this); | |
101 | } | |
c8c684e9 | 102 | CObjectFinalization(const CTransaction &tx, uint32_t *pEcode=nullptr, int32_t *pFinalizationOutNum=nullptr); |
48ccc7f5 | 103 | CObjectFinalization(const CScript &script); |
b2a98c42 MT |
104 | |
105 | ADD_SERIALIZE_METHODS; | |
106 | ||
107 | template <typename Stream, typename Operation> | |
108 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
c8c684e9 | 109 | READWRITE(version); |
2d8b9129 | 110 | READWRITE(finalizationType); |
111 | READWRITE(currencyID); | |
c8c684e9 | 112 | READWRITE(output); |
113 | if (IsConfirmed() || IsRejected()) | |
114 | { | |
115 | READWRITE(evidenceInputs); | |
116 | READWRITE(evidenceOutputs); | |
117 | } | |
b2a98c42 MT |
118 | } |
119 | ||
a613ac6c | 120 | bool IsValid() const |
b2a98c42 | 121 | { |
c8c684e9 | 122 | return version >= VERSION_FIRST && |
123 | version <= VERSION_LAST && | |
124 | finalizationType != FINALIZE_INVALID && | |
125 | !currencyID.IsNull() && | |
126 | output.IsValid(); | |
127 | } | |
128 | ||
54f68f98 | 129 | EFinalizationType FinalizationType() const |
130 | { | |
131 | return (EFinalizationType)(finalizationType & FINALIZE_TYPE_MASK); | |
132 | } | |
133 | ||
c8c684e9 | 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; | |
b2a98c42 MT |
188 | } |
189 | ||
190 | std::vector<unsigned char> AsVector() | |
191 | { | |
192 | return ::AsVector(*this); | |
193 | } | |
e87527cf | 194 | |
c8c684e9 | 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 | ||
48ccc7f5 | 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); | |
c8c684e9 | 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 | { | |
7c8e5e18 | 253 | static uint160 nameSpace; |
254 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationPendingKeyName(), nameSpace); | |
c8c684e9 | 255 | return key; |
256 | } | |
257 | ||
258 | static uint160 ObjectFinalizationPrelaunchKey() | |
259 | { | |
7c8e5e18 | 260 | static uint160 nameSpace; |
261 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationPrelaunchKeyName(), nameSpace); | |
c8c684e9 | 262 | return key; |
263 | } | |
264 | ||
265 | static uint160 ObjectFinalizationNotarizationKey() | |
266 | { | |
7c8e5e18 | 267 | static uint160 nameSpace; |
268 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationNotarizationKeyName(), nameSpace); | |
c8c684e9 | 269 | return key; |
270 | } | |
271 | ||
272 | static uint160 ObjectFinalizationExportKey() | |
273 | { | |
7c8e5e18 | 274 | static uint160 nameSpace; |
275 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationExportKeyName(), nameSpace); | |
c8c684e9 | 276 | return key; |
277 | } | |
278 | ||
279 | static uint160 ObjectFinalizationConfirmedKey() | |
280 | { | |
7c8e5e18 | 281 | static uint160 nameSpace; |
282 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationConfirmedKeyName(), nameSpace); | |
c8c684e9 | 283 | return key; |
284 | } | |
285 | ||
286 | static uint160 ObjectFinalizationRejectedKey() | |
287 | { | |
7c8e5e18 | 288 | static uint160 nameSpace; |
289 | static uint160 key = CVDXF::GetDataKey(ObjectFinalizationRejectedKeyName(), nameSpace); | |
c8c684e9 | 290 | return key; |
291 | } | |
292 | ||
2d8b9129 | 293 | UniValue ToUniValue() const; |
b2a98c42 MT |
294 | }; |
295 | ||
296 | class CChainNotarizationData | |
297 | { | |
298 | public: | |
299 | static const int CURRENT_VERSION = PBAAS_VERSION; | |
300 | uint32_t version; | |
b2a98c42 | 301 | |
c8c684e9 | 302 | std::vector<std::pair<CUTXORef, CPBaaSNotarization>> vtx; |
b2a98c42 MT |
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 | ||
4fa3b13d | 307 | CChainNotarizationData() : version(0), lastConfirmed(-1) {} |
b2a98c42 | 308 | |
c8c684e9 | 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) {} | |
b2a98c42 MT |
319 | |
320 | CChainNotarizationData(std::vector<unsigned char> vch) | |
321 | { | |
322 | ::FromVector(vch, *this); | |
323 | } | |
324 | ||
4fa3b13d MT |
325 | CChainNotarizationData(UniValue &obj); |
326 | ||
b2a98c42 MT |
327 | ADD_SERIALIZE_METHODS; |
328 | ||
329 | template <typename Stream, typename Operation> | |
330 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
331 | READWRITE(version); | |
b2a98c42 MT |
332 | READWRITE(vtx); |
333 | READWRITE(bestChain); | |
c8c684e9 | 334 | READWRITE(lastConfirmed); |
b2a98c42 MT |
335 | READWRITE(forks); |
336 | } | |
337 | ||
338 | std::vector<unsigned char> AsVector() | |
339 | { | |
340 | return ::AsVector(*this); | |
341 | } | |
342 | ||
a613ac6c | 343 | bool IsValid() const |
b2a98c42 MT |
344 | { |
345 | // this needs an actual check | |
346 | return version != 0; | |
347 | } | |
348 | ||
59a836ff | 349 | bool IsConfirmed() const |
b2a98c42 MT |
350 | { |
351 | return lastConfirmed != -1; | |
352 | } | |
353 | ||
4fa3b13d | 354 | UniValue ToUniValue() const; |
b2a98c42 MT |
355 | }; |
356 | ||
6bfcc4ec | 357 | std::vector<CNodeData> GetGoodNodes(int maxNum=CCurrencyDefinition::MAX_STARTUP_NODES); |
4ecaf167 | 358 | bool ValidateEarnedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); |
68b309c0 | 359 | bool IsEarnedNotarizationInput(const CScript &scriptSig); |
4ecaf167 | 360 | bool ValidateAcceptedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); |
68b309c0 | 361 | bool IsAcceptedNotarizationInput(const CScript &scriptSig); |
4ecaf167 | 362 | bool ValidateFinalizeNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled); |
68b309c0 | 363 | bool IsFinalizeNotarizationInput(const CScript &scriptSig); |
c8c684e9 | 364 | bool IsNotaryEvidenceInput(const CScript &scriptSig); |
76f69285 | 365 | extern string PBAAS_HOST, PBAAS_USERPASS, ASSETCHAINS_RPCHOST, ASSETCHAINS_RPCCREDENTIALS;; |
366 | extern int32_t PBAAS_PORT; | |
68b309c0 | 367 | |
b2a98c42 | 368 | #endif |