Solve Output: take an output script, returns {type, script, solvedBy, requiredSigs, canSign}

This commit is contained in:
Thomas Kerin 2016-11-09 17:13:14 +01:00
parent dd649867f6
commit ffca5afcff
2 changed files with 81 additions and 1 deletions

View File

@ -17,6 +17,9 @@ var types = {
P2WSH: 'witnessscripthash'
}
var SIGNABLE_SCRIPTS = [types.MULTISIG, types.P2PKH, types.P2PK]
var P2SH_SCRIPTS = SIGNABLE_SCRIPTS.concat([types.P2WPKH, types.P2WSH])
function classifyOutput (script) {
if (witnessPubKeyHash.output.check(script)) return types.P2WPKH
if (witnessScriptHash.output.check(script)) return types.P2WSH
@ -54,10 +57,61 @@ function classifyWitness (script, allowIncomplete) {
return types.NONSTANDARD
}
function solveOutput (scriptCode) {
if (!(scriptCode instanceof Buffer)) {
throw new Error('Argument 0 for solveScript must be a Buffer')
}
var outputType = classifyOutput(scriptCode)
var solvedBy = null
var requiredSigs = null
switch (outputType) {
// We can only determine the relevant hash from these, not if it's signable
case types.P2SH:
solvedBy = scriptHash.output.decode(scriptCode)
break
case types.P2WSH:
solvedBy = witnessScriptHash.output.decode(scriptCode)
break
// P2WPKH is separate from other signable types, it's best viewed as a special case for P2PKH
// Not included in canSign.
case types.P2WPKH:
solvedBy = witnessPubKeyHash.output.decode(scriptCode)
requiredSigs = 1
break
// We can immediately solve signatures for these
// When adding a new script type, edit here
case types.P2PK:
solvedBy = pubKey.output.decode(scriptCode)
requiredSigs = 1
break
case types.P2PKH:
solvedBy = pubKeyHash.output.decode(scriptCode)
requiredSigs = 1
break
case types.MULTISIG:
solvedBy = multisig.output.decode(scriptCode)
requiredSigs = solvedBy.m
break
}
return {
type: outputType,
script: scriptCode,
solvedBy: solvedBy,
canSign: SIGNABLE_SCRIPTS.indexOf(outputType) !== -1,
requiredSigs: requiredSigs
}
}
module.exports = {
classifyInput: classifyInput,
classifyOutput: classifyOutput,
classifyWitness: classifyWitness,
solveOutput: solveOutput,
multisig: multisig,
nullData: nullData,
pubKey: pubKey,
@ -65,5 +119,7 @@ module.exports = {
scriptHash: scriptHash,
witnessPubKeyHash: witnessPubKeyHash,
witnessScriptHash: witnessScriptHash,
types: types
types: types,
SIGNABLE_SCRIPTS: SIGNABLE_SCRIPTS,
P2SH_SCRIPTS: P2SH_SCRIPTS
}

View File

@ -105,6 +105,30 @@ describe('script', function () {
})
})
describe('solveOutput', function () {
fixtures.valid.forEach(function (f) {
var script
if (f.scriptPubKeyHex) {
script = new Buffer(f.scriptPubKeyHex, 'hex')
} else if (f.scriptPubKey) {
script = bscript.fromASM(f.scriptPubKey)
} else {
return
}
it('solves ' + bscript.toASM(script) + ' as ' + f.type, function () {
var solution = bscript.solveOutput(script)
assert.equal(solution.type, f.type)
if ([bscript.types.P2SH].concat(bscript.P2SH_SCRIPTS).indexOf(f.type) === -1) {
assert.equal(solution.solvedBy, null)
}
if (solution.canSign) {
assert.notEqual(solution.requiredSigs, null)
}
})
})
})
describe('SCRIPT_VERIFY_MINIMALDATA policy', function () {
fixtures.valid.forEach(function (f) {
if (f.scriptSigHex) {