Completed
Push — master ( 6cb3ab...d1eddc )
by thomas
127:23 queued 124:26
created

InputSigner::sign()   C

Complexity

Conditions 20
Paths 107

Size

Total Lines 57
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 20.432

Importance

Changes 0
Metric Value
cc 20
eloc 35
c 0
b 0
f 0
nc 107
nop 3
dl 0
loc 57
ccs 35
cts 39
cp 0.8974
crap 20.432
rs 6.2125

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