Completed
Pull Request — master (#383)
by thomas
66:10 queued 63:26
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 TransactionSignatureInterface[] $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 84
        if ($type === OutputClassifier::PAYTOPUBKEYHASH || $type === OutputClassifier::PAYTOPUBKEY || $type === OutputClassifier::MULTISIG) {
195 42
            $values = [];
196 42
            foreach ($scriptSig->getScriptParser()->decode() as $o) {
197 18
                $values[] = $o->getData();
198 14
            }
199
200 42
            $this->extractFromValues($type, $scriptPubKey, $values, 0);
201 14
        }
202
203 84
        if ($type === OutputClassifier::PAYTOSCRIPTHASH) {
204 24
            $decodeSig = $scriptSig->getScriptParser()->decode();
205 24
            if (count($decodeSig) > 0) {
206 18
                $redeemScript = new Script(end($decodeSig)->getData());
207 18
                $type = $this->classifier->classify($redeemScript);
208 18
                if (count($decodeSig) > 1) {
209 6
                    $decodeSig = array_slice($decodeSig, 0, -1);
210 2
                }
211
212 18
                $internalSig = [];
213 18
                foreach ($decodeSig as $operation) {
214 18
                    $internalSig[] = $operation->getData();
215 6
                }
216
217 18
                $this->redeemScript = $redeemScript;
218 18
                $this->extractFromValues($type, $redeemScript, $internalSig, 0);
219 6
            }
220 8
        }
221
222 84
        $witnesses = $this->tx->getWitnesses();
223 84
        if ($type === OutputClassifier::WITNESS_V0_KEYHASH) {
224 12
            $this->requiredSigs = 1;
225 12
            if (isset($witnesses[$this->nInput])) {
226 12
                $witness = $witnesses[$this->nInput];
227 12
                $this->signatures = [TransactionSignatureFactory::fromHex($witness[0], $this->ecAdapter)];
228 12
                $this->publicKeys = [PublicKeyFactory::fromHex($witness[1], $this->ecAdapter)];
229 4
            }
230 80
        } else if ($type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
231 18
            if (isset($witnesses[$this->nInput])) {
232 18
                $witness = $witnesses[$this->nInput];
233 18
                $witCount = count($witnesses[$this->nInput]);
234 18
                if ($witCount > 0) {
235 18
                    $witnessScript = new Script($witness[$witCount - 1]);
236 18
                    $vWitness = $witness->all();
237 18
                    if (count($vWitness) > 1) {
238 18
                        $vWitness = array_slice($witness->all(), 0, -1);
239 6
                    }
240
241 18
                    $type = $this->classifier->classify($witnessScript);
242 18
                    $this->extractFromValues($type, $witnessScript, $vWitness, 1);
243 18
                    $this->witnessScript = $witnessScript;
244 6
                }
245 6
            }
246 6
        }
247
248 84
        return $this;
249
    }
250
251
    /**
252
     * @param ScriptInterface $scriptCode
253
     * @param int $sigVersion
254
     * @return BufferInterface
255
     */
256 84
    public function calculateSigHash(ScriptInterface $scriptCode, $sigVersion)
257
    {
258 84
        if ($sigVersion === 1) {
259 30
            $hasher = new V1Hasher($this->tx, $this->txOut->getValue());
260 10
        } else {
261 54
            $hasher = new Hasher($this->tx);
262
        }
263
264 84
        return $hasher->calculate($scriptCode, $this->nInput, $this->sigHashType);
265
    }
266
267
    /**
268
     * @param PrivateKeyInterface $key
269
     * @param ScriptInterface $scriptCode
270
     * @param int $sigVersion
271
     * @return TransactionSignature
272
     */
273 84
    public function calculateSignature(PrivateKeyInterface $key, ScriptInterface $scriptCode, $sigVersion)
274
    {
275 84
        $hash = $this->calculateSigHash($scriptCode, $sigVersion);
276 84
        return new TransactionSignature(
277 84
            $this->ecAdapter,
278 84
            $this->ecAdapter->sign(
279 28
                $hash,
280 28
                $key,
281 84
                new Rfc6979(
282 84
                    $this->ecAdapter,
283 28
                    $key,
284 28
                    $hash,
285 56
                    'sha256'
286 28
                )
287 28
            ),
288 84
            $this->sigHashType
289 28
        );
290
    }
291
292
    /**
293
     * @return bool
294
     */
295 78
    public function isFullySigned()
296
    {
297 78
        return $this->requiredSigs !== 0 && $this->requiredSigs === count($this->signatures);
298
    }
299
300
    /**
301
     * The function only returns true when $scriptPubKey could be classified
302
     *
303
     * @param PrivateKeyInterface $key
304
     * @param ScriptInterface $scriptPubKey
305
     * @param string $outputType
306
     * @param BufferInterface[] $results
307
     * @param int $sigVersion
308
     * @return bool
309
     */
310 84
    private function doSignature(PrivateKeyInterface $key, ScriptInterface $scriptPubKey, &$outputType, array &$results, $sigVersion = 0)
311
    {
312 84
        $return = [];
313 84
        $outputType = $this->classifier->classify($scriptPubKey, $return);
314 84
        if ($outputType === OutputClassifier::UNKNOWN) {
315
            throw new \RuntimeException('Cannot sign unknown script type');
316
        }
317
318 84
        if ($outputType === OutputClassifier::PAYTOPUBKEY) {
319
            /** @var BufferInterface $return */
320 12
            $results[] = $return;
321 12
            $this->requiredSigs = 1;
322 12
            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...
323 12
                $this->signatures[0] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
324 4
            }
325
326 12
            return true;
327
        }
328
329 72
        if ($outputType === OutputClassifier::PAYTOPUBKEYHASH) {
330
            /** @var BufferInterface $return */
331 42
            $results[] = $return;
332 42
            $this->requiredSigs = 1;
333 42
            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...
334 36
                $this->signatures[0] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
335 36
                $this->publicKeys[0] = $key->getPublicKey();
336 12
            }
337
338 42
            return true;
339
        }
340
341 48
        if ($outputType === OutputClassifier::MULTISIG) {
342 30
            $info = new Multisig($scriptPubKey);
343 30
            $this->publicKeys = $info->getKeys();
344 30
            $this->requiredSigs = $info->getKeyCount();
345
346 30
            $myKey = $key->getPublicKey()->getBuffer();
347 30
            foreach ($info->getKeys() as $keyIdx => $publicKey) {
348 30
                $results[] = $publicKey->getBuffer();
349 30
                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...
350 30
                    $this->signatures[$keyIdx] = $this->calculateSignature($key, $scriptPubKey, $sigVersion);
351 10
                }
352 10
            }
353
354 30
            return true;
355
        }
356
357 42
        if ($outputType === OutputClassifier::PAYTOSCRIPTHASH) {
358
            /** @var BufferInterface $scriptHash */
359 24
            $scriptHash = $return;
360 24
            $results[] = $scriptHash;
361 24
            return true;
362
        }
363
364 30
        if ($outputType === OutputClassifier::WITNESS_V0_KEYHASH) {
365
            /** @var BufferInterface $pubKeyHash */
366 12
            $pubKeyHash = $return;
367 12
            $results[] = $pubKeyHash;
368 12
            $this->requiredSigs = 1;
369
370 12
            if ($pubKeyHash->getBinary() === $key->getPublicKey()->getPubKeyHash()->getBinary()) {
371 12
                $script = ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
372 12
                $this->signatures[0] = $this->calculateSignature($key, $script, 1);
373 12
                $this->publicKeys[0] = $key->getPublicKey();
374 4
            }
375
376 12
            return true;
377
        }
378
379 18
        if ($outputType === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
380
            /** @var BufferInterface $scriptHash */
381 18
            $scriptHash = $return;
382 18
            $results[] = $scriptHash;
383
384 18
            return true;
385
        }
386
387
        return false;
388
    }
389
390
    /**
391
     * @param PrivateKeyInterface $key
392
     * @param ScriptInterface|null $redeemScript
393
     * @param ScriptInterface|null $witnessScript
394
     * @return bool
395
     */
396 84
    public function sign(PrivateKeyInterface $key, ScriptInterface $redeemScript = null, ScriptInterface $witnessScript = null)
397
    {
398
        /** @var BufferInterface[] $return */
399 84
        $type = null;
400 84
        $return = [];
401 84
        $solved = $this->doSignature($key, $this->txOut->getScript(), $type, $return, 0);
402
403 84
        if ($solved && $type === OutputClassifier::PAYTOSCRIPTHASH) {
404 24
            $redeemScriptBuffer = $return[0];
405 24
            if (!$redeemScript instanceof ScriptInterface) {
406
                throw new \InvalidArgumentException('Must provide redeem script for P2SH');
407
            }
408
409 24
            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...
410
                throw new \InvalidArgumentException("Incorrect redeem script - hash doesn't match");
411
            }
412
413 24
            $results = []; // ???
414 24
            $solved = $solved && $this->doSignature($key, $redeemScript, $type, $results, 0) && $type !== OutputClassifier::PAYTOSCRIPTHASH;
415 24
            if ($solved) {
416 24
                $this->redeemScript = $redeemScript;
417 8
            }
418 8
        }
419
420 84
        if ($solved && $type === OutputClassifier::WITNESS_V0_KEYHASH) {
421 12
            $pubKeyHash = $return[0];
422 12
            $witnessScript = ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
423 12
            $subType = null;
424 12
            $subResults = [];
425 12
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, 1);
426 76
        } else if ($solved && $type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
427 18
            $scriptHash = $return[0];
428
429 18
            if (!$witnessScript instanceof ScriptInterface) {
430
                throw new \InvalidArgumentException('Must provide witness script for witness v0 scripthash');
431
            }
432
433 18
            if (!Hash::sha256($witnessScript->getBuffer())->getBinary() === $scriptHash->getBinary()) {
434
                throw new \InvalidArgumentException("Incorrect witness script - hash doesn't match");
435
            }
436
437 18
            $subType = null;
438 18
            $subResults = [];
439
440 18
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, 1)
441 18
                && $subType !== OutputClassifier::PAYTOSCRIPTHASH
442 18
                && $subType !== OutputClassifier::WITNESS_V0_SCRIPTHASH
443 18
                && $subType !== OutputClassifier::WITNESS_V0_KEYHASH;
444
445 18
            if ($solved) {
446 18
                $this->witnessScript = $witnessScript;
447 6
            }
448 6
        }
449
450 84
        return $solved;
451
    }
452
453
    /**
454
     * @param string $outputType
455
     * @param $answer
456
     * @return bool
457
     */
458 84
    private function serializeSimpleSig($outputType, &$answer)
459
    {
460 84
        if ($outputType === OutputClassifier::UNKNOWN) {
461
            throw new \RuntimeException('Cannot sign unknown script type');
462
        }
463
464 84
        if ($outputType === OutputClassifier::PAYTOPUBKEY && $this->isFullySigned()) {
465 12
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer()]), new ScriptWitness([]));
466 12
            return true;
467
        }
468
469 72
        if ($outputType === OutputClassifier::PAYTOPUBKEYHASH && $this->isFullySigned()) {
470 30
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]), new ScriptWitness([]));
471 30
            return true;
472
        }
473
474 48
        if ($outputType === OutputClassifier::MULTISIG) {
475 30
            $sequence = [Opcodes::OP_0];
476 30
            $nPubKeys = count($this->publicKeys);
477 30
            for ($i = 0; $i < $nPubKeys; $i++) {
478 30
                if (isset($this->signatures[$i])) {
479 30
                    $sequence[] = $this->signatures[$i]->getBuffer();
480 10
                }
481 10
            }
482
483 30
            $answer = new SigValues(ScriptFactory::sequence($sequence), new ScriptWitness([]));
484 30
            return true;
485
        }
486
487 42
        return false;
488
    }
489
490
    /**
491
     * @return SigValues
492
     */
493 84
    public function serializeSignatures()
494
    {
495 84
        static $emptyScript = null;
496 84
        static $emptyWitness = null;
497 84
        if (is_null($emptyScript) || is_null($emptyWitness)) {
498 6
            $emptyScript = new Script();
499 6
            $emptyWitness = new ScriptWitness([]);
500 2
        }
501
502
        /** @var BufferInterface[] $return */
503 84
        $outputType = $this->classifier->classify($this->txOut->getScript());
504
505
        /** @var SigValues $answer */
506 84
        $answer = new SigValues($emptyScript, $emptyWitness);
507 84
        $serialized = $this->serializeSimpleSig($outputType, $answer);
508
509 84
        $p2sh = false;
510 84
        if (!$serialized && $outputType === OutputClassifier::PAYTOSCRIPTHASH) {
511 24
            $p2sh = true;
512 24
            $outputType = $this->classifier->classify($this->redeemScript);
513 24
            $serialized = $this->serializeSimpleSig($outputType, $answer);
514 8
        }
515
516 84
        if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_KEYHASH) {
517 12
            $answer = new SigValues($emptyScript, new ScriptWitness([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]));
518 76
        } else if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
519 18
            $outputType = $this->classifier->classify($this->witnessScript);
520 18
            $serialized = $this->serializeSimpleSig($outputType, $answer);
521 18
            if ($serialized) {
522 18
                $data = [];
523 18
                foreach ($answer->getScriptSig()->getScriptParser()->decode() as $o) {
524 18
                    $data[] = $o->getData();
525 6
                }
526
527 18
                $data[] = $this->witnessScript->getBuffer();
528 18
                $answer = new SigValues($emptyScript, new ScriptWitness($data));
529 6
            }
530 6
        }
531
532 84
        if ($p2sh) {
533 24
            $answer = new SigValues(
534 24
                ScriptFactory::create($answer->getScriptSig()->getBuffer())->push($this->redeemScript->getBuffer())->getScript(),
535 24
                $answer->getScriptWitness()
536 8
            );
537 8
        }
538
539 84
        return $answer;
540
    }
541
}
542