Last active
November 9, 2022 22:27
-
-
Save baryon/cb673e9c1d68a0f35011720b24b2b16f to your computer and use it in GitHub Desktop.
Create Bitcoin Script from any unlockTx or lockingTx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const bsv = require( 'bsv' ) | |
const WhatsOnChain = require( 'whatsonchain' ) | |
const _ = require( 'lodash' ) | |
async function createScriptFromTx ( woc, prevTxid, outputIndex, scriptName, unlockParams = '', debugParams = '', txContext = {} ) { | |
//fetch transaction from prevTxid | |
const prevTxHex = await woc.getRawTxData( prevTxid ) | |
const prevTx = new bsv.Transaction(prevTxHex) | |
//analyse locking script | |
const output = prevTx.outputs[ outputIndex ] | |
const asm = output.script.toASM() | |
const fixedAsm = _.map( asm.split( ' ' ), ( item ) => { | |
switch ( item ) { | |
case '0': | |
return 'OP_0' | |
case '-1': | |
return 'OP_1NEGATE' | |
default: | |
return item | |
} | |
} ).join( '\n' ) | |
//create scrypt file | |
const contract = ` | |
contract ${scriptName} { | |
public function unlock(${unlockParams}) { | |
asm { | |
${fixedAsm} | |
} | |
} | |
} | |
` | |
console.log( `${scriptName}.scrypt ` + '>'.repeat( 10 ) ) | |
console.log( contract ) | |
console.log( '<'.repeat( 10 ) + ` ${scriptName}.scrypt `, '\n' ) | |
//debug's setting, paste to .vscode/launch.json | |
const debugSetting = ` | |
{ | |
"type": "scrypt", | |
"request": "launch", | |
"name": "Debug ${scriptName}", | |
"program": "\${workspaceFolder}/contracts/${scriptName}.scrypt", | |
"constructorArgs": [ | |
], | |
"pubFunc": "unlock", | |
"pubFuncArgs": [ | |
${debugParams} | |
], | |
"txContext": { | |
"hex": "${txContext.hex}", | |
"inputIndex": ${txContext.inputIndex}, | |
"inputSatoshis": ${prevTx.outputs[ outputIndex ].satoshis} | |
} | |
} | |
` | |
console.log( `launche.json ` + '>'.repeat( 10 ) ) | |
console.log( debugSetting ) | |
console.log( '<'.repeat( 10 ) + ` launche.json` ) | |
return { contract, debugSetting } | |
} | |
async function createScriptFromUnlockTx ( woc, unlockTxId, inputIndex, scriptName ) { | |
//fetch transaction from unlocking tx | |
const unlockTxHex = await woc.getRawTxData( unlockTxId ) | |
const unlockTx = new bsv.Transaction(unlockTxHex) | |
const input = unlockTx.inputs[ inputIndex ] | |
const prevTxid = input.prevTxId.toString('hex') | |
const outputIndex = input.outputIndex | |
let unlockParams, debugParams | |
const unlockASM = input.script.toASM() | |
const asms = _.map( unlockASM.split( ' ' ), ( item ) => { | |
switch ( item ) { | |
case '0': | |
return '00' | |
case '-1', 'OP_1NEGATE': | |
return '81' | |
default: | |
const m = item.match(/^OP_(\d+)$/) | |
if(m) { | |
const v = parseInt(m[1]).toString(16) | |
return v.length < 2 ? '0' + v : v | |
} | |
return item | |
} | |
} ) | |
unlockParams = 'bytes p0' | |
debugParams = `"b'${asms[ 0 ]}'"` | |
for ( let i = 1; i < asms.length; i++ ) { | |
unlockParams += `, bytes p${i}` | |
debugParams += `, "b'${asms[ i ]}'"` | |
} | |
const txContext = { | |
hex: unlockTx.uncheckedSerialize(), | |
inputIndex | |
} | |
return createScriptFromTx(woc, prevTxid, outputIndex, scriptName, unlockParams, debugParams, txContext) | |
} | |
//network: testnet/livenet | |
const woc = new WhatsOnChain( 'livenet' ) | |
//unlocking tx | |
//const unlockTxId = '20adad8bd4cc694cfed4ccadff911433601e55b0f8779e839bc6579cb8d234f9' | |
const unlockTxId = 'fc5e29ae7aafeb774cc1f94c951381bff358af64e8ad33a8a932c2271c64f2a4' | |
//const unlockTxId = '83a1d69d99797aee3936ced2908a59428e33db1fdaeee4125f278a3815b64403' | |
//Index | |
const inputIndex = 0 | |
//scriptName | |
const scriptName = 'SimpleP2PKH' | |
createScriptFromUnlockTx( woc, unlockTxId, inputIndex, scriptName ) |
another example on unlockTxId = '20adad8bd4cc694cfed4ccadff911433601e55b0f8779e839bc6579cb8d234f9'
https://whatsonchain.com/tx/20adad8bd4cc694cfed4ccadff911433601e55b0f8779e839bc6579cb8d234f9
% node createScriptFromTx.js
MultiSigBUG.scrypt >>>>>>>>>>
contract MultiSigBUG {
public function unlock(bytes p0, bytes p1) {
asm {
OP_0
OP_TOALTSTACK
OP_IF
OP_DUP
OP_HASH160
dd2d89bb9f64cbdf4139ff0e23c4813124af85e6
OP_EQUALVERIFY
OP_CHECKSIGVERIFY
OP_FROMALTSTACK
OP_1ADD
OP_TOALTSTACK
OP_ENDIF
OP_IF
OP_DUP
OP_HASH160
aef82c0ef3f0c1d867e12b64e9e8d2ebb983dc81
OP_EQUALVERIFY
OP_CHECKSIGVERIFY
OP_FROMALTSTACK
OP_1ADD
OP_TOALTSTACK
OP_ENDIF
OP_2
OP_FROMALTSTACK
OP_GREATERTHANOREQUAL
}
}
}
<<<<<<<<<< MultiSigBUG.scrypt
launche.json >>>>>>>>>>
{
"type": "scrypt",
"request": "launch",
"name": "Debug MultiSigBUG",
"program": "${workspaceFolder}/contracts/MultiSigBUG.scrypt",
"constructorArgs": [
],
"pubFunc": "unlock",
"pubFuncArgs": [
"b'00'", "b'00'"
],
"txContext": {
"hex": "02000000066ae810f19d8427fd95cbffa2ea01e8adfbc9c9710e9f137c00ce007dd78be3b600000000020000ffffffff45730c9a39f17564c5a267a0b27cd0f20ab13fb2f20b45e5a95584fafeb2f7e501000000020000ffffffffc05321108d3881221bf32d41084ac73af16dde235490d06c52a23c4e10b741e101000000020000ffffffff0b3da4ebb0d52439c24be0ae37bc77d87b820e6aebd8a013a4dc47fc8cace17901000000020000ffffffff50726d09ed427b43083a07fb871efc8999b6e7097b8dd2571958042f8adea1d601000000020000ffffffff40191014b8a0a1c2bbfe9da361ad0dbba3c5e4408dbe360b7dcb677ce9b2597401000000020000ffffffff01685747f80d0000001976a914d7185cd6f589013da9f72efba7193d7536b6175c88ac00000000",
"inputIndex": 0,
"inputSatoshis": 10000000000
}
}
<<<<<<<<<< launche.json
Debug the output asm code using sCrypt vscode extension https://marketplace.visualstudio.com/items?itemName=bsv-scrypt.sCrypt
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
a SimpleP2PKH example when unlockTxId = 'fc5e29ae7aafeb774cc1f94c951381bff358af64e8ad33a8a932c2271c64f2a4'
https://whatsonchain.com/tx/fc5e29ae7aafeb774cc1f94c951381bff358af64e8ad33a8a932c2271c64f2a4