Completed
Pull Request — master (#524)
by thomas
40:24 queued 38:13
created

Signer::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

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