scryptlib
Advanced tools
Comparing version 1.1.0-beta.6 to 1.1.0-beta.7
@@ -118,3 +118,3 @@ "use strict"; | ||
FunctionCall.prototype.verify = function (txContext) { | ||
var result = this.contract.run_verify(this.unlockingScript.toASM() || '', txContext); | ||
var result = this.contract.run_verify(this.unlockingScript, txContext); | ||
if (!result.success) { | ||
@@ -121,0 +121,0 @@ var debugUrl = this.genLaunchConfig(txContext); |
import { LibraryEntity, ParamEntity } from '.'; | ||
import { ContractEntity, OpCode, StaticEntity } from './compilerWrapper'; | ||
import { ABICoder, Arguments, FunctionCall, Script, State, Struct, SupportedParamType, ScryptType, TypeResolver, StructEntity, ABIEntity, CompileResult, AliasEntity } from './internal'; | ||
import { ABICoder, Arguments, FunctionCall, Script, State, bsv, Struct, SupportedParamType, ScryptType, TypeResolver, StructEntity, ABIEntity, CompileResult, AliasEntity } from './internal'; | ||
import { Library, ScryptTypeResolver } from './scryptTypes'; | ||
export interface TxContext { | ||
tx?: any; | ||
tx?: bsv.Transaction; | ||
inputIndex?: number; | ||
/** | ||
* @deprecated no need any more | ||
*/ | ||
inputSatoshis?: number; | ||
@@ -54,3 +57,3 @@ opReturn?: string; | ||
scriptedConstructor: FunctionCall; | ||
calls: Map<string, FunctionCall>; | ||
private calledPubFunctions; | ||
hexTemplateInlineASM: Map<string, string>; | ||
@@ -78,3 +81,8 @@ hexTemplateArgs: Map<string, string>; | ||
getNewStateScript(states: Record<string, SupportedParamType>): Script; | ||
run_verify(unlockingScriptASM: string, txContext?: TxContext): VerifyResult; | ||
run_verify(unlockingScript: bsv.Script | string, txContext?: TxContext): VerifyResult; | ||
private fmtError; | ||
genLaunchConfig(err: { | ||
error: string; | ||
failedAt: any; | ||
}, tx: bsv.Transaction, index?: number): string; | ||
private _dataPartInHex; | ||
@@ -90,2 +98,3 @@ set dataPart(dataInScript: Script | undefined); | ||
arguments(pubFuncName: string): Arguments; | ||
private lastCalledPubFunction; | ||
ctorArgs(): Arguments; | ||
@@ -92,0 +101,0 @@ static fromASM(asm: string): AbstractContract; |
@@ -73,3 +73,3 @@ "use strict"; | ||
} | ||
this.calls = new Map(); | ||
this.calledPubFunctions = []; | ||
this.hexTemplateInlineASM = new Map(); | ||
@@ -224,20 +224,26 @@ this.hexTemplateArgs = new Map(); | ||
}; | ||
AbstractContract.prototype.run_verify = function (unlockingScriptASM, txContext) { | ||
AbstractContract.prototype.run_verify = function (unlockingScript, txContext) { | ||
var txCtx = Object.assign({}, this._txContext || {}, txContext || {}); | ||
var us = unlockingScriptASM.trim() ? internal_1.bsv.Script.fromASM(unlockingScriptASM.trim()) : new internal_1.bsv.Script(''); | ||
var us; | ||
if (typeof unlockingScript === 'string') { | ||
us = unlockingScript.trim() ? internal_1.bsv.Script.fromASM(unlockingScript.trim()) : new internal_1.bsv.Script(''); | ||
} | ||
else { | ||
us = unlockingScript ? unlockingScript : new internal_1.bsv.Script(''); | ||
} | ||
var ls = internal_1.bsv.Script.fromHex(this.lockingScript.toHex()); | ||
var tx = txCtx.tx; | ||
var inputIndex = txCtx.inputIndex || 0; | ||
var inputSatoshis = txCtx.inputSatoshis || 0; | ||
var inputSatoshis = txCtx.inputSatoshis || (tx ? tx.getInputAmount(inputIndex) : 0); | ||
internal_1.bsv.Script.Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER; | ||
internal_1.bsv.Script.Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER; | ||
var bsi = new internal_1.bsv.Script.Interpreter(); | ||
var lastfExecs = {}; | ||
var failedAt = {}; | ||
bsi.stepListener = function (step) { | ||
if (step.fExec || (internal_1.bsv.Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= internal_1.bsv.Opcode.OP_ENDIF)) { | ||
if ((internal_1.bsv.Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= internal_1.bsv.Opcode.OP_ENDIF) || step.opcode.toNumber() === internal_1.bsv.Opcode.OP_RETURN) /**Opreturn */ { | ||
lastfExecs.opcode = step.opcode; | ||
failedAt.opcode = step.opcode; | ||
} | ||
else { | ||
lastfExecs = step; | ||
failedAt = step; | ||
} | ||
@@ -253,4 +259,3 @@ } | ||
} | ||
var failedOpCode = lastfExecs.opcode.toNumber(); | ||
if ([internal_1.bsv.Opcode.OP_CHECKSIG, internal_1.bsv.Opcode.OP_CHECKSIGVERIFY, internal_1.bsv.Opcode.OP_CHECKMULTISIG, internal_1.bsv.Opcode.OP_CHECKMULTISIGVERIFY].includes(failedOpCode)) { | ||
if (bsi.errstr.indexOf('SCRIPT_ERR_NULLFAIL') > -1) { | ||
if (!txCtx) { | ||
@@ -263,3 +268,14 @@ throw new Error('should provide txContext when verify'); | ||
} | ||
var error = "VerifyError: " + bsi.errstr + ", fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
failedAt.opcode = failedAt.opcode.toNumber(); | ||
return { | ||
success: result, | ||
error: this.fmtError({ | ||
error: bsi.errstr, | ||
failedAt: failedAt | ||
}) | ||
}; | ||
}; | ||
AbstractContract.prototype.fmtError = function (err) { | ||
var failedOpCode = err.failedAt.opcode; | ||
var error = "VerifyError: " + err.error + ", fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
if (this.sourceMapFile) { | ||
@@ -272,8 +288,8 @@ var sourceMapFilePath = internal_1.uri2path(this.sourceMapFile); | ||
var sources = sourceMap.sources.map(function (source) { return compilerWrapper_1.getFullFilePath(source, srcDir_1, sourceFileName_1); }); | ||
var pos = internal_1.findSrcInfoV2(lastfExecs.pc, sourceMap); | ||
var pos = internal_1.findSrcInfoV2(err.failedAt.pc, sourceMap); | ||
if (pos && sources[pos[1]]) { | ||
error = "VerifyError: " + bsi.errstr + " \n\t[Go to Source](" + internal_1.path2uri(sources[pos[1]]) + "#" + pos[2] + ") fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
error = "VerifyError: " + err.error + " \n\t[Go to Source](" + internal_1.path2uri(sources[pos[1]]) + "#" + pos[2] + ") fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
} | ||
} | ||
else if (this.version === 8) { | ||
else if (this.version <= 8) { | ||
var desc = Object.getPrototypeOf(this).constructor.desc; | ||
@@ -283,3 +299,3 @@ var sourceMap = compilerWrapper_1.loadSourceMapfromDesc(desc); | ||
// the complete script may have op_return and data, but compiled output does not have it. So we need to make sure the index is in boundary. | ||
var opcodeIndex = lastfExecs.pc; | ||
var opcodeIndex = err.failedAt.pc; | ||
if (sourceMap[opcodeIndex]) { | ||
@@ -295,3 +311,3 @@ var opcode = sourceMap[opcodeIndex]; | ||
if (opcode && opcode.pos) { | ||
error = "VerifyError: " + bsi.errstr + " \n\t[Go to Source](" + internal_1.path2uri(opcode.pos.file) + "#" + opcode.pos.line + ") fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
error = "VerifyError: " + err.error + " \n\t[Go to Source](" + internal_1.path2uri(opcode.pos.file) + "#" + opcode.pos.line + ") fails at " + new internal_1.bsv.Opcode(failedOpCode) + "\n"; | ||
} | ||
@@ -301,7 +317,17 @@ } | ||
} | ||
return { | ||
success: result, | ||
error: error | ||
}; | ||
return error; | ||
}; | ||
AbstractContract.prototype.genLaunchConfig = function (err, tx, index) { | ||
var error = this.fmtError(err); | ||
var lastCalledPubFunction = this.lastCalledPubFunction(); | ||
var inputIndex = index || 0; | ||
if (lastCalledPubFunction) { | ||
var debugUrl = lastCalledPubFunction.genLaunchConfig({ | ||
tx: tx, | ||
inputIndex: inputIndex | ||
}); | ||
error = error + ("\t[Launch Debugger](" + debugUrl.replace(/file:/i, 'scryptlaunch:') + ")\n"); | ||
} | ||
return error; | ||
}; | ||
Object.defineProperty(AbstractContract.prototype, "dataPart", { | ||
@@ -378,7 +404,17 @@ get: function () { | ||
} | ||
if (this.calls.has(pubFuncName)) { | ||
return this.calls.get(pubFuncName).args; | ||
for (var i = this.calledPubFunctions.length - 1; i >= 0; i--) { | ||
var called = this.calledPubFunctions[i]; | ||
if (called.methodName === pubFuncName) { | ||
return called.args; | ||
} | ||
} | ||
return []; | ||
}; | ||
AbstractContract.prototype.lastCalledPubFunction = function () { | ||
var index = this.calledPubFunctions.length - 1; | ||
if (index < 0) { | ||
return undefined; | ||
} | ||
return this.calledPubFunctions[index]; | ||
}; | ||
AbstractContract.prototype.ctorArgs = function () { | ||
@@ -525,3 +561,3 @@ return this.arguments('constructor'); | ||
var call = ContractClass.abiCoder.encodePubFunctionCall(this, entity.name, args); | ||
this.calls.set(entity.name, call); | ||
this.calledPubFunctions.push(call); | ||
return call; | ||
@@ -528,0 +564,0 @@ }; |
{ | ||
"name": "scryptlib", | ||
"version": "1.1.0-beta.6", | ||
"version": "1.1.0-beta.7", | ||
"description": "Javascript SDK for integration of Bitcoin SV Smart Contracts written in sCrypt language.", | ||
@@ -59,3 +59,3 @@ "engines": { | ||
"husky": "^5.2.0", | ||
"mocha": "^6.2.2", | ||
"mocha": "^10.1.0", | ||
"nyc": "^15.1.0", | ||
@@ -62,0 +62,0 @@ "ts-loader": "^6.2.1", |
@@ -347,3 +347,6 @@ /* eslint-disable @typescript-eslint/ban-types */ | ||
spentTxId: string | null; | ||
constructor(data: object); | ||
constructor(data: { | ||
script: Script, | ||
satoshis: number | ||
}); | ||
@@ -366,2 +369,4 @@ setScript(script: Script | string | Buffer): this; | ||
setScript(script: Script): this; | ||
getSignatures(tx: Transaction, privateKey: PrivateKey, inputIndex: number, sigtype?: number): any; | ||
getPreimage(tx: Transaction, inputIndex: number, sigtype?: number, isLowS?: boolean): any; | ||
} | ||
@@ -372,3 +377,3 @@ | ||
class PublicKeyHash extends Input { | ||
} | ||
@@ -470,3 +475,3 @@ } | ||
verify(): string | boolean; | ||
verify(): string | true; | ||
isCoinbase(): boolean; | ||
@@ -496,6 +501,6 @@ | ||
isLowS?: boolean | ||
}, unlockingScript: Script | ((tx: Transaction, outputInPrevTx: Transaction.Output, preimage: string, signature: string) => Script)): this; | ||
}, unlockingScript: Script | ((tx: Transaction, outputInPrevTx: Transaction.Output) => Script)): this; | ||
setInputSequence(inputIndex: number, sequence: number): this; | ||
setOutput(outputIndex: number, output: Transaction.Output | ((tx: Transaction) => Transaction.Output)): this; | ||
seal(): void; | ||
seal(): this; | ||
isSealed(): boolean; | ||
@@ -506,2 +511,17 @@ getChangeAmount(): number; | ||
prevouts(): string; | ||
getSignature(inputIndex: number, privateKey?: PrivateKey, sigtype?: number): string; | ||
getPreimage(inputIndex: number, sigtype?: number, isLowS?: boolean): string; | ||
addInputFromPrevTx(prevTx: Transaction, outputIndex?: number): this; | ||
addDummyInput(script: Script, satoshis: number): this; | ||
verifyInput(inputIndex: number, cb?: (execution: { | ||
success: boolean, | ||
error: string, | ||
failedAt: any | ||
}) => string): { | ||
success: boolean, | ||
error: string, | ||
failedAt: any | ||
}; | ||
getInputAmount(inputIndex: number): number; | ||
getOutputAmount(outputIndex: number): number; | ||
} | ||
@@ -508,0 +528,0 @@ |
@@ -69,2 +69,5 @@ 'use strict' | ||
message: 'No previous output information.' | ||
}, { | ||
name: 'MissingInput', | ||
message: 'Invalid inputIndex.' | ||
}] | ||
@@ -93,2 +96,5 @@ }, { | ||
}, { | ||
name: 'MissingOutput', | ||
message: 'Output not found' | ||
}, { | ||
name: 'InvalidSatoshis', | ||
@@ -95,0 +101,0 @@ message: 'Output satoshis are invalid' |
@@ -12,2 +12,7 @@ 'use strict' | ||
var Output = require('../output') | ||
var Signature = require('../../crypto/signature') | ||
var TransactionSignature = require('../signature') | ||
var Hash = require('../../crypto/hash') | ||
var Interpreter = require('../../script/interpreter') | ||
var Opcode = require('../../opcode') | ||
@@ -19,2 +24,17 @@ var MAXINT = 0xffffffff // Math.pow(2, 32) - 1; | ||
function getLowSPreimage (tx, sigtype, inputIndex, inputLockingScript, inputAmount) { | ||
var i = 0 | ||
do { | ||
var preimage = Sighash.sighashPreimage(tx, sigtype, inputIndex, inputLockingScript, inputAmount) | ||
var sighash = Hash.sha256sha256(preimage) | ||
if (_.isPositiveNumber(sighash.readUInt8()) && _.isPositiveNumber(sighash.readUInt8(31))) { | ||
return preimage | ||
} | ||
tx.nLockTime++ | ||
} while (i < Number.MAX_SAFE_INTEGER) | ||
} | ||
function Input (params) { | ||
@@ -151,15 +171,36 @@ if (!(this instanceof Input)) { | ||
* @param {number} inputIndex - the index of this input in the provided transaction | ||
* @param {number} sigType - defaults to Signature.SIGHASH_ALL | ||
* @param {Buffer} addressHash - if provided, don't calculate the hash of the | ||
* public key associated with the private key provided | ||
* @param {number} sigType - defaults to Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID | ||
* @abstract | ||
*/ | ||
Input.prototype.getSignatures = function () { | ||
// throw new errors.AbstractMethodInvoked( | ||
// 'Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported)' + | ||
// ' for input: ' + JSON.stringify(this) | ||
// ) | ||
return [] | ||
Input.prototype.getSignatures = function (transaction, privateKey, inputIndex, sigtype) { | ||
$.checkState(this.output instanceof Output) | ||
sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID) | ||
return [new TransactionSignature({ | ||
publicKey: privateKey.publicKey, | ||
prevTxId: this.prevTxId, | ||
outputIndex: this.outputIndex, | ||
inputIndex: inputIndex, | ||
signature: Sighash.sign(transaction, privateKey, sigtype, inputIndex, this.output.script, this.output.satoshisBN), | ||
sigtype: sigtype | ||
})] | ||
} | ||
/** | ||
* Retrieve preimage for the Input. | ||
* | ||
* @param {Transaction} transaction - the transaction to be signed | ||
* @param {number} inputIndex - the index of this input in the provided transaction | ||
* @param {number} sigType - defaults to Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID | ||
* @param {boolean} isLowS - true if the sig hash is safe for low s. | ||
* @abstract | ||
*/ | ||
Input.prototype.getPreimage = function (transaction, inputIndex, sigtype, isLowS) { | ||
$.checkState(this.output instanceof Output) | ||
sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID) | ||
isLowS = isLowS || false | ||
return isLowS | ||
? getLowSPreimage(transaction, sigtype, inputIndex, this.output.script, this.output.satoshisBN) | ||
: Sighash.sighashPreimage(transaction, sigtype, inputIndex, this.output.script, this.output.satoshisBN) | ||
} | ||
Input.prototype.isFullySigned = function () { | ||
@@ -206,2 +247,33 @@ throw new errors.AbstractMethodInvoked('Input#isFullySigned') | ||
Input.prototype.verify = function (transaction, inputIndex) { | ||
$.checkState(this.output instanceof Output) | ||
$.checkState(this.script instanceof Script) | ||
var us = this.script | ||
var ls = this.output.script | ||
var inputSatoshis = this.output.satoshisBN | ||
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER | ||
Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER | ||
const bsi = new Interpreter() | ||
let failedAt = {} | ||
bsi.stepListener = function (step) { | ||
if (step.fExec || (Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= Opcode.OP_ENDIF)) { | ||
if ((Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= Opcode.OP_ENDIF) || step.opcode.toNumber() === Opcode.OP_RETURN) /** Opreturn */ { | ||
failedAt.opcode = step.opcode | ||
} else { | ||
failedAt = step | ||
} | ||
} | ||
} | ||
var success = bsi.verify(us, ls, transaction, inputIndex, Interpreter.DEFAULT_FLAGS, inputSatoshis) | ||
failedAt.opcode = failedAt.opcode.toNumber() | ||
return { success, error: bsi.errstr, failedAt: success ? {} : failedAt } | ||
} | ||
module.exports = Input |
@@ -27,19 +27,2 @@ 'use strict' | ||
var BN = require('../crypto/bn') | ||
var Interpreter = require('../script/interpreter') | ||
function getLowSPreimage (tx, sigtype, inputIndex, inputLockingScript, inputAmount) { | ||
var i = 0 | ||
do { | ||
var preimage = Sighash.sighashPreimage(tx, sigtype, inputIndex, inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS).toString('hex') | ||
var sighash = Hash.sha256sha256(Buffer.from(preimage, 'hex')) | ||
if (_.isPositiveNumber(sighash.readUInt8()) && _.isPositiveNumber(sighash.readUInt8(31))) { | ||
return preimage | ||
} | ||
tx.nLockTime++ | ||
} while (i < Number.MAX_SAFE_INTEGER) | ||
} | ||
/** | ||
@@ -61,2 +44,4 @@ * Represents a transaction, a set of inputs and outputs to change ownership of tokens | ||
this._outputsMap = new Map() | ||
this._preimagesMap = new Map() | ||
this._signaturesMap = new Map() | ||
this._privateKey = undefined | ||
@@ -1170,3 +1155,3 @@ this._sigType = undefined | ||
*/ | ||
Transaction.prototype.verify = function () { | ||
Transaction.prototype.verify = function (notVerifyInput) { | ||
// Basic checks that don't depend on any context | ||
@@ -1226,2 +1211,9 @@ if (this.inputs.length === 0) { | ||
} | ||
if (!notVerifyInput) { | ||
var res = this.inputs[i].verify(this, i) | ||
if (!res.success) { | ||
return 'transaction input ' + i + ' VerifyError: ' + res.error | ||
} | ||
} | ||
} | ||
@@ -1249,3 +1241,2 @@ } | ||
var sigtype | ||
var sig | ||
var isLowS = false | ||
@@ -1263,16 +1254,13 @@ if (typeof options === 'number') { | ||
if (unlockScriptOrCallback instanceof Function) { | ||
var inputLockingScript = this.inputs[inputIndex].output.script | ||
var inputAmount = this.inputs[inputIndex].output.satoshis | ||
var preimage = isLowS | ||
? getLowSPreimage(this, sigtype, inputIndex, inputLockingScript, inputAmount) | ||
: Sighash.sighashPreimage(this, sigtype, inputIndex, inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS).toString('hex') | ||
var outputInPrevTx = this.inputs[inputIndex].output | ||
var preimage = this.inputs[inputIndex].getPreimage(this, inputIndex, options.sigtype, isLowS) | ||
this._preimagesMap.set(inputIndex, preimage) | ||
if (privateKey instanceof PrivateKey) { | ||
sig = Sighash.sign( | ||
this, privateKey, sigtype, inputIndex, | ||
inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS | ||
).toTxFormat().toString('hex') | ||
var sig = this.inputs[inputIndex].getSignatures(this, privateKey, inputIndex, options.sigtype)[0] | ||
this._signaturesMap.set(inputIndex, sig) | ||
} | ||
var unlockScript = unlockScriptOrCallback(this, this.inputs[inputIndex].output, preimage, sig) | ||
var unlockScript = unlockScriptOrCallback(this, outputInPrevTx) | ||
@@ -1330,17 +1318,19 @@ this._inputsMap.set(inputIndex, { | ||
this._inputsMap.forEach(function (options, key) { | ||
var inputLockingScript = self.inputs[key].output.script | ||
var inputAmount = self.inputs[key].output.satoshis | ||
var preimage = options.isLowS | ||
? getLowSPreimage(self, options.sigtype, key, inputLockingScript, inputAmount) | ||
: Sighash.sighashPreimage(self, options.sigtype, key, inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS).toString('hex') | ||
var outputInPrevTx = self.inputs[key].output | ||
var sig | ||
var preimage = self.inputs[key].getPreimage(self, key, options.sigtype, options.isLowS) | ||
self._preimagesMap.set(key, preimage) | ||
if (options.privateKey instanceof PrivateKey) { | ||
sig = Sighash.sign( | ||
self, options.privateKey, options.sigtype, key, | ||
inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS | ||
).toTxFormat().toString('hex') | ||
// var sig = Sighash.sign( | ||
// self, options.privateKey, options.sigtype, key, | ||
// inputLockingScript, new BN(inputAmount), Interpreter.DEFAULT_FLAGS | ||
// ).toTxFormat().toString('hex') | ||
var sig = self.inputs[key].getSignatures(self, options.privateKey, key, options.sigtype)[0] | ||
self._signaturesMap.set(key, sig) | ||
} | ||
var unlockScript = options.callback(self, self.inputs[key].output, preimage, sig) | ||
var unlockScript = options.callback(self, outputInPrevTx) | ||
@@ -1414,2 +1404,6 @@ self.inputs[key].setScript(unlockScript) | ||
/** | ||
* | ||
* @returns if the transaction is sealed | ||
*/ | ||
Transaction.prototype.isSealed = function () { | ||
@@ -1419,2 +1413,116 @@ return this.sealed | ||
Transaction.prototype.getPreimage = function (inputIndex, sigtype, isLowS) { | ||
$.checkArgumentType(inputIndex, 'number', 'inputIndex') | ||
var cached = this._preimagesMap.get(inputIndex || 0) | ||
if (cached) { | ||
return cached.toString('hex') | ||
} | ||
sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID) | ||
isLowS = isLowS || false | ||
inputIndex = inputIndex || 0 | ||
var preimage = this.inputs[inputIndex].getPreimage(this, inputIndex, sigtype, isLowS) | ||
this._preimagesMap.set(inputIndex, preimage) | ||
return preimage.toString('hex') | ||
} | ||
Transaction.prototype.getSignature = function (inputIndex, privateKey, sigtype) { | ||
$.checkArgumentType(inputIndex, 'number', 'inputIndex') | ||
var cached = this._signaturesMap.get(inputIndex || 0) | ||
if (cached) { | ||
return cached.signature.toTxFormat().toString('hex') | ||
} | ||
sigtype = sigtype || (Signature.SIGHASH_ALL | Signature.SIGHASH_FORKID) | ||
var sig = this.inputs[inputIndex].getSignatures(this, privateKey, inputIndex, sigtype)[0] | ||
return sig.signature.toTxFormat().toString('hex') | ||
} | ||
Transaction.prototype.addInputFromPrevTx = function (prevTx, outputIndex) { | ||
$.checkArgumentType(prevTx, Transaction, 'prevTx') | ||
var outputIdx = outputIndex || 0 | ||
const output = prevTx.outputs[outputIdx] | ||
if (output.script.isPublicKeyHashOut()) { | ||
return this.addInput(new PublicKeyHashInput({ | ||
prevTxId: prevTx.id, | ||
outputIndex: outputIdx, | ||
script: new Script(''), // placeholder | ||
output: output | ||
})) | ||
} else { | ||
return this.addInput(new Input({ | ||
prevTxId: prevTx.id, | ||
outputIndex: outputIdx, | ||
script: new Script(''), // placeholder | ||
output: output | ||
})) | ||
} | ||
} | ||
Transaction.prototype.addDummyInput = function (script, satoshis) { | ||
$.checkArgumentType(script, Script, 'script') | ||
$.checkArgumentType(satoshis, 'number', 'satoshis') | ||
return this.addInput(new Input({ | ||
prevTxId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458', | ||
outputIndex: 0, | ||
script: new Script(''), // placeholder | ||
output: new Output({ | ||
script: script, | ||
satoshis: satoshis | ||
}) | ||
})) | ||
} | ||
Transaction.prototype.verifyInput = function (inputIndex, cb) { | ||
$.checkArgumentType(inputIndex, 'number', 'inputIndex') | ||
if (!this.inputs[inputIndex]) { | ||
throw new errors.Transaction.Input.MissingInput() | ||
} | ||
var res = this.inputs[inputIndex].verify(this, inputIndex) | ||
if (cb) { | ||
res.error = cb(res) || res.error | ||
return { | ||
success: res.success, | ||
error: res.error | ||
} | ||
} | ||
return res | ||
} | ||
Transaction.prototype.getInputAmount = function (inputIndex) { | ||
$.checkArgumentType(inputIndex, 'number', 'inputIndex') | ||
if (!this.inputs[inputIndex]) { | ||
throw new errors.Transaction.Input.MissingInput() | ||
} | ||
return this.inputs[inputIndex].output.satoshis | ||
} | ||
Transaction.prototype.getOutputAmount = function (outputIndex) { | ||
$.checkArgumentType(outputIndex, 'number', 'outputIndex') | ||
if (!this.outputs[outputIndex]) { | ||
throw new errors.Transaction.MissingOutput() | ||
} | ||
return this.outputs[outputIndex].satoshis | ||
} | ||
module.exports = Transaction |
Sorry, the diff of this file is too big to display
1008088
24642