Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I use Redeem Script Hex for create PSBT to unlock P2SH? #125

Open
rushmi0 opened this issue Mar 12, 2024 · 1 comment
Open

How do I use Redeem Script Hex for create PSBT to unlock P2SH? #125

rushmi0 opened this issue Mar 12, 2024 · 1 comment

Comments

@rushmi0
Copy link

rushmi0 commented Mar 12, 2024

val xpub = DeterministicWallet.ExtendedPublicKey.decode(
            "xpub6CEAyB6zF8bLzi1tNqg4zEfWSBBXtieA4hm3EstWsgSJCgMQS1UrfAFAZHYH1o7tfgFuNWzJhsDHg1EhoF4G5gzXUpQNkt1RzSTyFeAUv4S"
        ).second
        println(xpub)

        // สร้างธุรกรรม
        val unsignedTx = Transaction(
            version = 2,
            txIn = listOf(
                TxIn(
                    OutPoint(
                        TxId("c95039b1ce6152a20ecab1759e924c15e25f4d980673bd64c07a43d2fb501acb"),
                        0
                    ),
                    signatureScript = listOf(),
                    sequence = 0xfdffffff
                )
            ),
            txOut = listOf(
                TxOut(
                    12_000.toSatoshi(),
                    ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")
                )
            ),
            lockTime = 1423787
        )
        val psbt = Psbt(unsignedTx)

        // ดึงข้อมูล public key, fingerprint, และ key path จาก xpub
        val publicKey = xpub.publicKey
        val fingerprint = xpub.parent
        val keyPath = xpub.path

        // สร้าง mapping ของ public key และ key path
        val pubkeyData = mapOf(
            publicKey to KeyPathWithMaster(fingerprint, keyPath)
        )

        // ระบุ redeem script
        val redeemScript = listOf(

        )

        // อัปเดต PSBT : https://github.com/ACINQ/bitcoin-kmp/blob/master/src%2FcommonMain%2Fkotlin%2Ffr%2Facinq%2Fbitcoin%2Fpsbt%2FPsbt.kt#L172-L172
        val firstPSBT = psbt.updateNonWitnessInput(
            inputTx = unsignedTx,
            outputIndex = 0,
            redeemScript = redeemScript,
            sighashType = 1,
            derivationPaths = pubkeyData
        )
@rushmi0
Copy link
Author

rushmi0 commented Mar 12, 2024

import fr.acinq.bitcoin.OP_CHECKLOCKTIMEVERIFY
import fr.acinq.bitcoin.OP_CHECKSIG
import fr.acinq.bitcoin.OP_DROP
import fr.acinq.bitcoin.OP_PUSHDATA
import win.notoshi.genesec.utils.ShiftTo.ByteArrayToHex
import win.notoshi.genesec.utils.ShiftTo.HexToByteArray
import win.notoshi.genesec.utils.ShiftTo.toByteArray
import java.nio.ByteBuffer
import java.nio.ByteOrder

class ScriptBuilder {

    // * https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
    fun TimeLock(blockNumber: Int, publicKey: ByteArray): String {
        if (blockNumber < 0) {
            throw IllegalArgumentException("Block number must be non-negative")
        }

        // กำหนดค่าเริ่มต้นสำหรับ blockNumber ในรูปแบบ LITTLE ENDIAN 8 Bytes
        val LITTLE_ENDIAN: ByteBuffer =
            ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putInt(blockNumber)

        // ตรวจสอบและกำหนดค่าให้กับ nLockTime โดยตัด byte 0x00 ที่อยู่ด้านท้ายออก
        var nLockTime: ByteArray = LITTLE_ENDIAN.array()
        while (nLockTime.isNotEmpty() && nLockTime.last() == 0x00.toByte()) {
            nLockTime = nLockTime.dropLast(1).toByteArray()
        }

        /*
        * องค์ประกอบสคริปต์
        *
        *   [ < ขนาดหมายเลข Block, หมายเลข Block รูปแบบ LITTLE ENDIAN > ]
        * OP_CHECKLOCKTIMEVERIFY
        * OP_DROP
        *   [ < ขนาดของ Public key >, < Public key > ]
        * OP_CHECKSIG
        */
        val stack = listOf(
            OP_PUSHDATA(nLockTime).opCode.toByteArray(),
            nLockTime,
            OP_CHECKLOCKTIMEVERIFY.code.toByteArray(),
            OP_DROP.code.toByteArray(),
            OP_PUSHDATA(publicKey).opCode.toByteArray(),
            publicKey,
            OP_CHECKSIG.code.toByteArray()
        )

        return buildString {
            stack.forEach { element ->
                append(element.ByteArrayToHex())
            }
        }
    }


}

fun main() {
    val script = ScriptBuilder()
    val publicKey = "02a1d6c523ea4baa26127a55eee14adcee1b1419407e317654682c0759f431ecaf"
    val redeemScript = script.TimeLock(1423787, publicKey.HexToByteArray())
    println(redeemScript)
    // 03abb915b1752102a1d6c523ea4baa26127a55eee14adcee1b1419407e317654682c0759f431ecafac
    // 3JFVsdsib5mrvpZmid1jdTPa2KR1fXXgpz
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant