Completed
Pull Request — master (#380)
by thomas
143:23 queued 73:21
created

InputSigner::extractFromValues()   D

Complexity

Conditions 10
Paths 27

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 10.0033

Importance

Changes 0
Metric Value
cc 10
eloc 23
c 0
b 0
f 0
nc 27
nop 4
dl 0
loc 39
ccs 30
cts 31
cp 0.9677
crap 10.0033
rs 4.8196

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BitWasp\Bitcoin\Transaction\Factory;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
8
use BitWasp\Bitcoin\Crypto\Hash;
9
use BitWasp\Bitcoin\Crypto\Random\Rfc6979;
10
use BitWasp\Bitcoin\Key\PublicKeyFactory;
11
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
12
use BitWasp\Bitcoin\Script\Opcodes;
13
use BitWasp\Bitcoin\Script\Script;
14
use BitWasp\Bitcoin\Script\ScriptFactory;
15
use BitWasp\Bitcoin\Script\ScriptInfo\Multisig;
16
use BitWasp\Bitcoin\Script\ScriptInterface;
17
use BitWasp\Bitcoin\Script\ScriptWitness;
18
use BitWasp\Bitcoin\Signature\SignatureSort;
19
use BitWasp\Bitcoin\Signature\TransactionSignature;
20
use BitWasp\Bitcoin\Signature\TransactionSignatureFactory;
21
use BitWasp\Bitcoin\Signature\TransactionSignatureInterface;
22
use BitWasp\Bitcoin\Transaction\SignatureHash\Hasher;
23
use BitWasp\Bitcoin\Transaction\SignatureHash\SigHashInterface;
24
use BitWasp\Bitcoin\Transaction\SignatureHash\V1Hasher;
25
use BitWasp\Bitcoin\Transaction\TransactionInterface;
26
use BitWasp\Bitcoin\Transaction\TransactionOutputInterface;
27
use BitWasp\Buffertools\BufferInterface;
28
29
class InputSigner
30
{
31
    /**
32
     * @var EcAdapterInterface
33
     */
34
    private $ecAdapter;
35
36
    /**
37
     * @var ScriptInterface $redeemScript
38
     */
39
    private $redeemScript;
40
41
    /**
42
     * @var ScriptInterface $witnessScript
43
     */
44
    private $witnessScript;
45
46
    /**
47
     * @var TransactionInterface
48
     */
49
    private $tx;
50
51
    /**
52
     * @var int
53
     */
54
    private $nInput;
55
56
    /**
57
     * @var TransactionOutputInterface
58
     */
59
    private $txOut;
60
61
    /**
62
     * @var PublicKeyInterface[]
63
     */
64
    private $publicKeys = [];
65
66
    /**
67
     * @var int
68
     */
69
    private $sigHashType;
70
71
    /**
72
     * @var TransactionSignatureInterface[]
73
     */
74
    private $signatures = [];
75
76
    /**
77
     * @var int
78
     */
79
    private $requiredSigs = 0;
80
81
    /**
82
     * @var OutputClassifier
83
     */
84
    private $classifier;
85
86
    /**
87
     * TxInputSigning constructor.
88
     * @param EcAdapterInterface $ecAdapter
89
     * @param TransactionInterface $tx
90
     * @param int $nInput
91
     * @param TransactionOutputInterface $txOut
92
     * @param int $sigHashType
93
     */
94 84
    public function __construct(EcAdapterInterface $ecAdapter, TransactionInterface $tx, $nInput, TransactionOutputInterface $txOut, $sigHashType = SigHashInterface::ALL)
95
    {
96 84
        $this->ecAdapter = $ecAdapter;
97 84
        $this->tx = $tx;
98 84
        $this->nInput = $nInput;
99 84
        $this->txOut = $txOut;
100 84
        $this->classifier = new OutputClassifier();
101 84
        $this->sigHashType = $sigHashType;
102 84
        $this->publicKeys = [];
103 84
        $this->signatures = [];
104
105 84
        $this->extractSignatures();
106 84
    }
107
108
    /**
109
     * @param int $sigVersion
110
     * @param $stack
111
     * @param ScriptInterface $scriptCode
112
     * @return \SplObjectStorage
113
     */
114 24
    private function sortMultiSigs($sigVersion, $stack, ScriptInterface $scriptCode)
115
    {
116 24
        if ($sigVersion === 1) {
117 12
            $hasher = new V1Hasher($this->tx, $this->txOut->getValue());
118 4
        } else {
119 12
            $hasher = new Hasher($this->tx);
120
        }
121
122 24
        $sigSort = new SignatureSort($this->ecAdapter);
123 24
        $sigs = new \SplObjectStorage;
124
125 24
        foreach ($stack as $txSig) {
126
            $hash = $hasher->calculate($scriptCode, $this->nInput, $txSig->getHashType());
127
            $linked = $sigSort->link([$txSig->getSignature()], $this->publicKeys, $hash);
128
129
            foreach ($this->publicKeys as $key) {
130
                if ($linked->contains($key)) {
131
                    $sigs[$key] = $txSig;
132
                }
133
            }
134 8
        }
135
136 24
        return $sigs;
137
    }
138
139
    /**
140
     * @param string $type
141
     * @param ScriptInterface $scriptCode
142
     * @param BufferInterface[] $stack
143
     * @param int $sigVersion
144
     * @return string
145
     */
146 72
    public function extractFromValues($type, ScriptInterface $scriptCode, array $stack, $sigVersion)
147
    {
148 72
        $size = count($stack);
149 72
        if ($type === OutputClassifier::PAYTOPUBKEYHASH) {
150 30
            $this->requiredSigs = 1;
151 30
            if ($size === 2) {
152 12
                $this->signatures = [TransactionSignatureFactory::fromHex($stack[0], $this->ecAdapter)];
153 12
                $this->publicKeys = [PublicKeyFactory::fromHex($stack[1], $this->ecAdapter)];
154 4
            }
155 10
        }
156
157 72
        if ($type === OutputClassifier::PAYTOPUBKEY) {
158 12
            $this->requiredSigs = 1;
159 12
            if ($size === 1) {
160 6
                $this->signatures = [TransactionSignatureFactory::fromHex($stack[0], $this->ecAdapter)];
161 2
            }
162 4
        }
163
164 72
        if ($type === OutputClassifier::MULTISIG) {
165 24
            $info = new Multisig($scriptCode);
166 24
            $this->requiredSigs = $info->getRequiredSigCount();
167 24
            $this->publicKeys = $info->getKeys();
168
169 24
            if ($size > 1) {
170 24
                $vars = [];
171 24
                foreach (array_slice($stack, 1, -1) as $sig) {
172
                    $vars[] = TransactionSignatureFactory::fromHex($sig, $this->ecAdapter);
173 8
                }
174
175 24
                $sigs = $this->sortMultiSigs($sigVersion, $vars, $scriptCode);
176
177 24
                foreach ($this->publicKeys as $idx => $key) {
178 24
                    $this->signatures[$idx] = isset($sigs[$key]) ? $sigs[$key]->getBuffer() : null;
179 8
                }
180 8
            }
181 8
        }
182
183 72
        return $type;
184
    }
185
186
    /**
187
     * @return $this
188
     */
189 84
    public function extractSignatures()
190
    {
191 84
        $scriptPubKey = $this->txOut->getScript();
192 84
        $scriptSig = $this->tx->getInput($this->nInput)->getScript();
193 84
        $type = $this->classifier->classify($scriptPubKey);
194
195 84
        if ($type === OutputClassifier::PAYTOPUBKEYHASH || $type === OutputClassifier::PAYTOPUBKEY || $type === OutputClassifier::MULTISIG) {
196 42
            $values = [];
197 42
            foreach ($scriptSig->getScriptParser()->decode() as $o) {
198 18
                $values[] = $o->getData();
199 14
            }
200
201 42
            $this->extractFromValues($type, $scriptPubKey, $values, 0);
202 14
        }
203
204 84
        if ($type === OutputClassifier::PAYTOSCRIPTHASH) {
205 24
            $decodeSig = $scriptSig->getScriptParser()->decode();
206 24
            if (count($decodeSig) > 0) {
207 18
                $redeemScript = new Script(end($decodeSig)->getData());
208 18
                $p2shType = $this->classifier->classify($redeemScript);
209
210 18
                if (count($decodeSig) > 1) {
211 6
                    $decodeSig = array_slice($decodeSig, 0, -1);
212 2
                }
213
214 18
                $internalSig = [];
215 18
                foreach ($decodeSig as $operation) {
216 18
                    $internalSig[] = $operation->getData();
217 6
                }
218
219 18
                $this->redeemScript = $redeemScript;
220 18
                $this->extractFromValues($p2shType, $redeemScript, $internalSig, 0);
221
222 18
                $type = $p2shType;
223 6
            }
224 8
        }
225
226 84
        $witnesses = $this->tx->getWitnesses();
227 84
        if ($type === OutputClassifier::WITNESS_V0_KEYHASH) {
228 12
            $this->requiredSigs = 1;
229 12
            if (isset($witnesses[$this->nInput])) {
230 12
                $witness = $witnesses[$this->nInput];
231 12
                $this->signatures = [TransactionSignatureFactory::fromHex($witness[0], $this->ecAdapter)];
232 12
                $this->publicKeys = [PublicKeyFactory::fromHex($witness[1], $this->ecAdapter)];
233 4
            }
234 80
        } else if ($type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
235 18
            if (isset($witnesses[$this->nInput])) {
236 18
                $witness = $witnesses[$this->nInput];
237 18
                $witCount = count($witnesses[$this->nInput]);
238 18
                if ($witCount > 0) {
239 18
                    $witnessScript = new Script($witness[$witCount - 1]);
240 18
                    $vWitness = $witness->all();
241 18
                    if (count($vWitness) > 1) {
242 18
                        $vWitness = array_slice($witness->all(), 0, -1);
243 6
                    }
244
245 18
                    $witnessType = $this->classifier->classify($witnessScript);
246 18
                    $this->extractFromValues($witnessType, $witnessScript, $vWitness, 1);
247 18
                    $this->witnessScript = $witnessScript;
248 6
                }
249 6
            }
250 6
        }
251
252 84
        return $this;
253
    }
254
255
    /**
256
     * @param ScriptInterface $scriptCode
257
     * @param int $sigVersion
258
     * @return BufferInterface
259
     */
260
    public function calculateSigHash(ScriptInterface $scriptCode, $sigVersion)
261 84
    {
262
        if ($sigVersion === 1) {
263 84
            $hasher = new V1Hasher($this->tx, $this->txOut->getValue());
264 30
        } else {
265 10
            $hasher = new Hasher($this->tx);
266 54
        }
267
268
        return $hasher->calculate($scriptCode, $this->nInput, $this->sigHashType);
269 84
    }
270
271 84
    /**
272 84
     * @param PrivateKeyInterface $key
273 84
     * @param ScriptInterface $scriptCode
274 28
     * @param int $sigVersion
275 28
     * @return TransactionSignature
276 84
     */
277 84
    public function calculateSignature(PrivateKeyInterface $key, ScriptInterface $scriptCode, $sigVersion)
278 28
    {
279 28
        $hash = $this->calculateSigHash($scriptCode, $sigVersion);
280 56
        return new TransactionSignature(
281 28
            $this->ecAdapter,
282 28
            $this->ecAdapter->sign(
283 84
                $hash,
284 28
                $key,
285
                new Rfc6979(
286
                    $this->ecAdapter,
287
                    $key,
288
                    $hash,
289
                    'sha256'
290 78
                )
291
            ),
292 78
            $this->sigHashType
293
        );
294
    }
295
296
    /**
297
     * @return bool
298
     */
299
    public function isFullySigned()
300
    {
301
        return $this->requiredSigs !== 0 && $this->requiredSigs === count($this->signatures);
302
    }
303
304
    /**
305 84
     * The function only returns true when $scriptPubKey could be classified
306
     *
307 84
     * @param PrivateKeyInterface $key
308 84
     * @param ScriptInterface $scriptPubKey
309 84
     * @param string $outputType
310
     * @param BufferInterface[] $results
311
     * @param int $sigVersion
312
     * @return bool
313 84
     */
314
    private function doSignature(PrivateKeyInterface $key, ScriptInterface $scriptPubKey, &$outputType, array &$results, $sigVersion = 0)
315 12
    {
316 12
        $return = [];
317 12
        $outputType = $this->classifier->classify($scriptPubKey, $return);
318 12
        if ($outputType === OutputClassifier::UNKNOWN) {
319 4
            throw new \RuntimeException('Cannot sign unknown script type');
320
        }
321 12
322
        if ($outputType === OutputClassifier::PAYTOPUBKEY) {
323
            /** @var BufferInterface $return */
324 72
            $results[] = $return;
325
            $this->requiredSigs = 1;
326 42
            if ($key->getPublicKey()->getBuffer()->equals($return)) {
0 ignored issues
show
Documentation introduced by
$return is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
327 42
                $this->signatures[0] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
328 42
            }
329 36
330 36
            return true;
331 12
        }
332
333 42
        if ($outputType === OutputClassifier::PAYTOPUBKEYHASH) {
334
            /** @var BufferInterface $return */
335
            $results[] = $return;
336 48
            $this->requiredSigs = 1;
337 30
            if ($key->getPublicKey()->getPubKeyHash()->equals($return)) {
0 ignored issues
show
Documentation introduced by
$return is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
338 30
                $this->signatures[0] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
339 30
                $this->publicKeys[0] = $key->getPublicKey();
340
            }
341 30
342 30
            return true;
343 30
        }
344 30
345 30
        if ($outputType === OutputClassifier::MULTISIG) {
346 10
            $info = new Multisig($scriptPubKey);
347 10
            $this->publicKeys = $info->getKeys();
348
            $this->requiredSigs = $info->getKeyCount();
349 30
350
            $myKey = $key->getPublicKey()->getBuffer();
351
            foreach ($info->getKeys() as $keyIdx => $publicKey) {
352 42
                $results[] = $publicKey->getBuffer();
353
                if ($publicKey->getBuffer()->equals($myKey)) {
0 ignored issues
show
Documentation introduced by
$myKey is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
354 24
                    $this->signatures[$keyIdx] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
355 24
                }
356 24
            }
357
358
            return true;
359 30
        }
360
361 12
        if ($outputType === OutputClassifier::PAYTOSCRIPTHASH) {
362 12
            /** @var BufferInterface $scriptHash */
363 12
            $scriptHash = $return;
364
            $results[] = $scriptHash;
365 12
            return true;
366 12
        }
367 12
368 12
        if ($outputType === OutputClassifier::WITNESS_V0_KEYHASH) {
369 4
            /** @var BufferInterface $pubKeyHash */
370
            $pubKeyHash = $return;
371 12
            $results[] = $pubKeyHash;
372
            $this->requiredSigs = 1;
373
374 18
            if ($pubKeyHash->getBinary() === $key->getPublicKey()->getPubKeyHash()->getBinary()) {
375
                $script = ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
376 18
                $this->signatures[0] = $this->calculateSignature($key, $script, 1);
377 18
                $this->publicKeys[0] = $key->getPublicKey();
378
            }
379 18
380
            return true;
381
        }
382
383
        if ($outputType === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
384
            /** @var BufferInterface $scriptHash */
385
            $scriptHash = $return;
386
            $results[] = $scriptHash;
387
388
            return true;
389
        }
390
391 84
        return false;
392
    }
393
394 84
    /**
395 84
     * @param PrivateKeyInterface $key
396 84
     * @param ScriptInterface|null $redeemScript
397
     * @param ScriptInterface|null $witnessScript
398 84
     * @return bool
399 24
     */
400
    public function sign(PrivateKeyInterface $key, ScriptInterface $redeemScript = null, ScriptInterface $witnessScript = null)
401 24
    {
402
        /** @var BufferInterface[] $return */
403
        $type = null;
404
        $return = [];
405 24
        $solved = $this->doSignature($key, $this->txOut->getScript(), $type, $return, 0);
406
407
        if ($solved && $type === OutputClassifier::PAYTOSCRIPTHASH) {
408
            $redeemScriptBuffer = $return[0];
409 24
410 24
            if (!$redeemScript instanceof ScriptInterface) {
411 24
                throw new \InvalidArgumentException('Must provide redeem script for P2SH');
412 24
            }
413 8
414 8
            if (!$redeemScript->getScriptHash()->equals($redeemScriptBuffer)) {
0 ignored issues
show
Documentation introduced by
$redeemScriptBuffer is of type object<BitWasp\Buffertools\BufferInterface>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
415
                throw new \InvalidArgumentException("Incorrect redeem script - hash doesn't match");
416 84
            }
417 12
418 12
            $results = []; // ???
419 12
            $solved = $solved && $this->doSignature($key, $redeemScript, $type, $results, 0) && $type !== OutputClassifier::PAYTOSCRIPTHASH;
420 12
            if ($solved) {
421 12
                $this->redeemScript = $redeemScript;
422 76
            }
423 18
        }
424
425 18
        if ($solved && $type === OutputClassifier::WITNESS_V0_KEYHASH) {
426
            $pubKeyHash = $return[0];
427
            $witnessScript = ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
428
            $subType = null;
429 18
            $subResults = [];
430
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, 1);
431
        } else if ($solved && $type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
432
            $scriptHash = $return[0];
433 18
434 18
            if (!$witnessScript instanceof ScriptInterface) {
435
                throw new \InvalidArgumentException('Must provide witness script for witness v0 scripthash');
436 18
            }
437 18
438 18
            if (!Hash::sha256($witnessScript->getBuffer())->getBinary() === $scriptHash->getBinary()) {
439 18
                throw new \InvalidArgumentException("Incorrect witness script - hash doesn't match");
440
            }
441 18
442 18
            $subType = null;
443 6
            $subResults = [];
444 6
445
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, 1)
446 84
                && $subType !== OutputClassifier::PAYTOSCRIPTHASH
447
                && $subType !== OutputClassifier::WITNESS_V0_SCRIPTHASH
448
                && $subType !== OutputClassifier::WITNESS_V0_KEYHASH;
449
450
            if ($solved) {
451
                $this->witnessScript = $witnessScript;
452
            }
453
        }
454 84
455
        return $solved;
456 84
    }
457
458
    /**
459
     * @param string $outputType
460 84
     * @param $answer
461 12
     * @return bool
462 12
     */
463
    private function serializeSimpleSig($outputType, &$answer)
464
    {
465 72
        if ($outputType === OutputClassifier::UNKNOWN) {
466 30
            throw new \RuntimeException('Cannot sign unknown script type');
467 30
        }
468
469
        if ($outputType === OutputClassifier::PAYTOPUBKEY && $this->isFullySigned()) {
470 48
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer()]), new ScriptWitness([]));
471 30
            return true;
472 30
        }
473 30
474 30
        if ($outputType === OutputClassifier::PAYTOPUBKEYHASH && $this->isFullySigned()) {
475 30
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]), new ScriptWitness([]));
476 10
            return true;
477 10
        }
478
479 30
        if ($outputType === OutputClassifier::MULTISIG) {
480 30
            $sequence = [Opcodes::OP_0];
481
            $nPubKeys = count($this->publicKeys);
482
            for ($i = 0; $i < $nPubKeys; $i++) {
483 42
                if (isset($this->signatures[$i])) {
484
                    $sequence[] = $this->signatures[$i]->getBuffer();
485
                }
486
            }
487
488
            $answer = new SigValues(ScriptFactory::sequence($sequence), new ScriptWitness([]));
489 84
            return true;
490
        }
491 84
492 84
        return false;
493 84
    }
494 6
495 6
    /**
496 2
     * @return SigValues
497
     */
498
    public function serializeSignatures()
499 84
    {
500
        static $emptyScript = null;
501
        static $emptyWitness = null;
502 84
        if (is_null($emptyScript) || is_null($emptyWitness)) {
503 84
            $emptyScript = new Script();
504
            $emptyWitness = new ScriptWitness([]);
505 84
        }
506 84
507 24
        /** @var BufferInterface[] $return */
508 24
        $outputType = $this->classifier->classify($this->txOut->getScript());
509 24
510 8
        /** @var SigValues $answer */
511
        $answer = new SigValues($emptyScript, $emptyWitness);
512 84
        $serialized = $this->serializeSimpleSig($outputType, $answer);
513 12
514 76
        $p2sh = false;
515 18
        if (!$serialized && $outputType === OutputClassifier::PAYTOSCRIPTHASH) {
516 18
            $p2sh = true;
517
            $outputType = $this->classifier->classify($this->redeemScript);
518 18
            $serialized = $this->serializeSimpleSig($outputType, $answer);
519 18
        }
520 18
521 18
        if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_KEYHASH) {
522 6
            $answer = new SigValues($emptyScript, new ScriptWitness([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]));
523
        } else if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
524 18
            $outputType = $this->classifier->classify($this->witnessScript);
525 18
            $serialized = $this->serializeSimpleSig($outputType, $answer);
526 6
527 6
            if ($serialized) {
528
                $data = [];
529 84
                foreach ($answer->getScriptSig()->getScriptParser()->decode() as $o) {
530 24
                    $data[] = $o->getData();
531 24
                }
532 24
533 8
                $data[] = $this->witnessScript->getBuffer();
534 8
                $answer = new SigValues($emptyScript, new ScriptWitness($data));
535
            }
536 84
        }
537
538
        if ($p2sh) {
539
            $answer = new SigValues(
540
                ScriptFactory::create($answer->getScriptSig()->getBuffer())->push($this->redeemScript->getBuffer())->getScript(),
541
                $answer->getScriptWitness()
542
            );
543
        }
544
545
        return $answer;
546
    }
547
}
548