Untitled
unknown
javascript
2 months ago
5.0 kB
5
Indexable
const crypto = require('crypto'); const bs58 = require('bs58'); const fs = require('fs'); // Utility functions const hexToBuffer = (hex) => Buffer.from(hex, 'hex'); const doubleSha256 = (data) => crypto.createHash('sha256').update(crypto.createHash('sha256').update(data).digest()).digest(); const encodeVarint = (n) => n < 0xfd ? [n] : (n <= 0xffff ? [0xfd, n & 0xFF, (n >> 8) & 0xFF] : (n <= 0xffffffff ? [0xfe, n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, (n >> 24) & 0xFF] : [0xff, ...Array.from({length: 8}, (_, i) => (n >> (i * 8)) & 0xFF)])); const intToLittleEndian = (val, size) => { let buf = Buffer.alloc(size); for (let i = 0; i < size; i++) buf[i] = (val >> (i * 8)) & 0xFF; return buf; }; // Base58 address to script conversion (P2PKH or P2SH) const addressToScript = (address) => { const decoded = bs58.decode(address); const hash160 = decoded.slice(1, 21); return Buffer.concat([Buffer.from([0xa9, 0x14]), hash160, Buffer.from([0x87])]); }; // Transaction serialization const serializeOutpoint = (hash, index) => { const hashBuf = Buffer.from(hash, 'hex').reverse(); const indexBuf = Buffer.alloc(4); indexBuf.writeUInt32LE(index); return Buffer.concat([hashBuf, indexBuf]); }; const serializeInput = (prevHash, prevIndex, script, sequence) => { const outpoint = serializeOutpoint(prevHash, prevIndex); const scriptLen = encodeVarint(script.length); const sequenceBuf = Buffer.alloc(4); sequenceBuf.writeUInt32LE(sequence); return Buffer.concat([outpoint, scriptLen, script, sequenceBuf]); }; const serializeOutput = (value, script) => { const valueBuf = Buffer.alloc(8); valueBuf.writeBigUInt64LE(BigInt(value)); const scriptLen = encodeVarint(script.length); return Buffer.concat([valueBuf, scriptLen, script]); }; // P2WSH Witness creation const getP2WSHWitness = (signatures, witnessScript) => { const witness = [0x04, 0x00]; // OP_0 due to CHECKMULTISIG bug signatures.forEach(sig => { witness.push(sig.length, ...sig); }); witness.push(witnessScript.length, ...witnessScript); return Buffer.from(witness); }; // Transaction creation const createTransaction = () => { const pubKey1 = hexToBuffer('032ff8c5df0bc00fe1ac2319c3b8070d6d1e04cfbf4fedda499ae7b775185ad53b'); const pubKey2 = hexToBuffer('039bbc8d24f89e5bc44c5b0d1980d6658316a6b2440023117c3c03a4975b04dd56'); const redeemScript = Buffer.concat([Buffer.from([0x52, 0x21]), pubKey1, Buffer.from([0x21]), pubKey2, Buffer.from([0x52, 0xae])]); const witnessScript = redeemScript; const witnessProgram = doubleSha256(witnessScript); const p2wshScript = Buffer.concat([Buffer.from([0x00, 0x20]), witnessProgram]); const p2shRedeemScript = p2wshScript; const p2shInputScript = Buffer.concat([Buffer.from([p2shRedeemScript.length]), p2shRedeemScript]); const version = Buffer.from([0x02, 0x00, 0x00, 0x00]); const marker = Buffer.from([0x00]); const flag = Buffer.from([0x01]); // Inputs and Outputs const nInputs = encodeVarint(1); const txInput = serializeInput('0'.repeat(64), 0, p2shInputScript, 0xffffffff); const nOutputs = encodeVarint(1); const outputScript = addressToScript('325UUecEQuyrTd28Xs2hvAxdAjHM7XzqVF'); const txOutput = serializeOutput(100000, outputScript); // Outpoints, sequences, outputs for final tx const outpoints = [serializeOutpoint('0'.repeat(64), 0)]; const hashPrevouts = doubleSha256(Buffer.concat(outpoints)); const sequences = [Buffer.from([0xff, 0xff, 0xff, 0xff])]; const hashSequence = doubleSha256(Buffer.concat(sequences)); const hashOutputs = doubleSha256(txOutput); // Preimage for sighash const preimage = Buffer.concat([ version, hashPrevouts, hashSequence, outpoints[0], encodeVarint(witnessScript.length), witnessScript, Buffer.from([100000]), sequences[0], hashOutputs, Buffer.from([0x00, 0x00, 0x00, 0x00]), Buffer.from([0x01, 0x00, 0x00, 0x00]) ]); const sighash = doubleSha256(preimage); // Signatures const signature1 = Buffer.from('304402202335473bc09007ca8d4b738e67ac56a0a75b4f945d8d2fd0452437c15d4e2041022048c08ad5b8f09b304eb36e6ed0c6087d8fccd15d4110d114e856a9580844594701', 'hex'); const signature2 = Buffer.from('30450221009aa7fc343e0d4d1d2298cb80b1b0453dcb0e38fe0af2f707118cb402a87fb0480220658b120004b1a43986b0ccdca723f66b9601c565152dee7631853b139c9746e701', 'hex'); const signatures = [signature1, signature2]; // Generate witness const witness = getP2WSHWitness(signatures, witnessScript); // Locktime const locktime = intToLittleEndian(0x00, 4); // Final transaction const finalTx = Buffer.concat([version, marker, flag, nInputs, txInput, nOutputs, txOutput, witness, locktime]); const txidNew = finalTx.toString('hex'); // Output and save result console.log(txidNew); fs.writeFileSync('out.txt', txidNew); }; // Call the function to create the transaction createTransaction();
Editor is loading...
Leave a Comment