Incorporate all Zcash updates through 2.0.7-3 in addition to PBaaS, reserves, etc.
[VerusCoin.git] / src / gtest / test_checkblock.cpp
1 #include <gtest/gtest.h>
2 #include <gmock/gmock.h>
3
4 #include "consensus/validation.h"
5 #include "main.h"
6 #include "utiltest.h"
7 #include "zcash/Proof.hpp"
8
9 class MockCValidationState : public CValidationState {
10 public:
11     MOCK_METHOD5(DoS, bool(int level, bool ret,
12              unsigned char chRejectCodeIn, std::string strRejectReasonIn,
13              bool corruptionIn));
14     MOCK_METHOD3(Invalid, bool(bool ret,
15                  unsigned char _chRejectCode, std::string _strRejectReason));
16     MOCK_METHOD1(Error, bool(std::string strRejectReasonIn));
17     MOCK_CONST_METHOD0(IsValid, bool());
18     MOCK_CONST_METHOD0(IsInvalid, bool());
19     MOCK_CONST_METHOD0(IsError, bool());
20     MOCK_CONST_METHOD1(IsInvalid, bool(int &nDoSOut));
21     MOCK_CONST_METHOD0(CorruptionPossible, bool());
22     MOCK_CONST_METHOD0(GetRejectCode, unsigned char());
23     MOCK_CONST_METHOD0(GetRejectReason, std::string());
24 };
25
26 int32_t futureblock;
27 TEST(CheckBlock, VersionTooLow) {
28     auto verifier = libzcash::ProofVerifier::Strict();
29
30     CBlock block;
31     block.nVersion = 1;
32
33     MockCValidationState state;
34     EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1);
35     EXPECT_FALSE(CheckBlock(&futureblock, 0, 0, block, state, Params(), verifier, false, false));
36 }
37
38
39 // Test that a Sprout tx with negative version is still rejected
40 // by CheckBlock under Sprout consensus rules.
41 TEST(CheckBlock, BlockSproutRejectsBadVersion) {
42     SelectParams(CBaseChainParams::MAIN);
43
44     CMutableTransaction mtx;
45     mtx.vin.resize(1);
46     mtx.vin[0].prevout.SetNull();
47     mtx.vin[0].scriptSig = CScript() << 1 << OP_0;
48     mtx.vout.resize(1);
49     mtx.vout[0].scriptPubKey = CScript() << OP_TRUE;
50     mtx.vout[0].nValue = 0;
51     mtx.vout.push_back(CTxOut(
52         GetBlockSubsidy(1, Params().GetConsensus())/5,
53         Params().GetFoundersRewardScriptAtHeight(1)));
54     mtx.fOverwintered = false;
55     mtx.nVersion = -1;
56     mtx.nVersionGroupId = 0;
57
58     CTransaction tx {mtx};
59     CBlock block;
60     block.vtx.push_back(tx);
61
62     MockCValidationState state;
63     CBlockIndex indexPrev {Params().GenesisBlock()};
64
65     auto verifier = libzcash::ProofVerifier::Strict();
66
67     EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1);
68     EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false));
69 }
70
71
72 class ContextualCheckBlockTest : public ::testing::Test {
73 protected:
74     virtual void SetUp() {
75         SelectParams(CBaseChainParams::MAIN);
76     }
77
78     virtual void TearDown() {
79         // Revert to test default. No-op on mainnet params.
80         RegtestDeactivateSapling();
81     }
82
83     // Returns a valid but empty mutable transaction at block height 1.
84     CMutableTransaction GetFirstBlockCoinbaseTx() {
85         CMutableTransaction mtx;
86
87         // No inputs.
88         mtx.vin.resize(1);
89         mtx.vin[0].prevout.SetNull();
90
91         // Set height to 1.
92         mtx.vin[0].scriptSig = CScript() << 1 << OP_0;
93
94         // Give it a single zero-valued, always-valid output.
95         mtx.vout.resize(1);
96         mtx.vout[0].scriptPubKey = CScript() << OP_TRUE;
97         mtx.vout[0].nValue = 0;
98
99         // Give it a Founder's Reward vout for height 1.
100         mtx.vout.push_back(CTxOut(
101                     GetBlockSubsidy(1, Params().GetConsensus())/5,
102                     Params().GetFoundersRewardScriptAtHeight(1)));
103
104         return mtx;
105     }
106
107     // Expects a height-1 block containing a given transaction to pass
108     // ContextualCheckBlock. This is used in accepting (Sprout-Sprout,
109     // Overwinter-Overwinter, ...) tests. You should not call it without
110     // calling a SCOPED_TRACE macro first to usefully label any failures.
111     void ExpectValidBlockFromTx(const CTransaction& tx) {
112         // Create a block and add the transaction to it.
113         CBlock block;
114         block.vtx.push_back(tx);
115
116         // Set the previous block index to the genesis block.
117         CBlockIndex indexPrev {Params().GenesisBlock()};
118
119         // We now expect this to be a valid block.
120         MockCValidationState state;
121         EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev));
122     }
123
124     // Expects a height-1 block containing a given transaction to fail
125     // ContextualCheckBlock. This is used in rejecting (Sprout-Overwinter,
126     // Overwinter-Sprout, ...) tests. You should not call it without
127     // calling a SCOPED_TRACE macro first to usefully label any failures.
128     void ExpectInvalidBlockFromTx(const CTransaction& tx, int level, std::string reason) {
129         // Create a block and add the transaction to it.
130         CBlock block;
131         block.vtx.push_back(tx);
132
133         // Set the previous block index to the genesis block.
134         CBlockIndex indexPrev {Params().GenesisBlock()};
135
136         // We now expect this to be an invalid block, for the given reason.
137         MockCValidationState state;
138         EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)).Times(1);
139         EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
140     }
141
142 };
143
144
145 TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) {
146     // Put a transaction in a block with no height in scriptSig
147     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
148     mtx.vin[0].scriptSig = CScript() << OP_0;
149     mtx.vout.pop_back(); // remove the FR output
150
151     CBlock block;
152     block.vtx.push_back(mtx);
153
154     // Treating block as genesis should pass
155     MockCValidationState state;
156     EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), NULL));
157
158     // Give the transaction a Founder's Reward vout
159     mtx.vout.push_back(CTxOut(
160                 GetBlockSubsidy(1, Params().GetConsensus())/5,
161                 Params().GetFoundersRewardScriptAtHeight(1)));
162
163     // Treating block as non-genesis should fail
164     CTransaction tx2 {mtx};
165     block.vtx[0] = tx2;
166     CBlock prev;
167     CBlockIndex indexPrev {prev};
168     indexPrev.SetHeight(0);
169     EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
170     EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
171
172     // Setting to an incorrect height should fail
173     mtx.vin[0].scriptSig = CScript() << 2 << OP_0;
174     CTransaction tx3 {mtx};
175     block.vtx[0] = tx3;
176     EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1);
177     EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev));
178
179     // After correcting the scriptSig, should pass
180     mtx.vin[0].scriptSig = CScript() << 1 << OP_0;
181     CTransaction tx4 {mtx};
182     block.vtx[0] = tx4;
183     EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev));
184 }
185
186 // TEST PLAN: first, check that each ruleset accepts its own transaction type.
187 // Currently (May 2018) this means we'll test Sprout-Sprout,
188 // Overwinter-Overwinter, and Sapling-Sapling.
189
190 // Test block evaluated under Sprout rules will accept Sprout transactions.
191 // This test assumes that mainnet Overwinter activation is at least height 2.
192 TEST_F(ContextualCheckBlockTest, BlockSproutRulesAcceptSproutTx) {
193     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
194
195     // Make it a Sprout transaction w/o JoinSplits
196     mtx.fOverwintered = false;
197     mtx.nVersion = 1;
198
199     SCOPED_TRACE("BlockSproutRulesAcceptSproutTx");
200     ExpectValidBlockFromTx(CTransaction(mtx));
201 }
202
203
204 // Test block evaluated under Overwinter rules will accept Overwinter transactions.
205 TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesAcceptOverwinterTx) {
206     SelectParams(CBaseChainParams::REGTEST);
207     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, 1);
208
209     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
210
211     // Make it an Overwinter transaction
212     mtx.fOverwintered = true;
213     mtx.nVersion = OVERWINTER_TX_VERSION;
214     mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
215
216     SCOPED_TRACE("BlockOverwinterRulesAcceptOverwinterTx");
217     ExpectValidBlockFromTx(CTransaction(mtx));
218 }
219
220
221 // Test that a block evaluated under Sapling rules can contain Sapling transactions.
222 TEST_F(ContextualCheckBlockTest, BlockSaplingRulesAcceptSaplingTx) {
223     SelectParams(CBaseChainParams::REGTEST);
224     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, 1);
225     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, 1);
226
227     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
228
229     // Make it a Sapling transaction
230     mtx.fOverwintered = true;
231     mtx.nVersion = SAPLING_TX_VERSION;
232     mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
233
234     SCOPED_TRACE("BlockSaplingRulesAcceptSaplingTx");
235     ExpectValidBlockFromTx(CTransaction(mtx));
236 }
237
238 // TEST PLAN: next, check that each ruleset will not accept other transaction
239 // types. Currently (May 2018) this means we'll test Sprout-Overwinter,
240 // Sprout-Sapling, Overwinter-Sprout, Overwinter-Sapling, Sapling-Sprout, and
241 // Sapling-Overwinter.
242
243 // Test that a block evaluated under Sprout rules cannot contain non-Sprout
244 // transactions which require Overwinter to be active.  This test assumes that
245 // mainnet Overwinter activation is at least height 2.
246 TEST_F(ContextualCheckBlockTest, BlockSproutRulesRejectOtherTx) {
247     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
248
249     // Make it an Overwinter transaction
250     mtx.fOverwintered = true;
251     mtx.nVersion = OVERWINTER_TX_VERSION;
252     mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
253
254     {
255         SCOPED_TRACE("BlockSproutRulesRejectOverwinterTx");
256         ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "tx-overwinter-not-active");
257     }
258
259     // Make it a Sapling transaction
260     mtx.fOverwintered = true;
261     mtx.nVersion = SAPLING_TX_VERSION;
262     mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
263
264     {
265         SCOPED_TRACE("BlockSproutRulesRejectSaplingTx");
266         ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "tx-overwinter-not-active");
267     }
268 };
269
270
271 // Test block evaluated under Overwinter rules cannot contain non-Overwinter
272 // transactions.
273 TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesRejectOtherTx) {
274     SelectParams(CBaseChainParams::REGTEST);
275     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, 1);
276
277     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
278
279     // Set the version to Sprout+JoinSplit (but nJoinSplit will be 0).
280     mtx.nVersion = 2;
281
282     {
283         SCOPED_TRACE("BlockOverwinterRulesRejectSproutTx");
284         ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-active");
285     }
286
287     // Make it a Sapling transaction
288     mtx.fOverwintered = true;
289     mtx.nVersion = SAPLING_TX_VERSION;
290     mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
291
292     {
293         SCOPED_TRACE("BlockOverwinterRulesRejectSaplingTx");
294         ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-overwinter-tx-version-group-id");
295     }
296 }
297
298
299 // Test block evaluated under Sapling rules cannot contain non-Sapling transactions.
300 TEST_F(ContextualCheckBlockTest, BlockSaplingRulesRejectOtherTx) {
301     SelectParams(CBaseChainParams::REGTEST);
302     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, 1);
303     UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, 1);
304
305     CMutableTransaction mtx = GetFirstBlockCoinbaseTx();
306
307     // Set the version to Sprout+JoinSplit (but nJoinSplit will be 0).
308     mtx.nVersion = 2;
309
310     {
311         SCOPED_TRACE("BlockSaplingRulesRejectSproutTx");
312         ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-active");
313     }
314
315     // Make it an Overwinter transaction
316     mtx.fOverwintered = true;
317     mtx.nVersion = OVERWINTER_TX_VERSION;
318     mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
319
320     {
321         SCOPED_TRACE("BlockSaplingRulesRejectOverwinterTx");
322         ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-sapling-tx-version-group-id");
323     }
324 }
This page took 0.046878 seconds and 4 git commands to generate.