UNPKG

thebigguy-contract

Version:

A library to generate P2SH scripts and create spend transactions for permissionless share-based distribution of UTXOs

99 lines 4.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createTx = createTx; const ecash_lib_1 = require("ecash-lib"); const payment_1 = require("./payment"); const script_1 = require("./script"); const utils_1 = require("./utils"); /** * Generates a valid transaction for any UTXO locked by the expected script. * The `fee´ and `parties` used to lock the UTXO must be known and provided * so tha the correct outputs for the transaction can be determined. * * @param ecc An instance of `ecash-lib`'s ECC implementation for reusability * @param prvKey The private key that will be used to sign transactions * @param utxo The outpoint and value being spent * @param fee The fee used for the script locking the `utxo´ * @param parties The list of parties used for the script locking the `utxo` * * @returns A signed transaction that can be serialized and broadcasted. */ function createTx(ecc, prvKey, utxo, fee, parties) { // produce contract script const contract = (0, script_1.createScript)(ecc, prvKey, fee, parties); // create transaction with dynamic outputs based on value const tx = new ecash_lib_1.Tx({ outputs: (0, payment_1.createOutputs)(utxo.value, fee, contract, parties), inputs: [ { prevOut: { txid: utxo.txid, outIdx: utxo.outIdx, }, signData: { sats: BigInt(utxo.value), redeemScript: contract } } ] }); // produce serialized previouts const serializedPrevouts = (0, utils_1.serializePrevouts)(tx.inputs); // produce serialized outputs const serializedOutputs = (0, utils_1.serializeOutputs)(tx.outputs); // get the ALL_BIP143 preimage for the input // // The ALL_BIP143 flag must be used because the script needs to receive both // the prevouts and outputs as input and those need to be validated against // hashPrevouts and hashOutputs. // const sigHashType = ecash_lib_1.ALL_BIP143; const unsignedTx = ecash_lib_1.UnsignedTx.fromTx(tx); const unsignedTxInput = new ecash_lib_1.UnsignedTxInput({ inputIdx: 0, unsignedTx }); const inputPreimage = unsignedTxInput.sigHashPreimage(sigHashType); // sign the preimage (double SHA256, as per BIP 143) // // This is the key aspect since the signature can be used both for CHECKSIG and // CHEKDATASIG. In combination, it ensures that the bytes given as input can be // treated as the same preimage used for transaction validation. In turn, this // allows trusting other provided inputs like the outputs and their values. // const signature = (0, ecash_lib_1.flagSignature)(ecc.schnorrSign(prvKey, (0, ecash_lib_1.sha256d)(inputPreimage.bytes)), sigHashType); // produce the P2SH spend script (inputs + script) const spendScript = ecash_lib_1.Script.fromOps([ (0, ecash_lib_1.pushBytesOp)(serializedPrevouts), (0, ecash_lib_1.pushBytesOp)(serializedOutputs), (0, ecash_lib_1.pushBytesOp)(signature), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(0, 4)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(4, 36)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(36, 68)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(68, 104)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(104, -52)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(-52, -44)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(-44, -40)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(-40, -8)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.bytes.slice(-8)), (0, ecash_lib_1.pushBytesOp)(inputPreimage.redeemScript.bytecode), ]); // produce signed transaction // // The signatory is precomputed in the previous preimage signature. This // process validates fees and dust, and produces a new transaction that // includes the redeem script for the input. // const signedTx = new ecash_lib_1.TxBuilder({ outputs: tx.outputs, inputs: [{ input: tx.inputs[0], signatory: () => spendScript }] }).sign({ ecc }); // make a final verification of the fee const minFee = signedTx.serSize(); if (fee < minFee) { throw new Error(`The fee must be at least 1 sat per byte, that is, ${minFee} or more`); } // return signed transaction return signedTx; } //# sourceMappingURL=tx.js.map