extractSigs - verify pubKey & pubKeyHash purported public keys, plus a round of comments

This commit is contained in:
Thomas Kerin 2016-11-12 18:01:54 +01:00
parent c215f350fc
commit b09cf89f97

View File

@ -185,12 +185,19 @@ InSigner.prototype.extractStandard = function (solution, chunks, sigVersion) {
if (solution.type === bscript.types.P2PK) {
if (bscript.pubKey.input.check(chunks)) {
decoded = bscript.pubKey.input.decode(chunks)
if (!decoded.pubKey.equals(solution.solvedBy)) {
throw new Error('Key in scriptSig does not match output script key')
}
signatures[0] = decoded.signature
publicKeys[0] = solution.solvedBy
}
} else if (solution.type === bscript.types.P2PKH) {
if (bscript.pubKeyHash.input.check(chunks)) {
decoded = bscript.pubKeyHash.input.decode(chunks)
if (!bcrypto.hash160(decoded.pubKey).equals(solution.solvedBy)) {
throw new Error('Key in scriptSig does not match output script key-hash')
}
signatures[0] = decoded.signature
publicKeys[0] = decoded.pubKey
}
@ -216,67 +223,75 @@ InSigner.prototype.extractStandard = function (solution, chunks, sigVersion) {
}
InSigner.prototype.solve = function (opts) {
// Determine scriptPubKey is solvable
var scriptPubKey = solveScript(opts.scriptPubKey)
if (scriptPubKey.type !== bscript.types.P2SH && ALLOWED_P2SH_SCRIPTS.indexOf(scriptPubKey.type) === -1) {
throw new Error('txOut script is non-standard')
}
var solution = scriptPubKey
var redeemScript
var witnessScript
var value = 0
var sigVersion = Transaction.SIG_V0
var solution = scriptPubKey
var value = 0
if (solution.type === bscript.types.P2SH) {
var scriptHash = solution.solvedBy
// Redeem script must be provided by opts
if (!(opts.redeemScript instanceof Buffer)) {
throw new Error('Redeem script required to solve utxo')
}
// Check redeemScript against script-hash
if (!scriptHash.equals(bcrypto.hash160(opts.redeemScript))) {
throw new Error('Redeem script does not match txOut script hash')
}
// Determine redeemScript is solvable
solution = solveScript(opts.redeemScript)
if (ALLOWED_P2SH_SCRIPTS.indexOf(solution.type)) {
redeemScript = solution
} else {
if (!ALLOWED_P2SH_SCRIPTS.indexOf(solution.type)) {
throw new Error('Unsupported P2SH script')
}
redeemScript = solution
}
if (solution.type === bscript.types.P2WPKH) {
// txOutValue is required here
if (!types.Satoshi(opts.value)) {
throw new Error('Value is required for witness-key-hash')
}
// We set solution to this to avoid work later, since P2WPKH is a special case of P2PKH
solution = solveScript(bscript.pubKeyHash.output.encode(solution.solvedBy))
value = opts.value
sigVersion = Transaction.SIG_V1
value = opts.value
} else if (solution.type === bscript.types.P2WSH) {
var witnessScriptHash = solution.solvedBy
// Witness script must be provided by opts
if (!(opts.witnessScript instanceof Buffer)) {
throw new Error('P2WSH script required to solve utxo')
}
// txOutValue is required here
if (!types.Satoshi(opts.value)) {
throw new Error('Value is required for witness-script-hash')
}
if (!bufferEquals(bcrypto.sha256(opts.witnessScript), witnessScriptHash)) {
// Check witnessScript against script hash
if (!bcrypto.sha256(opts.witnessScript).equals(witnessScriptHash)) {
throw new Error('Witness script does not match txOut script hash')
}
solution = witnessScript = solveScript(opts.witnessScript)
value = opts.value
sigVersion = Transaction.SIG_V1
if (SIGNABLE_SCRIPTS.indexOf(witnessScript.type) === -1) {
solution = solveScript(opts.witnessScript)
// Determine if witnessScript is solvable
if (SIGNABLE_SCRIPTS.indexOf(solution.type) === -1) {
throw new Error('witness script is not supported')
}
witnessScript = solution
sigVersion = Transaction.SIG_V1
value = opts.value
}
this.signScript = solution
this.scriptPubKey = scriptPubKey
this.value = value
this.sigVersion = sigVersion
this.redeemScript = redeemScript
this.witnessScript = witnessScript
this.sigVersion = sigVersion
this.value = value
}
InSigner.prototype.extractSig = function () {
@ -284,20 +299,20 @@ InSigner.prototype.extractSig = function () {
var input = this.tx.ins[this.nIn]
var solution = this.scriptPubKey
var extractChunks = []
var sigVersion = 0
if (solution.canSign) {
extractChunks = evalPushOnly(input.script)
}
if (solution.type === bscript.types.P2SH) {
if (bscript.scriptHash.input.check(input.script)) {
// If we go to extract a P2SH scriptSig, verify the provided redeemScript
var p2sh = bscript.scriptHash.input.decode(input.script)
if (!p2sh.redeemScript.equals(this.redeemScript.script)) {
throw new Error('Redeem script from scriptSig does not match')
}
solution = this.redeemScript
if (solution.canSign) {
// We only bother if canSign, otherwise we waste time
extractChunks = evalPushOnly(p2sh.redeemScriptSig)
}
}
@ -310,7 +325,6 @@ InSigner.prototype.extractSig = function () {
throw new Error('Public key does not match key-hash')
}
sigVersion = 1
extractChunks = input.witness
}
} else if (solution.type === bscript.types.P2WSH) {
@ -318,14 +332,13 @@ InSigner.prototype.extractSig = function () {
if (!this.witnessScript.equals(input.witness[ input.witness.length - 1 ])) {
throw new Error('Witness script does not match')
}
sigVersion = 1
solution = input.witnessScript
extractChunks = input.witness.slice(0, -1)
}
}
if (extractChunks.length > 0) {
[this.signatures, this.publicKeys] = this.extractStandard(solution, extractChunks, sigVersion)
[this.signatures, this.publicKeys] = this.extractStandard(solution, extractChunks, this.sigVersion)
}
}