Completed
Push — 0.0.35 ( b2fc74...d8d049 )
by thomas
28:12 queued 09:10
created

Signer::setCheckerCreator()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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