Completed
Pull Request — master (#384)
by thomas
66:15 queued 63:52
created

InputSigner::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 4
dl 0
loc 12
ccs 10
cts 10
cp 1
crap 1
rs 9.4285
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 TransactionSignatureInterface[]
68
     */
69
    private $signatures = [];
70
71
    /**
72
     * @var int
73
     */
74
    private $requiredSigs = 0;
75
76
    /**
77
     * @var OutputClassifier
78
     */
79
    private $classifier;
80
81
    /**
82
     * TxInputSigning constructor.
83
     * @param EcAdapterInterface $ecAdapter
84
     * @param TransactionInterface $tx
85
     * @param int $nInput
86
     * @param TransactionOutputInterface $txOut
87
     */
88 84
    public function __construct(EcAdapterInterface $ecAdapter, TransactionInterface $tx, $nInput, TransactionOutputInterface $txOut)
89
    {
90 84
        $this->ecAdapter = $ecAdapter;
91 84
        $this->tx = $tx;
92 84
        $this->nInput = $nInput;
93 84
        $this->txOut = $txOut;
94 84
        $this->classifier = new OutputClassifier();
95 84
        $this->publicKeys = [];
96 84
        $this->signatures = [];
97
98 84
        $this->extractSignatures();
99 84
    }
100
101
    /**
102
     * @param int $sigVersion
103
     * @param TransactionSignatureInterface[] $stack
104
     * @param ScriptInterface $scriptCode
105
     * @return \SplObjectStorage
106
     */
107 24
    private function sortMultiSigs($sigVersion, $stack, ScriptInterface $scriptCode)
108
    {
109 24
        if ($sigVersion === 1) {
110 12
            $hasher = new V1Hasher($this->tx, $this->txOut->getValue());
111 8
        } else {
112 12
            $hasher = new Hasher($this->tx);
113
        }
114
115 24
        $sigSort = new SignatureSort($this->ecAdapter);
116 24
        $sigs = new \SplObjectStorage;
117
118 24
        foreach ($stack as $txSig) {
119
            $hash = $hasher->calculate($scriptCode, $this->nInput, $txSig->getHashType());
120
            $linked = $sigSort->link([$txSig->getSignature()], $this->publicKeys, $hash);
121
122
            foreach ($this->publicKeys as $key) {
123
                if ($linked->contains($key)) {
124
                    $sigs[$key] = $txSig;
125
                }
126
            }
127 16
        }
128
129 24
        return $sigs;
130
    }
131
132
    /**
133
     * @param string $type
134
     * @param ScriptInterface $scriptCode
135
     * @param BufferInterface[] $stack
136
     * @param int $sigVersion
137
     * @return string
138
     */
139 72
    public function extractFromValues($type, ScriptInterface $scriptCode, array $stack, $sigVersion)
140
    {
141 72
        $size = count($stack);
142 72
        if ($type === OutputClassifier::PAYTOPUBKEYHASH) {
143 30
            $this->requiredSigs = 1;
144 30
            if ($size === 2) {
145 12
                $this->signatures = [TransactionSignatureFactory::fromHex($stack[0], $this->ecAdapter)];
146 12
                $this->publicKeys = [PublicKeyFactory::fromHex($stack[1], $this->ecAdapter)];
147 8
            }
148 20
        }
149
150 72
        if ($type === OutputClassifier::PAYTOPUBKEY) {
151 12
            $this->requiredSigs = 1;
152 12
            if ($size === 1) {
153 6
                $this->signatures = [TransactionSignatureFactory::fromHex($stack[0], $this->ecAdapter)];
154 4
            }
155 8
        }
156
157 72
        if ($type === OutputClassifier::MULTISIG) {
158 24
            $info = new Multisig($scriptCode);
159 24
            $this->requiredSigs = $info->getRequiredSigCount();
160 24
            $this->publicKeys = $info->getKeys();
161
162 24
            if ($size > 1) {
163 24
                $vars = [];
164 24
                foreach (array_slice($stack, 1, -1) as $sig) {
165
                    $vars[] = TransactionSignatureFactory::fromHex($sig, $this->ecAdapter);
166 16
                }
167
168 24
                $sigs = $this->sortMultiSigs($sigVersion, $vars, $scriptCode);
169
170 24
                foreach ($this->publicKeys as $idx => $key) {
171 24
                    $this->signatures[$idx] = isset($sigs[$key]) ? $sigs[$key]->getBuffer() : null;
172 16
                }
173 16
            }
174 16
        }
175
176 72
        return $type;
177
    }
178
179
    /**
180
     * @return $this
181
     */
182 84
    public function extractSignatures()
183
    {
184 84
        $scriptPubKey = $this->txOut->getScript();
185 84
        $scriptSig = $this->tx->getInput($this->nInput)->getScript();
186 84
        $type = $this->classifier->classify($scriptPubKey);
187
188 84
        if ($type === OutputClassifier::PAYTOPUBKEYHASH || $type === OutputClassifier::PAYTOPUBKEY || $type === OutputClassifier::MULTISIG) {
189 42
            $values = [];
190 42
            foreach ($scriptSig->getScriptParser()->decode() as $o) {
191 18
                $values[] = $o->getData();
192 28
            }
193
194 66
            $this->extractFromValues($type, $scriptPubKey, $values, 0);
195 28
        }
196
197 84
        if ($type === OutputClassifier::PAYTOSCRIPTHASH) {
198 24
            $decodeSig = $scriptSig->getScriptParser()->decode();
199 24
            if (count($decodeSig) > 0) {
200 18
                $redeemScript = new Script(end($decodeSig)->getData());
201 18
                $p2shType = $this->classifier->classify($redeemScript);
202
203 18
                if (count($decodeSig) > 1) {
204 6
                    $decodeSig = array_slice($decodeSig, 0, -1);
205 4
                }
206
207 18
                $internalSig = [];
208 18
                foreach ($decodeSig as $operation) {
209 18
                    $internalSig[] = $operation->getData();
210 12
                }
211
212 18
                $this->redeemScript = $redeemScript;
213 18
                $this->extractFromValues($p2shType, $redeemScript, $internalSig, 0);
214
215 18
                $type = $p2shType;
216 12
            }
217 16
        }
218
219 84
        $witnesses = $this->tx->getWitnesses();
220 84
        if ($type === OutputClassifier::WITNESS_V0_KEYHASH) {
221 12
            $this->requiredSigs = 1;
222 12
            if (isset($witnesses[$this->nInput])) {
223 12
                $witness = $witnesses[$this->nInput];
224 12
                $this->signatures = [TransactionSignatureFactory::fromHex($witness[0], $this->ecAdapter)];
225 12
                $this->publicKeys = [PublicKeyFactory::fromHex($witness[1], $this->ecAdapter)];
226 8
            }
227 82
        } else if ($type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
228 18
            if (isset($witnesses[$this->nInput])) {
229 18
                $witness = $witnesses[$this->nInput];
230 18
                $witCount = count($witnesses[$this->nInput]);
231 18
                if ($witCount > 0) {
232 18
                    $witnessScript = new Script($witness[$witCount - 1]);
233 18
                    $vWitness = $witness->all();
234 18
                    if (count($vWitness) > 1) {
235 18
                        $vWitness = array_slice($witness->all(), 0, -1);
236 12
                    }
237
238 18
                    $witnessType = $this->classifier->classify($witnessScript);
239 18
                    $this->extractFromValues($witnessType, $witnessScript, $vWitness, 1);
240 18
                    $this->witnessScript = $witnessScript;
241 12
                }
242 12
            }
243 12
        }
244
245 84
        return $this;
246
    }
247
248
    /**
249
     * @param ScriptInterface $scriptCode
250
     * @param int $sigHashType
251
     * @param int $sigVersion
252
     * @return BufferInterface
253
     */
254 84
    public function calculateSigHash(ScriptInterface $scriptCode, $sigHashType, $sigVersion)
255
    {
256 84
        if ($sigVersion === 1) {
257 30
            $hasher = new V1Hasher($this->tx, $this->txOut->getValue());
258 20
        } else {
259 54
            $hasher = new Hasher($this->tx);
260
        }
261
262 84
        return $hasher->calculate($scriptCode, $this->nInput, $sigHashType);
263
    }
264
265
    /**
266
     * @param PrivateKeyInterface $key
267
     * @param ScriptInterface $scriptCode
268
     * @param int $sigHashType
269
     * @param int $sigVersion
270
     * @return TransactionSignature
271
     */
272 84
    public function calculateSignature(PrivateKeyInterface $key, ScriptInterface $scriptCode, $sigHashType, $sigVersion)
273
    {
274 84
        $hash = $this->calculateSigHash($scriptCode, $sigHashType, $sigVersion);
275 84
        return new TransactionSignature(
276 84
            $this->ecAdapter,
277 84
            $this->ecAdapter->sign(
278 56
                $hash,
279 56
                $key,
280 84
                new Rfc6979(
281 84
                    $this->ecAdapter,
282 56
                    $key,
283 56
                    $hash,
284 28
                    'sha256'
285 56
                )
286 56
            ),
287
            $sigHashType
288 56
        );
289
    }
290
291
    /**
292
     * @return bool
293
     */
294 78
    public function isFullySigned()
295
    {
296 78
        return $this->requiredSigs !== 0 && $this->requiredSigs === count($this->signatures);
297
    }
298
299
    /**
300
     * The function only returns true when $scriptPubKey could be classified
301
     *
302
     * @param PrivateKeyInterface $key
303
     * @param ScriptInterface $scriptPubKey
304
     * @param string $outputType
305
     * @param BufferInterface[] $results
306
     * @param int $sigHashType
307
     * @param int $sigVersion
308
     * @return bool
309
     */
310 84
    private function doSignature(PrivateKeyInterface $key, ScriptInterface $scriptPubKey, &$outputType, array &$results, $sigHashType, $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, $sigHashType, $sigVersion);
324 8
            }
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, $sigHashType, $sigVersion);
335 36
                $this->publicKeys[0] = $key->getPublicKey();
336 24
            }
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, $sigHashType, $sigVersion);
351 20
                }
352 20
            }
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, $sigHashType, 1);
373 12
                $this->publicKeys[0] = $key->getPublicKey();
374 8
            }
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
     * @param int $sigHashType
395
     * @return bool
396
     */
397 84
    public function sign(PrivateKeyInterface $key, ScriptInterface $redeemScript = null, ScriptInterface $witnessScript = null, $sigHashType = SigHashInterface::ALL)
398
    {
399
        /** @var BufferInterface[] $return */
400 84
        $type = null;
401 84
        $return = [];
402 84
        $solved = $this->doSignature($key, $this->txOut->getScript(), $type, $return, $sigHashType, 0);
403
404 84
        if ($solved && $type === OutputClassifier::PAYTOSCRIPTHASH) {
405 24
            $redeemScriptBuffer = $return[0];
406
407 24
            if (!$redeemScript instanceof ScriptInterface) {
408
                throw new \InvalidArgumentException('Must provide redeem script for P2SH');
409
            }
410
411 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...
412
                throw new \InvalidArgumentException("Incorrect redeem script - hash doesn't match");
413
            }
414
415 24
            $results = []; // ???
416 24
            $solved = $solved && $this->doSignature($key, $redeemScript, $type, $results, $sigHashType, 0) && $type !== OutputClassifier::PAYTOSCRIPTHASH;
417 24
            if ($solved) {
418 24
                $this->redeemScript = $redeemScript;
419 16
            }
420 16
        }
421
422 84
        if ($solved && $type === OutputClassifier::WITNESS_V0_KEYHASH) {
423 12
            $pubKeyHash = $return[0];
424 12
            $witnessScript = ScriptFactory::sequence([Opcodes::OP_DUP, Opcodes::OP_HASH160, $pubKeyHash, Opcodes::OP_EQUALVERIFY, Opcodes::OP_CHECKSIG]);
425 12
            $subType = null;
426 12
            $subResults = [];
427 12
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, $sigHashType, 1);
428 80
        } else if ($solved && $type === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
429 18
            $scriptHash = $return[0];
430
431 18
            if (!$witnessScript instanceof ScriptInterface) {
432
                throw new \InvalidArgumentException('Must provide witness script for witness v0 scripthash');
433
            }
434
435 18
            if (!Hash::sha256($witnessScript->getBuffer())->getBinary() === $scriptHash->getBinary()) {
436
                throw new \InvalidArgumentException("Incorrect witness script - hash doesn't match");
437
            }
438
439 18
            $subType = null;
440 18
            $subResults = [];
441
442 18
            $solved = $solved && $this->doSignature($key, $witnessScript, $subType, $subResults, $sigHashType, 1)
443 18
                && $subType !== OutputClassifier::PAYTOSCRIPTHASH
444 18
                && $subType !== OutputClassifier::WITNESS_V0_SCRIPTHASH
445 18
                && $subType !== OutputClassifier::WITNESS_V0_KEYHASH;
446
447 18
            if ($solved) {
448 18
                $this->witnessScript = $witnessScript;
449 12
            }
450 12
        }
451
452 84
        return $solved;
453
    }
454
455
    /**
456
     * @param string $outputType
457
     * @param $answer
458
     * @return bool
459
     */
460 84
    private function serializeSimpleSig($outputType, &$answer)
461
    {
462 84
        if ($outputType === OutputClassifier::UNKNOWN) {
463
            throw new \RuntimeException('Cannot sign unknown script type');
464
        }
465
466 84
        if ($outputType === OutputClassifier::PAYTOPUBKEY && $this->isFullySigned()) {
467 12
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer()]), new ScriptWitness([]));
468 12
            return true;
469
        }
470
471 72
        if ($outputType === OutputClassifier::PAYTOPUBKEYHASH && $this->isFullySigned()) {
472 30
            $answer = new SigValues(ScriptFactory::sequence([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]), new ScriptWitness([]));
473 30
            return true;
474
        }
475
476 48
        if ($outputType === OutputClassifier::MULTISIG) {
477 30
            $sequence = [Opcodes::OP_0];
478 30
            $nPubKeys = count($this->publicKeys);
479 30
            for ($i = 0; $i < $nPubKeys; $i++) {
480 30
                if (isset($this->signatures[$i])) {
481 30
                    $sequence[] = $this->signatures[$i]->getBuffer();
482 20
                }
483 20
            }
484
485 30
            $answer = new SigValues(ScriptFactory::sequence($sequence), new ScriptWitness([]));
486 30
            return true;
487
        }
488
489 42
        return false;
490
    }
491
492
    /**
493
     * @return SigValues
494
     */
495 84
    public function serializeSignatures()
496
    {
497 84
        static $emptyScript = null;
498 84
        static $emptyWitness = null;
499 84
        if (is_null($emptyScript) || is_null($emptyWitness)) {
500 6
            $emptyScript = new Script();
501 6
            $emptyWitness = new ScriptWitness([]);
502 4
        }
503
504
        /** @var BufferInterface[] $return */
505 84
        $outputType = $this->classifier->classify($this->txOut->getScript());
506
507
        /** @var SigValues $answer */
508 84
        $answer = new SigValues($emptyScript, $emptyWitness);
509 84
        $serialized = $this->serializeSimpleSig($outputType, $answer);
510
511 84
        $p2sh = false;
512 84
        if (!$serialized && $outputType === OutputClassifier::PAYTOSCRIPTHASH) {
513 24
            $p2sh = true;
514 24
            $outputType = $this->classifier->classify($this->redeemScript);
515 24
            $serialized = $this->serializeSimpleSig($outputType, $answer);
516 16
        }
517
518 84
        if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_KEYHASH) {
519 12
            $answer = new SigValues($emptyScript, new ScriptWitness([$this->signatures[0]->getBuffer(), $this->publicKeys[0]->getBuffer()]));
520 80
        } else if (!$serialized && $outputType === OutputClassifier::WITNESS_V0_SCRIPTHASH) {
521 18
            $outputType = $this->classifier->classify($this->witnessScript);
522 18
            $serialized = $this->serializeSimpleSig($outputType, $answer);
523
524 18
            if ($serialized) {
525 18
                $data = [];
526 18
                foreach ($answer->getScriptSig()->getScriptParser()->decode() as $o) {
527 18
                    $data[] = $o->getData();
528 12
                }
529
530 18
                $data[] = $this->witnessScript->getBuffer();
531 18
                $answer = new SigValues($emptyScript, new ScriptWitness($data));
532 12
            }
533 12
        }
534
535 84
        if ($p2sh) {
536 24
            $answer = new SigValues(
537 24
                ScriptFactory::create($answer->getScriptSig()->getBuffer())->push($this->redeemScript->getBuffer())->getScript(),
538 24
                $answer->getScriptWitness()
539 16
            );
540 16
        }
541
542 84
        return $answer;
543
    }
544
}
545