@@ -199,14 +199,87 @@ BOOST_AUTO_TEST_CASE(coldstake_lof_script)
199199 BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
200200}
201201
202+ BOOST_AUTO_TEST_CASE (coldstake_script)
203+ {
204+ SelectParams (CBaseChainParams::REGTEST);
205+ CScript scriptP2CS;
206+ CKey stakerKey, ownerKey;
207+
208+ // create unsigned coinstake transaction
209+ CMutableTransaction good_tx = CreateNewColdStakeTx (scriptP2CS, stakerKey, ownerKey, false );
210+
211+ // sign the input with the staker key
212+ SignColdStake (good_tx, 0 , scriptP2CS, stakerKey, true );
213+
214+ // check the signature and script
215+ ScriptError err = SCRIPT_ERR_OK;
216+ CMutableTransaction tx (good_tx);
217+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
218+
219+ // pay less than expected
220+ tx.vout [1 ].nValue -= 3 * COIN;
221+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
222+ BOOST_CHECK (!CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
223+ BOOST_CHECK_MESSAGE (err == SCRIPT_ERR_CHECKCOLDSTAKEVERIFY, ScriptErrorString (err));
224+
225+ // Add another p2cs out
226+ tx.vout .emplace_back (3 * COIN, scriptP2CS);
227+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
228+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
229+
230+ const CKey& dummyKey = DecodeSecret (" 91t7cwPGevo885Uccg87nVjzUxKhXta9JprHM3R21PQkBFMFg2i" );
231+ const CKeyID& dummyKeyID = dummyKey.GetPubKey ().GetID ();
232+ const CScript& dummyP2PKH = GetDummyP2PKH (dummyKeyID);
233+
234+ // Add a dummy P2PKH out at the end
235+ tx.vout .emplace_back (3 * COIN, dummyP2PKH);
236+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
237+ BOOST_CHECK (!CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
238+ BOOST_CHECK_MESSAGE (err == SCRIPT_ERR_CHECKCOLDSTAKEVERIFY, ScriptErrorString (err));
239+ // -- but the owner can
240+ SignColdStake (tx, 0 , scriptP2CS, ownerKey, false );
241+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
242+
243+ // Add a dummy P2PKH out at the beginning
244+ tx = good_tx;
245+ tx.vout [1 ] = CTxOut (3 * COIN, dummyP2PKH);
246+ tx.vout .emplace_back (3 * COIN, scriptP2CS);
247+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
248+ BOOST_CHECK (!CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
249+ BOOST_CHECK_MESSAGE (err == SCRIPT_ERR_CHECKCOLDSTAKEVERIFY, ScriptErrorString (err));
250+ // -- but the owner can
251+ SignColdStake (tx, 0 , scriptP2CS, ownerKey, false );
252+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
253+
254+ // Replace with new p2cs
255+ tx = good_tx;
256+ tx.vout [1 ].scriptPubKey = GetDummyP2CS (dummyKeyID);
257+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
258+ BOOST_CHECK (!CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
259+ BOOST_CHECK_MESSAGE (err == SCRIPT_ERR_CHECKCOLDSTAKEVERIFY, ScriptErrorString (err));
260+ // -- but the owner can
261+ SignColdStake (tx, 0 , scriptP2CS, ownerKey, false );
262+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
263+
264+ // Replace with single dummy out
265+ tx = good_tx;
266+ tx.vout [1 ] = CTxOut (COIN, dummyP2PKH);
267+ SignColdStake (tx, 0 , scriptP2CS, stakerKey, true );
268+ BOOST_CHECK (!CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
269+ BOOST_CHECK_MESSAGE (err == SCRIPT_ERR_CHECKCOLDSTAKEVERIFY, ScriptErrorString (err));
270+ // -- but the owner can
271+ SignColdStake (tx, 0 , scriptP2CS, ownerKey, false );
272+ BOOST_CHECK (CheckP2CSScript (tx.vin [0 ].scriptSig , scriptP2CS, tx, err));
273+ }
274+
202275// Check that it's not possible to "fake" a P2CS script for the owner by splitting the locking
203276// and unlocking parts. This particular script can be spent by any key, with a
204277// unlocking script composed like: <sig> <pk> <DUP> <HASH160> <pkh>
205278static CScript GetFakeLockingScript (const CKeyID staker, const CKeyID& owner)
206279{
207280 CScript script;
208281 script << opcodetype (0x2F ) << opcodetype (0x01 ) << OP_ROT <<
209- OP_IF << OP_CHECKCOLDSTAKEVERIFY_LOF << ToByteVector (staker) <<
282+ OP_IF << OP_CHECKCOLDSTAKEVERIFY << ToByteVector (staker) <<
210283 OP_ELSE << ToByteVector (owner) << OP_DROP <<
211284 OP_EQUALVERIFY << OP_CHECKSIG;
212285
0 commit comments