Completed
Pull Request — master (#519)
by thomas
80:31 queued 75:30
created

Signer   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 94.29%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 121
ccs 33
cts 35
cp 0.9429
rs 10
c 2
b 0
f 0
wmc 12
lcom 1
cbo 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A tolerateInvalidPublicKey() 0 10 2
A sign() 0 8 2
A input() 0 16 3
A get() 0 17 3
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 InputSignerInterface[]
46
     */
47
    private $signatureCreator = [];
48
49
    /**
50
     * TxWitnessSigner constructor.
51
     * @param TransactionInterface $tx
52
     * @param EcAdapterInterface $ecAdapter
53
     */
54 64
    public function __construct(TransactionInterface $tx, EcAdapterInterface $ecAdapter = null)
55
    {
56 64
        $this->tx = $tx;
57 64
        $this->ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
58 64
        $this->sigSerializer = new TransactionSignatureSerializer(EcSerializer::getSerializer(DerSignatureSerializerInterface::class, true, $this->ecAdapter));
59 64
        $this->pubKeySerializer = EcSerializer::getSerializer(PublicKeySerializerInterface::class, true, $this->ecAdapter);
60 64
    }
61
62
    /**
63
     * @param bool $setting
64
     * @return $this
65
     */
66 2
    public function tolerateInvalidPublicKey($setting)
67
    {
68 2
        if (!is_bool($setting)) {
69
            throw new \InvalidArgumentException("Boolean value expected");
70
        }
71
72 2
        $this->tolerateInvalidPublicKey = $setting;
73
74 2
        return $this;
75
    }
76
77
    /**
78
     * @param int $nIn
79
     * @param PrivateKeyInterface $key
80
     * @param TransactionOutputInterface $txOut
81
     * @param SignData $signData
82
     * @param int $sigHashType
83
     * @return $this
84
     */
85 50
    public function sign($nIn, PrivateKeyInterface $key, TransactionOutputInterface $txOut, SignData $signData = null, $sigHashType = SigHash::ALL)
86
    {
87 50
        if (!$this->input($nIn, $txOut, $signData)->sign($key, $sigHashType)) {
88
            throw new \RuntimeException('Unsignable script');
89
        }
90
91 50
        return $this;
92
    }
93
94
    /**
95
     * @param int $nIn
96
     * @param TransactionOutputInterface $txOut
97
     * @param SignData|null $signData
98
     * @return InputSignerInterface
99
     */
100 64
    public function input($nIn, TransactionOutputInterface $txOut, SignData $signData = null)
101
    {
102 64
        if (null === $signData) {
103 14
            $signData = new SignData();
104
        }
105
106 64
        if (!isset($this->signatureCreator[$nIn])) {
107 64
            $input = (new InputSigner($this->ecAdapter, $this->tx, $nIn, $txOut, $signData, $this->sigSerializer, $this->pubKeySerializer))
108 64
                ->tolerateInvalidPublicKey($this->tolerateInvalidPublicKey)
109 64
                ->extract();
110
111 60
            $this->signatureCreator[$nIn] = $input;
112
        }
113
114 60
        return $this->signatureCreator[$nIn];
115
    }
116
117
    /**
118
     * @return TransactionInterface
119
     */
120 50
    public function get()
121
    {
122 50
        $mutable = TransactionFactory::mutate($this->tx);
123 50
        $witnesses = [];
124 50
        foreach ($mutable->inputsMutator() as $idx => $input) {
125 50
            $sig = $this->signatureCreator[$idx]->serializeSignatures();
126 50
            $input->script($sig->getScriptSig());
127 50
            $witnesses[$idx] = $sig->getScriptWitness();
128
        }
129
130 50
        if (count($witnesses) > 0) {
131 50
            $mutable->witness($witnesses);
132
        }
133
134 50
        $new = $mutable->done();
135 50
        return $new;
136
    }
137
}
138