@@ -70,20 +70,23 @@ bool GetAmountFromParentChainPegin(CAmount& amount, const CTransaction& txBTC, u
7070}
7171
7272// Takes federation redeem script and adds HMAC_SHA256(pubkey, scriptPubKey) as a tweak to each pubkey
73- CScript calculate_contract (const CScript& federationRedeemScript , const CScript& scriptPubKey) {
73+ CScript calculate_contract (const CScript& federation_script , const CScript& scriptPubKey) {
7474 CScript scriptDestination;
75- txnouttype type;
7675 std::vector<std::vector<unsigned char > > solutions;
77- // Sanity check fedRedeemScript
78- if (!Solver (federationRedeemScript, type, solutions) || (type != TX_MULTISIG && type != TX_TRUE)) {
76+ unsigned int required;
77+ std::vector<std::vector<unsigned char >> keys;
78+ // Sanity check federation_script only to match 3 templates
79+ if (federation_script != CScript () << OP_TRUE &&
80+ !MatchMultisig (federation_script, required, keys) &&
81+ !MatchLiquidWatchman (federation_script)) {
7982 assert (false );
8083 }
8184
8285 {
83- CScript::const_iterator sdpc = federationRedeemScript .begin ();
86+ CScript::const_iterator sdpc = federation_script .begin ();
8487 std::vector<unsigned char > vch;
8588 opcodetype opcodeTmp;
86- while (federationRedeemScript .GetOp (sdpc, opcodeTmp, vch))
89+ while (federation_script .GetOp (sdpc, opcodeTmp, vch))
8790 {
8891 size_t pub_len = 33 ;
8992 if (vch.size () == pub_len)
@@ -352,3 +355,75 @@ CTxOut GetPeginOutputFromWitness(const CScriptWitness& pegin_witness) {
352355 // return CTxOut(CAsset(pegin_witness.stack[1]), value, CScript(pegin_witness.stack[3].begin(), pegin_witness.stack[3].end()));
353356 return CTxOut (value, CScript (pegin_witness.stack [3 ].begin (), pegin_witness.stack [3 ].end ()));
354357}
358+
359+ bool MatchLiquidWatchman (const CScript& script)
360+ {
361+ CScript::const_iterator it = script.begin ();
362+ std::vector<unsigned char > data;
363+ opcodetype opcode;
364+
365+ // Stack depth check for branch choice
366+ if (!script.GetOp (it, opcode, data) || opcode != OP_DEPTH) {
367+ return false ;
368+ }
369+ // Take in value, then check equality
370+ if (!script.GetOp (it, opcode, data) ||
371+ !script.GetOp (it, opcode, data) ||
372+ opcode != OP_EQUAL) {
373+ return false ;
374+ }
375+ // IF EQUAL
376+ if (!script.GetOp (it, opcode, data) || opcode != OP_IF) {
377+ return false ;
378+ }
379+ // Take in value k, make sure minimally encoded number from 1 to 16
380+ if (!script.GetOp (it, opcode, data) ||
381+ opcode > OP_16 ||
382+ (opcode < OP_1NEGATE && !CheckMinimalPush (data, opcode))) {
383+ return false ;
384+ }
385+ opcodetype opcode2 = opcode;
386+ std::vector<unsigned char > num = data;
387+ // Iterate through multisig stuff until ELSE is hit
388+ while (opcode != OP_ELSE) {
389+ if (!script.GetOp (it, opcode, data)) {
390+ return false ;
391+ }
392+ }
393+ // Take minimally-encoded CSV push number k'
394+ if (!script.GetOp (it, opcode, data) ||
395+ opcode > OP_16 || (opcode < OP_1NEGATE && !CheckMinimalPush (data, opcode))) {
396+ return false ;
397+ }
398+ // CSV
399+ if (!script.GetOp (it, opcode, data) || opcode != OP_CHECKSEQUENCEVERIFY) {
400+ return false ;
401+ }
402+ // Drop the CSV number
403+ if (!script.GetOp (it, opcode, data) || opcode != OP_DROP) {
404+ return false ;
405+ }
406+ // Take the minimally-encoded n of k-of-n multisig arg
407+ if (!script.GetOp (it, opcode, data) ||
408+ opcode > OP_16 || (opcode < OP_1NEGATE && !CheckMinimalPush (data, opcode)) ) {
409+ return false ;
410+ }
411+
412+ // The two multisig k-numbers must not match, otherwise ELSE branch can not be reached
413+ if (opcode == opcode2 && num == data) {
414+ return false ;
415+ }
416+
417+ // Find the ENDIF
418+ while (opcode != OP_ENDIF) {
419+ if (!script.GetOp (it, opcode, data)) {
420+ return false ;
421+ }
422+ }
423+ // CHECKMULTISIG
424+ if (!script.GetOp (it, opcode, data) || opcode != OP_CHECKMULTISIG) {
425+ return false ;
426+ }
427+ // No more pushes
428+ return (it + 1 == script.end ());
429+ }
0 commit comments