]>
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 | ||
60 | #ifndef NOTARIZATION_H | |
61 | #define NOTARIZATION_H | |
62 | ||
63 | #include "pbaas/pbaas.h" | |
64 | #include "key_io.h" | |
65 | ||
66 | // This is the data for a PBaaS notarization transaction, either of a PBaaS chain into the Verus chain, or the Verus | |
67 | // chain into a PBaaS chain. | |
68 | ||
69 | // Part of a transaction with an opret that contains only the hashes and proofs, without the source | |
70 | // headers, transactions, and objects. This type of notarizatoin is mined into a block by the miner, and is created on the PBaaS | |
71 | // chain. | |
1fa4454d MT |
72 | // |
73 | // Notarizations include the following elements in order: | |
74 | // Latest block header being notarized, or a header ref for a merge-mined header | |
75 | // Proof of the header using the latest MMR root | |
76 | // Cross notarization transaction less its op_ret | |
77 | // Proof of the cross notarization using the latest MMR root | |
b2a98c42 MT |
78 | class CPBaaSNotarization |
79 | { | |
80 | public: | |
81 | static const int FINAL_CONFIRMATIONS = 10; | |
4fa3b13d | 82 | static const int MIN_BLOCKS_BETWEEN_ACCEPTED = 8; |
b2a98c42 MT |
83 | static const int CURRENT_VERSION = PBAAS_VERSION; |
84 | uint32_t nVersion; // PBAAS version | |
85 | uint160 chainID; // chain being notarized | |
1fa4454d | 86 | uint160 notaryKeyID; // confirmed notary rewards are spent to this address when this notarization is confirmed |
b2a98c42 MT |
87 | |
88 | uint32_t notarizationHeight; // height of the notarization we certify | |
89 | uint256 mmrRoot; // latest MMR root of the notarization height | |
1fa4454d | 90 | uint256 notarizationPreHash; // combination of block hash, merkle root, and compact power for the notarization height |
b2a98c42 MT |
91 | uint256 compactPower; // compact power of the block height notarization to compare |
92 | ||
93 | uint256 prevNotarization; // txid of the prior notarization on this chain that we agree with, even those not accepted yet | |
94 | int32_t prevHeight; | |
9f00b96a | 95 | uint256 crossNotarization; // hash of previous notarization transaction on the other chain, which is the first tx object in the opret input |
b2a98c42 MT |
96 | int32_t crossHeight; |
97 | ||
98 | COpRetProof opRetProof; // hashes and types of all objects in our opret, enabling reconstruction without the opret on notarized chain | |
99 | ||
9f0c14b2 | 100 | std::vector<CNodeData> nodes; // network nodes |
b2a98c42 MT |
101 | |
102 | CPBaaSNotarization() : nVersion(PBAAS_VERSION_INVALID) { } | |
103 | ||
104 | CPBaaSNotarization(uint32_t version, | |
105 | uint160 chainid, | |
1fa4454d | 106 | uint160 notarykey, |
b2a98c42 | 107 | int32_t notarizationheight, |
1fa4454d MT |
108 | uint256 MMRRoot, |
109 | uint256 preHash, | |
b2a98c42 MT |
110 | uint256 compactpower, |
111 | uint256 prevnotarization, | |
112 | int32_t prevheight, | |
113 | uint256 crossnotarization, | |
114 | int32_t crossheight, | |
115 | COpRetProof orp, | |
9f0c14b2 | 116 | std::vector<CNodeData> &Nodes) : |
b2a98c42 MT |
117 | nVersion(version), |
118 | chainID(chainid), | |
1fa4454d | 119 | notaryKeyID(notarykey), |
b2a98c42 MT |
120 | |
121 | notarizationHeight(notarizationheight), | |
122 | mmrRoot(MMRRoot), | |
1fa4454d | 123 | notarizationPreHash(preHash), |
b2a98c42 MT |
124 | compactPower(compactpower), |
125 | ||
126 | prevNotarization(prevnotarization), | |
127 | prevHeight(prevheight), | |
128 | crossNotarization(crossnotarization), | |
129 | crossHeight(crossheight), | |
130 | ||
131 | opRetProof(orp), | |
132 | ||
9f0c14b2 | 133 | nodes(Nodes) |
b2a98c42 MT |
134 | { } |
135 | ||
136 | CPBaaSNotarization(const std::vector<unsigned char> &asVector) | |
137 | { | |
138 | ::FromVector(asVector, *this); | |
139 | } | |
140 | ||
141 | CPBaaSNotarization(const CTransaction &tx, bool validate = false); | |
142 | ||
4fa3b13d MT |
143 | CPBaaSNotarization(const UniValue &obj); |
144 | ||
b2a98c42 MT |
145 | ADD_SERIALIZE_METHODS; |
146 | ||
147 | template <typename Stream, typename Operation> | |
148 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
149 | READWRITE(VARINT(nVersion)); | |
150 | READWRITE(chainID); | |
1fa4454d | 151 | READWRITE(notaryKeyID); |
b2a98c42 MT |
152 | READWRITE(notarizationHeight); |
153 | READWRITE(mmrRoot); | |
1fa4454d | 154 | READWRITE(notarizationPreHash); |
b2a98c42 MT |
155 | READWRITE(compactPower); |
156 | READWRITE(prevNotarization); | |
157 | READWRITE(prevHeight); | |
158 | READWRITE(crossNotarization); | |
159 | READWRITE(crossHeight); | |
160 | READWRITE(opRetProof); | |
9f0c14b2 | 161 | READWRITE(nodes); |
b2a98c42 MT |
162 | } |
163 | ||
164 | std::vector<unsigned char> AsVector() | |
165 | { | |
166 | return ::AsVector(*this); | |
167 | } | |
168 | ||
169 | bool IsValid() | |
170 | { | |
171 | return !mmrRoot.IsNull(); | |
172 | } | |
173 | ||
4fa3b13d | 174 | UniValue ToUniValue() const; |
b2a98c42 MT |
175 | }; |
176 | ||
177 | class CNotarizationFinalization | |
178 | { | |
179 | public: | |
180 | int32_t confirmedInput; | |
181 | ||
182 | CNotarizationFinalization() : confirmedInput(-1) {} | |
183 | CNotarizationFinalization(int32_t nIn) : confirmedInput(nIn) {} | |
184 | CNotarizationFinalization(std::vector<unsigned char> vch) | |
185 | { | |
186 | ::FromVector(vch, *this); | |
187 | } | |
188 | CNotarizationFinalization(const CTransaction &tx, bool validate=false); | |
189 | ||
190 | ADD_SERIALIZE_METHODS; | |
191 | ||
192 | template <typename Stream, typename Operation> | |
193 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
194 | READWRITE(confirmedInput); | |
195 | } | |
196 | ||
197 | bool IsValid() | |
198 | { | |
199 | return confirmedInput != -1; | |
200 | } | |
201 | ||
202 | std::vector<unsigned char> AsVector() | |
203 | { | |
204 | return ::AsVector(*this); | |
205 | } | |
e87527cf MT |
206 | |
207 | UniValue ToUniValue() const | |
208 | { | |
209 | UniValue ret(UniValue::VOBJ); | |
210 | ret.push_back(Pair("confirmedinput", confirmedInput)); | |
211 | return ret; | |
212 | } | |
b2a98c42 MT |
213 | }; |
214 | ||
215 | class CChainNotarizationData | |
216 | { | |
217 | public: | |
218 | static const int CURRENT_VERSION = PBAAS_VERSION; | |
219 | uint32_t version; | |
b2a98c42 MT |
220 | |
221 | std::vector<std::pair<uint256, CPBaaSNotarization>> vtx; | |
222 | int32_t lastConfirmed; // last confirmed notarization | |
223 | std::vector<std::vector<int32_t>> forks; // chains that represent alternate branches from the last confirmed notarization | |
224 | int32_t bestChain; // index in forks of the chain, beginning with the last confirmed notarization, that has the most power | |
225 | ||
4fa3b13d | 226 | CChainNotarizationData() : version(0), lastConfirmed(-1) {} |
b2a98c42 MT |
227 | |
228 | CChainNotarizationData(uint32_t ver, int32_t start, int32_t end, | |
229 | std::vector<std::pair<uint256, CPBaaSNotarization>> txes, | |
230 | int32_t lastConf, | |
231 | std::vector<std::vector<int32_t>> &Forks, | |
232 | int32_t Best) : | |
4fa3b13d | 233 | version(ver), |
b2a98c42 MT |
234 | vtx(txes), lastConfirmed(lastConf), bestChain(Best), forks(Forks) {} |
235 | ||
236 | CChainNotarizationData(std::vector<unsigned char> vch) | |
237 | { | |
238 | ::FromVector(vch, *this); | |
239 | } | |
240 | ||
4fa3b13d MT |
241 | CChainNotarizationData(UniValue &obj); |
242 | ||
b2a98c42 MT |
243 | ADD_SERIALIZE_METHODS; |
244 | ||
245 | template <typename Stream, typename Operation> | |
246 | inline void SerializationOp(Stream& s, Operation ser_action) { | |
247 | READWRITE(version); | |
b2a98c42 MT |
248 | READWRITE(vtx); |
249 | READWRITE(bestChain); | |
250 | READWRITE(forks); | |
251 | } | |
252 | ||
253 | std::vector<unsigned char> AsVector() | |
254 | { | |
255 | return ::AsVector(*this); | |
256 | } | |
257 | ||
258 | bool IsValid() | |
259 | { | |
260 | // this needs an actual check | |
261 | return version != 0; | |
262 | } | |
263 | ||
264 | bool IsConfirmed() | |
265 | { | |
266 | return lastConfirmed != -1; | |
267 | } | |
268 | ||
4fa3b13d | 269 | UniValue ToUniValue() const; |
b2a98c42 MT |
270 | }; |
271 | ||
13ed2980 MT |
272 | class CInputDescriptor |
273 | { | |
274 | public: | |
275 | CScript scriptPubKey; | |
276 | CAmount nValue; | |
277 | CTxIn txIn; | |
278 | CInputDescriptor() : nValue(0) {} | |
279 | CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {} | |
280 | }; | |
281 | ||
282 | bool CreateEarnedNotarization(CMutableTransaction &mnewTx, std::vector<CInputDescriptor> &inputs, CTransaction &lastTx, CTransaction &crossTx, int32_t height, int32_t *confirmedInput, CTxDestination *confirmedDest); | |
572c763f | 283 | uint256 CreateAcceptedNotarization(const CBlock &blk, int32_t txIndex, int32_t height); |
ba256d3a MT |
284 | std::vector<CInputDescriptor> AddSpendsAndFinalizations(const CChainNotarizationData &cnd, |
285 | const uint256 &lastNotarizationID, | |
286 | const CTransaction &lastTx, | |
287 | CMutableTransaction &mnewTx, | |
288 | int32_t *pConfirmedInput, | |
289 | int32_t *pConfirmedIdx, | |
290 | CTxDestination *pConfirmedDest); | |
1fa4454d MT |
291 | bool GetNotarizationAndFinalization(int32_t ecode, CMutableTransaction mtx, CPBaaSNotarization &pbn, uint32_t *pNotarizeOutIndex, uint32_t *pFinalizeOutIndex); |
292 | bool ValidateEarnedNotarization(CTransaction &ntx, CPBaaSNotarization *notarization = NULL); | |
68b309c0 MT |
293 | bool ValidateEarnedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); |
294 | bool IsEarnedNotarizationInput(const CScript &scriptSig); | |
295 | bool ValidateAcceptedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); | |
296 | bool IsAcceptedNotarizationInput(const CScript &scriptSig); | |
297 | bool ValidateFinalizeNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); | |
298 | bool IsFinalizeNotarizationInput(const CScript &scriptSig); | |
13ed2980 | 299 | bool IsServiceRewardInput(const CScript &scriptSig); |
8577896f | 300 | bool IsBlockBoundTransaction(const CTransaction &tx); |
68b309c0 | 301 | |
b2a98c42 | 302 | #endif |