-
Notifications
You must be signed in to change notification settings - Fork 405
Expand file tree
/
Copy pathpegin_witness_tests.cpp
More file actions
152 lines (125 loc) · 8.11 KB
/
Copy pathpegin_witness_tests.cpp
File metadata and controls
152 lines (125 loc) · 8.11 KB
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
144
145
146
147
148
149
150
151
152
// Copyright (c) 2017-2017 Blockstream
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addresstype.h>
#include <clientversion.h>
#include <chainparams.h>
#include <checkqueue.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <validation.h> // For CheckTransaction
#include <pegins.h>
#include <policy/policy.h>
#include <script/script.h>
#include <script/script_error.h>
#include <util/strencodings.h>
#include <validation.h>
#include <streams.h>
#include <test/util/setup_common.h>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/test/unit_test.hpp>
std::vector<std::vector<unsigned char> > witness_stack = {
ParseHex("00ca9a3b00000000"),
ParseHex("ef4699c160d014d5ff79636d8a4cb990b9df4ebab649f144d19f5c495c585e47"),
ParseHex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f"),
ParseHex("00141eef6361cd1507a303834285d1521d6baf1b19ae"),
ParseHex("0200000001b399292c8100b8a1b66eb23896f799c1712390d560af0f70e81acd2d17a3b06e0000000049483045022100c3c749623486ea57ea93dfaf78d85590d78c7590a25768fe80f0ea4d6047419002202a0a00a90392b86c53c0fdda908c4591ba28040c16c25734c23b7df3c8b70acd01feffffff0228196bee000000001976a914470dd41542ee1a1bd75f1a838878648c8d65622488ac00ca9a3b0000000017a914cb60b1d7f76ba12b45a116c482c165a74c5d7e388765000000"),
ParseHex("000000205e3913a320cd2e3a2efa141e47419f54cb9e82320cf8dbc812fc19b9a1b2413a57f5e9fb4fa22de191454a241387f5d10cc794ee0fbf72ae2841baf3129a4eab8133025affff7f20000000000200000002f9d0be670007d38fceece999cb6144658a99c307ccc37f6d8f69129ed0f4545ff321df9790633bc33c67239c4174df8142ee616ee6a2e2788fe4820fe70e9bce0105")
};
std::vector<unsigned char> pegin_transaction = ParseHex("020000000101f321df9790633bc33c67239c4174df8142ee616ee6a2e2788fe4820fe70e9bce0100004000ffffffff0201ef4699c160d014d5ff79636d8a4cb990b9df4ebab649f144d19f5c495c585e4701000000003b9ab2e0001976a914809326f7628dc976fbe63806479a1b8dfcc8c4b988ac01ef4699c160d014d5ff79636d8a4cb990b9df4ebab649f144d19f5c495c585e47010000000000001720000000000000000002483045022100ae17064745d80650a6a5cbcbe15c8c45ba498d1c6f45a7c0f5f32d871b463fc60220799f2836471702c21f7cfe124651727b530ad41f7af4dc213c65f5030a2f6fc4012103a9d3c6c7c161a565a76113632fe13330cf2c0207ba79a76d1154cdc3cb94d940060800ca9a3b0000000020ef4699c160d014d5ff79636d8a4cb990b9df4ebab649f144d19f5c495c585e472006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f1600141eef6361cd1507a303834285d1521d6baf1b19aebe0200000001b399292c8100b8a1b66eb23896f799c1712390d560af0f70e81acd2d17a3b06e0000000049483045022100c3c749623486ea57ea93dfaf78d85590d78c7590a25768fe80f0ea4d6047419002202a0a00a90392b86c53c0fdda908c4591ba28040c16c25734c23b7df3c8b70acd01feffffff0228196bee000000001976a914470dd41542ee1a1bd75f1a838878648c8d65622488ac00ca9a3b0000000017a914cb60b1d7f76ba12b45a116c482c165a74c5d7e38876500000097000000205e3913a320cd2e3a2efa141e47419f54cb9e82320cf8dbc812fc19b9a1b2413a57f5e9fb4fa22de191454a241387f5d10cc794ee0fbf72ae2841baf3129a4eab8133025affff7f20000000000200000002f9d0be670007d38fceece999cb6144658a99c307ccc37f6d8f69129ed0f4545ff321df9790633bc33c67239c4174df8142ee616ee6a2e2788fe4820fe70e9bce010500000000");
COutPoint prevout(Txid::FromUint256(uint256S("ce9b0ee70f82e48f78e2a2e66e61ee4281df74419c23673cc33b639097df21f3")), 1);
const std::string fedpegscript_str = "512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae";
// Needed for easier parent PoW check, and setting fedpegscript
struct FedpegSetup : public BasicTestingSetup {
FedpegSetup() : BasicTestingSetup(ChainType::CUSTOM, {}, fedpegscript_str) {}
};
BOOST_FIXTURE_TEST_SUITE(pegin_witness_tests, FedpegSetup)
BOOST_AUTO_TEST_CASE(witness_valid)
{
CScriptWitness witness;
witness.stack = witness_stack;
std::string err;
std::vector<unsigned char> fedpegscript_bytes = ParseHex(fedpegscript_str);
CScript fedpegscript(fedpegscript_bytes.begin(), fedpegscript_bytes.end());
// Test sample was generated as "legacy" with p2sh-p2wsh fedpegscript
CScript fedpeg_program(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(fedpegscript)))));
std::vector<std::pair<CScript, CScript>> fedpegscripts;
// TODO test with additional scripts
fedpegscripts.emplace_back(fedpeg_program, fedpegscript);
bool valid = IsValidPeginWitness(witness, fedpegscripts, prevout, err, false);
BOOST_CHECK(err == "");
BOOST_CHECK(valid);
// Missing byte on each field to make claim ill-formatted
// This will break deserialization and other data-matching checks
for (unsigned int i = 0; i < witness.stack.size(); i++) {
witness.stack[i].pop_back();
BOOST_CHECK(!IsValidPeginWitness(witness, fedpegscripts, prevout, err, false));
witness.stack = witness_stack;
BOOST_CHECK(IsValidPeginWitness(witness, fedpegscripts, prevout, err, false));
}
// Test mismatched but valid nOut to proof
COutPoint fake_prevout = prevout;
fake_prevout.n = 0;
BOOST_CHECK(!IsValidPeginWitness(witness, fedpegscripts, fake_prevout, err, false));
// Test mismatched but valid txid
fake_prevout = prevout;
fake_prevout.hash = Txid::FromUint256(uint256S("2f103ee04a5649eecb932b4da4ca9977f53a12bbe04d9d1eb5ccc0f4a06334"));
BOOST_CHECK(!IsValidPeginWitness(witness, fedpegscripts, fake_prevout, err, false));
// Ensure that all witness stack sizes are handled
BOOST_CHECK(IsValidPeginWitness(witness, fedpegscripts, prevout, err, false));
for (unsigned int i = 0; i < witness.stack.size(); i++) {
witness.stack.pop_back();
BOOST_CHECK(!IsValidPeginWitness(witness, fedpegscripts, prevout, err, false));
}
witness.stack = witness_stack;
// Extra element causes failure
witness.stack.push_back(witness.stack.back());
BOOST_CHECK(!IsValidPeginWitness(witness, fedpegscripts, prevout, err, false));
witness.stack = witness_stack;
// Check validation of peg-in transaction's inputs and balance
DataStream ssTx(pegin_transaction);
CTransactionRef txRef;
try {
ssTx >> TX_WITH_WITNESS(txRef);
} catch (...) {
BOOST_CHECK(false);
return;
}
CTransaction tx(*txRef);
// Only one(valid) input witness should exist, and should match
BOOST_CHECK(tx.witness.vtxinwit.size() == 1);
BOOST_CHECK(tx.witness.vtxinwit[0].m_pegin_witness.stack == witness_stack);
BOOST_CHECK(tx.vin[0].m_is_pegin);
// Check that serialization doesn't cause issuance to become non-null
BOOST_CHECK(tx.vin[0].assetIssuance.IsNull());
BOOST_CHECK(IsValidPeginWitness(tx.witness.vtxinwit[0].m_pegin_witness, fedpegscripts, prevout, err, false));
CAmountMap fee_map;
std::set<std::pair<uint256, COutPoint>> setPeginsSpent;
TxValidationState state;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
// Get the latest block index to look up fedpegscripts
// For these tests, should be genesis-block-hardcoded consensus.fedpegscript
BOOST_CHECK(Consensus::CheckTxInputs(tx, state, coins, 0, fee_map, setPeginsSpent, nullptr, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.size() == 1);
setPeginsSpent.clear();
// Strip pegin_witness
CMutableTransaction mtxn(tx);
mtxn.witness.vtxinwit[0].m_pegin_witness.SetNull();
CTransaction tx2(mtxn);
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, coins, 0, fee_map, setPeginsSpent, nullptr, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.empty());
// Invalidate peg-in (and spending) authorization by pegin marker.
// This only checks for peg-in authorization, with the only input marked
// as m_is_pegin
CMutableTransaction mtxn2(tx);
mtxn2.vin[0].m_is_pegin = false;
CTransaction tx3(mtxn2);
BOOST_CHECK(!Consensus::CheckTxInputs(tx3, state, coins, 0, fee_map, setPeginsSpent, nullptr, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.empty());
// TODO Test mixed pegin/non-pegin input case
// TODO Test spending authorization in conjunction with valid witness program in pegin auth
}
BOOST_AUTO_TEST_SUITE_END()