Skip to content

Commit 3ad3157

Browse files
afk11dcousens
authored andcommitted
P2WSH initial commit, tests pass with new logic
1 parent b6ae10b commit 3ad3157

File tree

1 file changed

+86
-32
lines changed

1 file changed

+86
-32
lines changed

src/transaction_builder.js

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -176,54 +176,108 @@ function expandOutput (script, scriptType, ourPubKey) {
176176
}
177177
}
178178

179-
function prepareInput (input, kpPubKey, redeemScript) {
180-
if (redeemScript) {
181-
var redeemScriptHash = bcrypto.hash160(redeemScript)
179+
function checkP2shInput (input, redeemScriptHash) {
180+
if (input.prevOutType) {
181+
if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH')
182182

183-
// if redeemScript exists, it is pay-to-scriptHash
184-
// if we have a prevOutScript, enforce hash160(redeemScriptequality) to the redeemScript
185-
if (input.prevOutType) {
186-
if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH')
183+
var prevOutScriptScriptHash = bscript.decompile(input.prevOutScript)[1]
184+
if (!prevOutScriptScriptHash.equals(redeemScriptHash)) throw new Error('Inconsistent hash160(RedeemScript)')
185+
}
186+
}
187187

188-
var prevOutScriptScriptHash = bscript.decompile(input.prevOutScript)[1]
189-
if (!prevOutScriptScriptHash.equals(redeemScriptHash)) throw new Error('Inconsistent hash160(RedeemScript)')
190-
}
188+
function checkP2WSHInput (input, witnessScriptHash) {
189+
if (input.prevOutType) {
190+
if (input.prevOutType !== scriptTypes.P2WSH) throw new Error('PrevOutScript must be P2WSH')
191191

192-
var expanded = expandOutput(redeemScript, undefined, kpPubKey)
193-
if (!expanded.pubKeys) throw new Error('RedeemScript not supported "' + bscript.toASM(redeemScript) + '"')
192+
var scriptHash = bscript.decompile(input.prevOutScript)[1]
193+
if (!scriptHash.equals(witnessScriptHash)) throw new Error('Inconsistent hash160(WitnessScript)')
194+
}
195+
}
194196

195-
input.pubKeys = expanded.pubKeys
196-
input.signatures = expanded.signatures
197-
input.redeemScript = redeemScript
198-
input.redeemScriptType = expanded.scriptType
199-
input.prevOutScript = input.prevOutScript || bscript.scriptHash.output.encode(redeemScriptHash)
200-
input.prevOutType = scriptTypes.P2SH
201-
input.witness = false
197+
function prepareInput (input, kpPubKey, redeemScript, witnessScript) {
198+
var expanded
199+
var prevOutType
200+
var prevOutScript
201+
202+
var p2sh = false
203+
var p2shType
204+
var redeemScriptHash
202205

203-
// maybe we have some prevOut knowledge
206+
var witness = false
207+
var witnessType
208+
var witnessScriptHash
209+
210+
if (redeemScript && witnessScript) {
211+
redeemScriptHash = bcrypto.hash160(redeemScript)
212+
witnessScriptHash = bcrypto.hash256(witnessScript)
213+
checkP2shInput(input, redeemScriptHash)
214+
if (!redeemScript.equals(bscript.witnessScriptHash.output.encode(witnessScriptHash))) throw new Error('Witness script inconsistent with redeem script')
215+
216+
expanded = expandOutput(witnessScript, undefined, kpPubKey)
217+
if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"')
218+
219+
prevOutType = bscript.types.P2SH
220+
prevOutScript = bscript.scriptHash.output.encode(redeemScriptHash)
221+
p2sh = witness = true
222+
p2shType = bscript.types.P2WSH
223+
witnessType = expanded.scriptType
224+
} else if (redeemScript) {
225+
redeemScriptHash = bcrypto.hash160(redeemScript)
226+
checkP2shInput(input, redeemScriptHash)
227+
228+
expanded = expandOutput(redeemScript, undefined, kpPubKey)
229+
if (!expanded.pubKeys) throw new Error('RedeemScript not supported "' + bscript.toASM(redeemScript) + '"')
230+
231+
prevOutType = bscript.types.P2SH
232+
prevOutScript = bscript.scriptHash.output.encode(redeemScriptHash)
233+
p2sh = true
234+
p2shType = expanded.scriptType
235+
} else if (witnessScript) {
236+
witnessScriptHash = bcrypto.hash256(witnessScript)
237+
checkP2WSHInput(input, witnessScriptHash)
238+
239+
expanded = expandOutput(witnessScript, undefined, kpPubKey)
240+
if (!expanded.pubKeys) throw new Error('WitnessScript not supported "' + bscript.toASM(redeemScript) + '"')
241+
242+
prevOutType = bscript.types.P2WSH
243+
prevOutScript = bscript.witnessScriptHash.output.encode(witnessScriptHash)
244+
witness = true
245+
witnessType = expanded.scriptType
204246
} else if (input.prevOutType) {
205247
// embedded scripts are not possible without a redeemScript
206248
if (input.prevOutType === scriptTypes.P2SH ||
207-
input.prevOutType === scriptTypes.P2WSH) {
249+
input.prevOutType === scriptTypes.P2WSH) {
208250
throw new Error('PrevOutScript is ' + input.prevOutType + ', requires redeemScript')
209251
}
210252

211-
// try to derive missing information using our kpPubKey
253+
prevOutType = input.prevOutType
254+
prevOutScript = input.prevOutScript
212255
expanded = expandOutput(input.prevOutScript, input.prevOutType, kpPubKey)
213256
if (!expanded.pubKeys) return
214257

215-
input.pubKeys = expanded.pubKeys
216-
input.signatures = expanded.signatures
217-
input.witness = (input.prevOutScript === scriptTypes.P2WPKH)
218-
219-
// no prior knowledge, assume pubKeyHash
258+
witness = (input.prevOutScript === scriptTypes.P2WPKH)
220259
} else {
221-
input.prevOutScript = bscript.pubKeyHash.output.encode(bcrypto.hash160(kpPubKey))
222-
input.prevOutType = scriptTypes.P2PKH
223-
input.pubKeys = [kpPubKey]
224-
input.signatures = [undefined]
225-
input.witness = false
260+
prevOutScript = bscript.pubKeyHash.output.encode(bcrypto.hash160(kpPubKey))
261+
expanded = expandOutput(prevOutScript, scriptTypes.P2PKH, kpPubKey)
262+
prevOutType = scriptTypes.P2PKH
263+
witness = false
264+
}
265+
266+
if (p2sh) {
267+
input.redeemScript = redeemScript
268+
input.redeemScriptType = p2shType
226269
}
270+
271+
if (witness && witnessType === bscript.types.P2WSH) {
272+
input.witnessScript = witnessScript
273+
input.witnessScriptType = witnessType
274+
}
275+
276+
input.pubKeys = expanded.pubKeys
277+
input.signatures = expanded.signatures
278+
input.prevOutScript = prevOutScript
279+
input.prevOutType = prevOutType
280+
input.witness = witness
227281
}
228282

229283
function buildStack (type, signatures, pubKeys, allowIncomplete) {

0 commit comments

Comments
 (0)