/// <summary> /// Generate atomic swap payment script to P2PKH <paramref name="bobAddress"/> with multisig refund /// </summary> /// <param name="aliceRefundPubKey">Alice public key for refund</param> /// <param name="bobRefundPubKey">Bob public key for refund</param> /// <param name="bobAddress">Bob target address</param> /// <param name="secretHash">Secret hash</param> /// <param name="expectedNetwork">Expected network necessary to get the correct hash address</param> /// <returns>Atomic swap payment script</returns> public static Script GenerateP2PkhSwapPayment( byte[] aliceRefundPubKey, byte[] bobRefundPubKey, string bobAddress, byte[] secretHash, Network expectedNetwork = null) { // OP_IF // 2 <aliceRefundPubKey> <bobRefundPubKey> 2 CHECKMULTISIG // OP_ELSE // OP_HASH256 <secretHash> OP_EQUALVERIFY OP_DUP OP_HASH160 <bobAddress> OP_EQUALVERIFY OP_CHECKSIG // OP_ENDIF if (aliceRefundPubKey == null) { throw new ArgumentNullException(nameof(aliceRefundPubKey)); } if (bobRefundPubKey == null) { throw new ArgumentNullException(nameof(bobRefundPubKey)); } if (bobAddress == null) { throw new ArgumentNullException(nameof(bobAddress)); } if (secretHash == null) { throw new ArgumentNullException(nameof(secretHash)); } var bobAddressHash = new BitcoinPubKeyAddress(bobAddress, expectedNetwork).Hash; return(new Script(new List <Op> { OpcodeType.OP_IF, Op.GetPushOp(2), Op.GetPushOp(aliceRefundPubKey), Op.GetPushOp(bobRefundPubKey), Op.GetPushOp(2), OpcodeType.OP_CHECKMULTISIG, OpcodeType.OP_ELSE, OpcodeType.OP_HASH256, Op.GetPushOp(secretHash), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_DUP, OpcodeType.OP_HASH160, Op.GetPushOp(bobAddressHash.ToBytes()), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG, OpcodeType.OP_ENDIF })); }
/// <summary> /// Generate atomic swap payment script to P2PKH <paramref name="bobAddress"/> with HTLC refund and secret size check /// </summary> /// <param name="aliceRefundAddress">Alice refund address</param> /// <param name="bobAddress">Bob target address</param> /// <param name="lockTimeStamp">Lock TimeStamp for refund</param> /// <param name="secretHash">Secret hash</param> /// <param name="secretSize">Secret size in bytes</param> /// <param name="expectedNetwork">Expected network necessary to get the correct hash addresses</param> /// <returns>Atomic swap payment script</returns> public static Script GenerateHtlcP2PkhSwapPayment( string aliceRefundAddress, string bobAddress, long lockTimeStamp, byte[] secretHash, int secretSize, Network expectedNetwork = null) { // OP_IF // <lockTimeStamp> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <aliceRefundAddress> OP_EQUALVERIFY CHECKSIG // OP_ELSE // OP_SIZE <secretSize> OP_EQUALVERIFY OP_HASH256 <secretHash> OP_EQUALVERIFY OP_DUP OP_HASH160 <bobAddress> OP_EQUALVERIFY OP_CHECKSIG // OP_ENDIF if (aliceRefundAddress == null) { throw new ArgumentNullException(nameof(aliceRefundAddress)); } if (bobAddress == null) { throw new ArgumentNullException(nameof(bobAddress)); } if (secretHash == null) { throw new ArgumentNullException(nameof(secretHash)); } if (secretSize <= 0) { throw new ArgumentException("Invalid Secret Size", nameof(secretSize)); } var aliceRefundAddressHash = new BitcoinPubKeyAddress(aliceRefundAddress, expectedNetwork).Hash; var bobAddressHash = new BitcoinPubKeyAddress(bobAddress, expectedNetwork).Hash; return(new Script(new List <Op> { // if refund OpcodeType.OP_IF, Op.GetPushOp(lockTimeStamp), OpcodeType.OP_CHECKLOCKTIMEVERIFY, OpcodeType.OP_DROP, OpcodeType.OP_DUP, OpcodeType.OP_HASH160, Op.GetPushOp(aliceRefundAddressHash.ToBytes()), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG, // else redeem OpcodeType.OP_ELSE, OpcodeType.OP_SIZE, Op.GetPushOp(secretSize), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_HASH256, Op.GetPushOp(secretHash), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_DUP, OpcodeType.OP_HASH160, Op.GetPushOp(bobAddressHash.ToBytes()), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG, OpcodeType.OP_ENDIF })); }