]>
Commit | Line | Data |
---|---|---|
0bb3d40f JG |
1 | // Copyright (c) 2016 The Zcash developers |
2 | // Distributed under the MIT software license, see the accompanying | |
bc909a7a | 3 | // file COPYING or https://www.opensource.org/licenses/mit-license.php . |
0bb3d40f JG |
4 | |
5 | #include "utiltest.h" | |
6 | ||
be126699 | 7 | #include "consensus/upgrades.h" |
89e75c8c | 8 | #include "transaction_builder.h" |
be126699 | 9 | |
a6bbb26e JG |
10 | #include <array> |
11 | ||
c3e2de59 | 12 | // Sprout |
c1009374 | 13 | CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, |
8f410367 EOW |
14 | const libzcash::SproutSpendingKey& sk, |
15 | CAmount value, | |
16 | bool randomInputs, | |
17 | int32_t version /* = 2 */) { | |
0bb3d40f | 18 | CMutableTransaction mtx; |
3a5f66c8 | 19 | mtx.nVersion = version; |
0bb3d40f JG |
20 | mtx.vin.resize(2); |
21 | if (randomInputs) { | |
22 | mtx.vin[0].prevout.hash = GetRandHash(); | |
23 | mtx.vin[1].prevout.hash = GetRandHash(); | |
24 | } else { | |
25 | mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); | |
26 | mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); | |
27 | } | |
28 | mtx.vin[0].prevout.n = 0; | |
29 | mtx.vin[1].prevout.n = 0; | |
30 | ||
31 | // Generate an ephemeral keypair. | |
32 | uint256 joinSplitPubKey; | |
33 | unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; | |
34 | crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); | |
35 | mtx.joinSplitPubKey = joinSplitPubKey; | |
36 | ||
a6bbb26e | 37 | std::array<libzcash::JSInput, 2> inputs = { |
0bb3d40f JG |
38 | libzcash::JSInput(), // dummy input |
39 | libzcash::JSInput() // dummy input | |
40 | }; | |
41 | ||
a6bbb26e | 42 | std::array<libzcash::JSOutput, 2> outputs = { |
0bb3d40f JG |
43 | libzcash::JSOutput(sk.address(), value), |
44 | libzcash::JSOutput(sk.address(), value) | |
45 | }; | |
46 | ||
0bb3d40f JG |
47 | // Prepare JoinSplits |
48 | uint256 rt; | |
b7a6c321 | 49 | JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, |
0bb3d40f | 50 | inputs, outputs, 2*value, 0, false}; |
f57f76d7 | 51 | mtx.vJoinSplit.push_back(jsdesc); |
0bb3d40f | 52 | |
3e5cc59c EOW |
53 | // Consider: The following is a bit misleading (given the name of this function) |
54 | // and should perhaps be changed, but currently a few tests in test_wallet.cpp | |
55 | // depend on this happening. | |
3a5f66c8 EOW |
56 | if (version >= 4) { |
57 | // Shielded Output | |
58 | OutputDescription od; | |
59 | mtx.vShieldedOutput.push_back(od); | |
60 | } | |
e6b0a8b9 | 61 | |
0bb3d40f | 62 | // Empty output script. |
be126699 | 63 | uint32_t consensusBranchId = SPROUT_BRANCH_ID; |
0bb3d40f JG |
64 | CScript scriptCode; |
65 | CTransaction signTx(mtx); | |
be126699 | 66 | uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); |
0bb3d40f JG |
67 | |
68 | // Add the signature | |
69 | assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, | |
a513ea90 JG |
70 | dataToBeSigned.begin(), 32, |
71 | joinSplitPrivKey | |
72 | ) == 0); | |
0bb3d40f | 73 | |
c1009374 SB |
74 | return mtx; |
75 | } | |
76 | ||
77 | CWalletTx GetValidSproutReceive(ZCJoinSplit& params, | |
78 | const libzcash::SproutSpendingKey& sk, | |
79 | CAmount value, | |
80 | bool randomInputs, | |
81 | int32_t version /* = 2 */) | |
82 | { | |
83 | CMutableTransaction mtx = GetValidSproutReceiveTransaction( | |
84 | params, sk, value, randomInputs, version | |
85 | ); | |
86 | CTransaction tx {mtx}; | |
87 | CWalletTx wtx {NULL, tx}; | |
88 | return wtx; | |
89 | } | |
90 | ||
91 | CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, | |
92 | const libzcash::SproutSpendingKey& sk, | |
93 | CAmount value, | |
94 | bool randomInputs, | |
95 | int32_t version /* = 2 */) | |
96 | { | |
97 | CMutableTransaction mtx = GetValidSproutReceiveTransaction( | |
98 | params, sk, value, randomInputs, version | |
99 | ); | |
f57f76d7 DA |
100 | mtx.vJoinSplit[0].commitments[0] = uint256(); |
101 | mtx.vJoinSplit[0].commitments[1] = uint256(); | |
0bb3d40f JG |
102 | CTransaction tx {mtx}; |
103 | CWalletTx wtx {NULL, tx}; | |
104 | return wtx; | |
105 | } | |
106 | ||
8f410367 EOW |
107 | libzcash::SproutNote GetSproutNote(ZCJoinSplit& params, |
108 | const libzcash::SproutSpendingKey& sk, | |
109 | const CTransaction& tx, size_t js, size_t n) { | |
642a1caf | 110 | ZCNoteDecryption decryptor {sk.receiving_key()}; |
f57f76d7 | 111 | auto hSig = tx.vJoinSplit[js].h_sig(params, tx.joinSplitPubKey); |
5020a936 | 112 | auto note_pt = libzcash::SproutNotePlaintext::decrypt( |
0bb3d40f | 113 | decryptor, |
f57f76d7 DA |
114 | tx.vJoinSplit[js].ciphertexts[n], |
115 | tx.vJoinSplit[js].ephemeralKey, | |
0bb3d40f JG |
116 | hSig, |
117 | (unsigned char) n); | |
118 | return note_pt.note(sk.address()); | |
119 | } | |
120 | ||
8f410367 EOW |
121 | CWalletTx GetValidSproutSpend(ZCJoinSplit& params, |
122 | const libzcash::SproutSpendingKey& sk, | |
123 | const libzcash::SproutNote& note, | |
124 | CAmount value) { | |
0bb3d40f JG |
125 | CMutableTransaction mtx; |
126 | mtx.vout.resize(2); | |
127 | mtx.vout[0].nValue = value; | |
128 | mtx.vout[1].nValue = 0; | |
129 | ||
130 | // Generate an ephemeral keypair. | |
131 | uint256 joinSplitPubKey; | |
132 | unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; | |
133 | crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); | |
134 | mtx.joinSplitPubKey = joinSplitPubKey; | |
135 | ||
136 | // Fake tree for the unused witness | |
4fc309f0 | 137 | SproutMerkleTree tree; |
0bb3d40f JG |
138 | |
139 | libzcash::JSOutput dummyout; | |
140 | libzcash::JSInput dummyin; | |
141 | ||
142 | { | |
5d99e3e9 | 143 | if (note.value() > value) { |
e5eab182 JG |
144 | libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); |
145 | libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); | |
5d99e3e9 S |
146 | dummyout = libzcash::JSOutput(dummyaddr, note.value() - value); |
147 | } else if (note.value() < value) { | |
e5eab182 JG |
148 | libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); |
149 | libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); | |
5d99e3e9 | 150 | libzcash::SproutNote dummynote(dummyaddr.a_pk, (value - note.value()), uint256(), uint256()); |
0bb3d40f JG |
151 | tree.append(dummynote.cm()); |
152 | dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey); | |
153 | } | |
154 | } | |
155 | ||
156 | tree.append(note.cm()); | |
157 | ||
a6bbb26e | 158 | std::array<libzcash::JSInput, 2> inputs = { |
0bb3d40f JG |
159 | libzcash::JSInput(tree.witness(), note, sk), |
160 | dummyin | |
161 | }; | |
162 | ||
a6bbb26e | 163 | std::array<libzcash::JSOutput, 2> outputs = { |
0bb3d40f JG |
164 | dummyout, // dummy output |
165 | libzcash::JSOutput() // dummy output | |
166 | }; | |
167 | ||
0bb3d40f JG |
168 | // Prepare JoinSplits |
169 | uint256 rt = tree.root(); | |
b7a6c321 | 170 | JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, |
0bb3d40f | 171 | inputs, outputs, 0, value, false}; |
f57f76d7 | 172 | mtx.vJoinSplit.push_back(jsdesc); |
0bb3d40f JG |
173 | |
174 | // Empty output script. | |
be126699 | 175 | uint32_t consensusBranchId = SPROUT_BRANCH_ID; |
0bb3d40f JG |
176 | CScript scriptCode; |
177 | CTransaction signTx(mtx); | |
be126699 | 178 | uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); |
0bb3d40f JG |
179 | |
180 | // Add the signature | |
181 | assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, | |
a513ea90 JG |
182 | dataToBeSigned.begin(), 32, |
183 | joinSplitPrivKey | |
184 | ) == 0); | |
0bb3d40f JG |
185 | CTransaction tx {mtx}; |
186 | CWalletTx wtx {NULL, tx}; | |
187 | return wtx; | |
188 | } | |
89e75c8c | 189 | |
c3e2de59 | 190 | // Sapling |
8a1d1930 | 191 | const Consensus::Params& RegtestActivateSapling() { |
c3e2de59 EOW |
192 | SelectParams(CBaseChainParams::REGTEST); |
193 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); | |
194 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); | |
195 | return Params().GetConsensus(); | |
196 | } | |
197 | ||
8a1d1930 | 198 | void RegtestDeactivateSapling() { |
c3e2de59 EOW |
199 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); |
200 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); | |
c3e2de59 EOW |
201 | } |
202 | ||
1188c9ad | 203 | const Consensus::Params& RegtestActivateBlossom(bool updatePow, int blossomActivationHeight) { |
ff0820df EOW |
204 | SelectParams(CBaseChainParams::REGTEST); |
205 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); | |
206 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); | |
1188c9ad | 207 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, blossomActivationHeight); |
ff0820df EOW |
208 | if (updatePow) { |
209 | UpdateRegtestPow(32, 16, uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); | |
210 | } | |
211 | return Params().GetConsensus(); | |
212 | } | |
213 | ||
1188c9ad | 214 | void RegtestDeactivateBlossom() { |
ff0820df EOW |
215 | UpdateRegtestPow(0, 0, uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f")); |
216 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); | |
217 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); | |
218 | UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); | |
219 | SelectParams(CBaseChainParams::MAIN); | |
220 | } | |
221 | ||
222 | ||
8a1d1930 | 223 | libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey() { |
1534671f EOW |
224 | std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32); |
225 | HDSeed seed(rawSeed); | |
226 | return libzcash::SaplingExtendedSpendingKey::Master(seed); | |
227 | } | |
228 | ||
8a1d1930 | 229 | CKey AddTestCKeyToKeyStore(CBasicKeyStore& keyStore) { |
275bd8f6 EOW |
230 | CKey tsk = DecodeSecret(T_SECRET_REGTEST); |
231 | keyStore.AddKey(tsk); | |
232 | return tsk; | |
233 | } | |
234 | ||
9eadcb3e EOW |
235 | TestSaplingNote GetTestSaplingNote(const libzcash::SaplingPaymentAddress& pa, CAmount value) { |
236 | // Generate dummy Sapling note | |
237 | libzcash::SaplingNote note(pa, value); | |
238 | uint256 cm = note.cm().get(); | |
239 | SaplingMerkleTree tree; | |
240 | tree.append(cm); | |
241 | return { note, tree }; | |
242 | } | |
243 | ||
3e5cc59c EOW |
244 | CWalletTx GetValidSaplingReceive(const Consensus::Params& consensusParams, |
245 | CBasicKeyStore& keyStore, | |
246 | const libzcash::SaplingExtendedSpendingKey &sk, | |
247 | CAmount value) { | |
248 | // From taddr | |
8a1d1930 | 249 | CKey tsk = AddTestCKeyToKeyStore(keyStore); |
3e5cc59c EOW |
250 | auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID()); |
251 | // To zaddr | |
252 | auto fvk = sk.expsk.full_viewing_key(); | |
9eadcb3e | 253 | auto pa = sk.DefaultAddress(); |
89e75c8c | 254 | |
8865f4b6 | 255 | auto builder = TransactionBuilder(consensusParams, 1, &keyStore); |
89e75c8c | 256 | builder.SetFee(0); |
3e5cc59c | 257 | builder.AddTransparentInput(COutPoint(), scriptPubKey, value); |
9eadcb3e | 258 | builder.AddSaplingOutput(fvk.ovk, pa, value, {}); |
89e75c8c | 259 | |
9eadcb3e | 260 | CTransaction tx = builder.Build().GetTxOrThrow(); |
89e75c8c EOW |
261 | CWalletTx wtx {NULL, tx}; |
262 | return wtx; | |
263 | } |