forked from dashpay/dash
/
specialtx.cpp
143 lines (120 loc) · 4.19 KB
/
specialtx.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (c) 2018 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chainparams.h"
#include "clientversion.h"
#include "consensus/validation.h"
#include "hash.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "validation.h"
#include "cbtx.h"
#include "deterministicmns.h"
#include "specialtx.h"
#include "llmq/quorums_commitment.h"
#include "llmq/quorums_blockprocessor.h"
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL)
return true;
if (pindexPrev && VersionBitsState(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) != THRESHOLD_ACTIVE) {
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type");
}
switch (tx.nType) {
case TRANSACTION_PROVIDER_REGISTER:
return CheckProRegTx(tx, pindexPrev, state);
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
return CheckProUpServTx(tx, pindexPrev, state);
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
return CheckProUpRegTx(tx, pindexPrev, state);
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return CheckProUpRevTx(tx, pindexPrev, state);
case TRANSACTION_COINBASE:
return CheckCbTx(tx, pindexPrev, state);
case TRANSACTION_QUORUM_COMMITMENT:
return llmq::CheckLLMQCommitment(tx, pindexPrev, state);
}
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type-check");
}
bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state)
{
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
return true;
}
switch (tx.nType) {
case TRANSACTION_PROVIDER_REGISTER:
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return true; // handled in batches per block
case TRANSACTION_COINBASE:
return true; // nothing to do
case TRANSACTION_QUORUM_COMMITMENT:
return true; // handled per block
}
return state.DoS(100, false, REJECT_INVALID, "bad-tx-type-proc");
}
bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
{
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
return true;
}
switch (tx.nType) {
case TRANSACTION_PROVIDER_REGISTER:
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return true; // handled in batches per block
case TRANSACTION_COINBASE:
return true; // nothing to do
case TRANSACTION_QUORUM_COMMITMENT:
return true; // handled per block
}
return false;
}
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state)
{
for (int i = 0; i < (int)block.vtx.size(); i++) {
const CTransaction& tx = *block.vtx[i];
if (!CheckSpecialTx(tx, pindex->pprev, state)) {
return false;
}
if (!ProcessSpecialTx(tx, pindex, state)) {
return false;
}
}
if (!llmq::quorumBlockProcessor->ProcessBlock(block, pindex->pprev, state)) {
return false;
}
if (!deterministicMNManager->ProcessBlock(block, pindex->pprev, state)) {
return false;
}
if (!CheckCbTxMerkleRootMNList(block, pindex, state)) {
return false;
}
return true;
}
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex)
{
for (int i = (int)block.vtx.size() - 1; i >= 0; --i) {
const CTransaction& tx = *block.vtx[i];
if (!UndoSpecialTx(tx, pindex)) {
return false;
}
}
if (!deterministicMNManager->UndoBlock(block, pindex)) {
return false;
}
if (!llmq::quorumBlockProcessor->UndoBlock(block, pindex)) {
return false;
}
return true;
}
uint256 CalcTxInputsHash(const CTransaction& tx)
{
CHashWriter hw(CLIENT_VERSION, SER_GETHASH);
for (const auto& in : tx.vin) {
hw << in.prevout;
}
return hw.GetHash();
}