Open rushmi0 opened 7 months ago
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
}