@@ -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
229283function buildStack ( type , signatures , pubKeys , allowIncomplete ) {
0 commit comments