Completed
Pull Request — master (#591)
by thomas
30:58
created

Signer::get()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 6
nop 0
dl 0
loc 19
ccs 12
cts 12
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Transaction\Factory;
6
7
use BitWasp\Bitcoin\Bitcoin;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\EcSerializer;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
11
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Key\PublicKeySerializerInterface;
12
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Signature\DerSignatureSerializerInterface;
13
use BitWasp\Bitcoin\Serializer\Signature\TransactionSignatureSerializer;
14
use BitWasp\Bitcoin\Transaction\SignatureHash\SigHash;
15
use BitWasp\Bitcoin\Transaction\TransactionFactory;
16
use BitWasp\Bitcoin\Transaction\TransactionInterface;
17
use BitWasp\Bitcoin\Transaction\TransactionOutputInterface;
18
19
class Signer
20
{
21
    /**
22
     * @var EcAdapterInterface
23
     */
24
    private $ecAdapter;
25
26
    /**
27
     * @var TransactionInterface
28
     */
29
    private $tx;
30
31
    /**
32
     * @var TransactionSignatureSerializer
33
     */
34
    private $sigSerializer;
35
36
    /**
37
     * @var PublicKeySerializerInterface
38
     */
39
    private $pubKeySerializer;
40
41
    /**
42
     * @var bool
43
     */
44
    private $tolerateInvalidPublicKey = false;
45
46
    /**
47
     * @var bool
48
     */
49
    private $redeemBitcoinCash = false;
50
51
    /**
52
     * @var bool
53
     */
54
    private $padUnsignedMultisigs = false;
55
56
    /**
57
     * @var bool
58
     */
59
    private $allowComplexScripts = false;
60
61
    /**
62
     * @var InputSignerInterface[]
63
     */
64
    private $signatureCreator = [];
65
66
    /**
67
     * TxWitnessSigner constructor.
68
     * @param TransactionInterface $tx
69
     * @param EcAdapterInterface $ecAdapter
70
     */
71 81
    public function __construct(TransactionInterface $tx, EcAdapterInterface $ecAdapter = null)
72
    {
73 81
        $this->tx = $tx;
74 81
        $this->ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
75 81
        $this->sigSerializer = new TransactionSignatureSerializer(EcSerializer::getSerializer(DerSignatureSerializerInterface::class, true, $this->ecAdapter));
76 81
        $this->pubKeySerializer = EcSerializer::getSerializer(PublicKeySerializerInterface::class, true, $this->ecAdapter);
77 81
    }
78
79
    /**
80
     * @param bool $setting
81
     * @return $this
82
     */
83 1
    public function redeemBitcoinCash(bool $setting)
84
    {
85 1
        $this->redeemBitcoinCash = $setting;
86 1
        return $this;
87
    }
88
89
    /**
90
     * @param bool $setting
91
     * @return $this
92
     */
93 14
    public function padUnsignedMultisigs(bool $setting)
94
    {
95 14
        $this->padUnsignedMultisigs = $setting;
96 14
        return $this;
97
    }
98
99
    /**
100
     * @param bool $setting
101
     * @return $this
102
     */
103 2
    public function tolerateInvalidPublicKey(bool $setting)
104
    {
105 2
        $this->tolerateInvalidPublicKey = $setting;
106 2
        return $this;
107
    }
108
109
    /**
110
     * @param bool $setting
111
     * @return $this
112
     */
113 33
    public function allowComplexScripts(bool $setting)
114
    {
115 33
        $this->allowComplexScripts = $setting;
116 33
        return $this;
117
    }
118
119
    /**
120
     * @param int $nIn
121
     * @param PrivateKeyInterface $key
122
     * @param TransactionOutputInterface $txOut
123
     * @param SignData $signData
124
     * @param int $sigHashType
125
     * @return $this
126
     */
127 25
    public function sign(int $nIn, PrivateKeyInterface $key, TransactionOutputInterface $txOut, SignData $signData = null, $sigHashType = SigHash::ALL)
128
    {
129 25
        $input = $this->input($nIn, $txOut, $signData);
130 25
        foreach ($input->getSteps() as $idx => $step) {
131 25
            $input->sign($key, $sigHashType);
132
        }
133
134 25
        return $this;
135
    }
136
137
    /**
138
     * @param int $nIn
139
     * @param TransactionOutputInterface $txOut
140
     * @param SignData|null $signData
141
     * @return InputSignerInterface
142
     */
143 80
    public function input(int $nIn, TransactionOutputInterface $txOut, SignData $signData = null): InputSignerInterface
144
    {
145 80
        if (null === $signData) {
146 8
            $signData = new SignData();
147
        }
148
149 80
        if (!isset($this->signatureCreator[$nIn])) {
150 80
            $input = (new InputSigner($this->ecAdapter, $this->tx, $nIn, $txOut, $signData, $this->sigSerializer, $this->pubKeySerializer))
151 80
                ->padUnsignedMultisigs($this->padUnsignedMultisigs)
152 80
                ->tolerateInvalidPublicKey($this->tolerateInvalidPublicKey)
153 80
                ->redeemBitcoinCash($this->redeemBitcoinCash)
154 80
                ->allowComplexScripts($this->allowComplexScripts)
155 80
                ->extract();
156
157 68
            $this->signatureCreator[$nIn] = $input;
158
        }
159
160 68
        return $this->signatureCreator[$nIn];
161
    }
162
163
    /**
164
     * @return TransactionInterface
165
     */
166 59
    public function get(): TransactionInterface
167
    {
168 59
        $mutable = TransactionFactory::mutate($this->tx);
169 59
        $witnesses = [];
170 59
        foreach ($mutable->inputsMutator() as $idx => $input) {
171 59
            if (isset($this->signatureCreator[$idx])) {
172 58
                $sig = $this->signatureCreator[$idx]->serializeSignatures();
173 58
                $input->script($sig->getScriptSig());
174 59
                $witnesses[$idx] = $sig->getScriptWitness();
175
            }
176
        }
177
178 59
        if (count($witnesses) > 0) {
179 58
            $mutable->witness($witnesses);
180
        }
181
182 59
        $new = $mutable->done();
183 59
        return $new;
184
    }
185
}
186