Completed
Pull Request — master (#239)
by thomas
31:39 queued 14:06
created

Transaction::getWitness()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace BitWasp\Bitcoin\Transaction;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Collection\Transaction\TransactionInputCollection;
7
use BitWasp\Bitcoin\Collection\Transaction\TransactionOutputCollection;
8
use BitWasp\Bitcoin\Collection\Transaction\TransactionWitnessCollection;
9
use BitWasp\Bitcoin\Crypto\Hash;
10
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
11
use BitWasp\Bitcoin\Serializable;
12
use BitWasp\Bitcoin\Serializer\Transaction\OldTransactionSerializer;
13
use BitWasp\Bitcoin\Serializer\Transaction\TransactionSerializer;
14
use BitWasp\Bitcoin\Transaction\SignatureHash\Hasher;
15
use BitWasp\Bitcoin\Utxo\Utxo;
16
use BitWasp\Buffertools\BufferInterface;
17
use BitWasp\CommonTrait\FunctionAliasArrayAccess;
18
19
class Transaction extends Serializable implements TransactionInterface
20
{
21
    use FunctionAliasArrayAccess;
22
23
    /**
24
     * @var int|string
25
     */
26
    private $version;
27
28
    /**
29
     * @var TransactionInputCollection
30
     */
31
    private $inputs;
32
33
    /**
34
     * @var TransactionOutputCollection
35
     */
36
    private $outputs;
37
38
    /**
39
     * @var TransactionWitnessCollection
40
     */
41
    private $witness;
42
43
    /**
44
     * @var int|string
45
     */
46
    private $lockTime;
47
48
    /**
49
     * Transaction constructor.
50
     *
51
     * @param int $nVersion
52
     * @param TransactionInputCollection|null $inputs
53
     * @param TransactionOutputCollection|null $outputs
54
     * @param TransactionWitnessCollection|null $witness
55
     * @param int $nLockTime
56
     */
57 1938
    public function __construct(
58
        $nVersion = TransactionInterface::DEFAULT_VERSION,
59
        TransactionInputCollection $inputs = null,
60
        TransactionOutputCollection $outputs = null,
61
        TransactionWitnessCollection $witness = null,
62
        $nLockTime = 0
63
    ) {
64
65 1938
        if (!is_numeric($nVersion)) {
66 6
            throw new \InvalidArgumentException('Transaction version must be numeric');
67
        }
68
69 1932
        if (!is_numeric($nLockTime)) {
70 6
            throw new \InvalidArgumentException('Transaction locktime must be numeric');
71
        }
72
73 1926
        $math = Bitcoin::getMath();
74 1926
        if ($math->cmp($nVersion, TransactionInterface::MAX_VERSION) > 0) {
75 6
            throw new \InvalidArgumentException('Version must be less than ' . TransactionInterface::MAX_VERSION);
76
        }
77
78 1920
        if ($math->cmp($nLockTime, 0) < 0 || $math->cmp($nLockTime, TransactionInterface::MAX_LOCKTIME) > 0) {
79 6
            throw new \InvalidArgumentException('Locktime must be positive and less than ' . TransactionInterface::MAX_LOCKTIME);
80
        }
81
82 1914
        $this->version = $nVersion;
0 ignored issues
show
Documentation Bug introduced by
It seems like $nVersion can also be of type double. However, the property $version is declared as type integer|string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
83 1914
        $this->inputs = $inputs ?: new TransactionInputCollection();
84 1914
        $this->outputs = $outputs ?: new TransactionOutputCollection();
85 1914
        $this->witness = $witness ?: new TransactionWitnessCollection();
86 1914
        $this->lockTime = $nLockTime;
0 ignored issues
show
Documentation Bug introduced by
It seems like $nLockTime can also be of type double. However, the property $lockTime is declared as type integer|string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
87
88 1914
        $this
89 1914
            ->initFunctionAlias('version', 'getVersion')
90 1914
            ->initFunctionAlias('inputs', 'getInputs')
91 1914
            ->initFunctionAlias('outputs', 'getOutputs')
92 1914
            ->initFunctionAlias('locktime', 'getLockTime');
93 1914
    }
94
95
    /**
96
     * @return Transaction
97
     */
98 165
    public function __clone()
99
    {
100 165
        $this->inputs = clone $this->inputs;
101 165
        $this->outputs = clone $this->outputs;
102 165
    }
103
104
    /**
105
     * @return BufferInterface
106
     */
107 183
    public function getTxHash()
108
    {
109 183
        return Hash::sha256d($this->getBuffer());
110
    }
111
112
    /**
113
     * @return BufferInterface
114
     */
115 183
    public function getTxId()
116 6
    {
117 183
        return $this->getTxHash()->flip();
118
    }
119
120
    /**
121
     * @return \BitWasp\Buffertools\BufferInterface
122
     */
123
    public function getWitnessTxId()
124
    {
125
        return Hash::sha256d($this->getWitnessBuffer())->flip();
126
    }
127
128
    /**
129
     * @return int|string
130
     */
131 375
    public function getVersion()
132
    {
133 375
        return $this->version;
134
    }
135
136
    /**
137
     * Get the array of inputs in the transaction
138
     *
139
     * @return TransactionInputCollection
140
     */
141 1050
    public function getInputs()
142
    {
143 1050
        return $this->inputs;
144
    }
145
146
    /**
147
     * @param int $index
148
     * @return TransactionInputInterface
149
     */
150 159
    public function getInput($index)
151
    {
152 159
        return $this->inputs[$index];
153
    }
154
155
    /**
156
     * Get Outputs
157
     *
158
     * @return TransactionOutputCollection
159
     */
160 384
    public function getOutputs()
161
    {
162 384
        return $this->outputs;
163
    }
164
165
    /**
166
     * @param int $vout
167
     * @return TransactionOutputInterface
168
     */
169 153
    public function getOutput($vout)
170
    {
171 153
        return $this->outputs[$vout];
172
    }
173
174
    /**
175
     * @return TransactionWitnessCollection
176
     */
177 147
    public function getWitnesses()
178
    {
179 147
        return $this->witness;
180
    }
181
182
    /**
183
     * @return ScriptWitnessInterface
184
     */
185
    public function getWitness($index)
186
    {
187
        return $this->witness[$index];
188
    }
189
190
    /**
191
     * @param int $vout
192
     * @return OutPointInterface
193
     */
194 24
    public function makeOutpoint($vout)
195
    {
196 24
        $this->getOutput($vout);
0 ignored issues
show
Unused Code introduced by
The call to the method BitWasp\Bitcoin\Transact...ransaction::getOutput() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
197 24
        return new OutPoint($this->getTxId(), $vout);
198
    }
199
200
    /**
201
     * @param int $vout
202
     * @return Utxo
203
     */
204
    public function makeUtxo($vout)
205
    {
206
        $output = $this->getOutput($vout);
207
208
        return new Utxo(
209
            new OutPoint($this->getTxId(), $vout),
210
            $output
211
        );
212
    }
213
214
    /**
215
     * Get Lock Time
216
     *
217
     * @return int|string
218
     */
219 381
    public function getLockTime()
220
    {
221 381
        return $this->lockTime;
222
    }
223
224
    /**
225
     * @return \BitWasp\Bitcoin\Transaction\SignatureHash\SigHash
226
     */
227 96
    public function getSignatureHash()
228
    {
229 96
        return new Hasher($this);
230
    }
231
232
    /**
233
     * @return int|string
234
     */
235 6
    public function getValueOut()
236
    {
237 6
        $math = Bitcoin::getMath();
238 6
        $value = 0;
239 6
        foreach ($this->outputs as $output) {
240 6
            $value = $math->add($value, $output->getValue());
241 6
        }
242
243 6
        return $value;
244
    }
245
246
    /**
247
     * @return bool
248
     */
249 6
    public function isCoinbase()
250
    {
251 6
        return count($this->inputs) === 1 && $this->getInput(0)->isCoinBase();
252
    }
253
254
    /**
255
     * @return Validator
256
     */
257 54
    public function validator()
258
    {
259 54
        return new Validator($this);
260
    }
261
262
    /**
263
     * @return BufferInterface
264
     */
265 315
    public function getBuffer()
266
    {
267 315
        return (new OldTransactionSerializer())->serialize($this);
268
    }
269
270
    /**
271
     * @return BufferInterface
272
     */
273 54
    public function getWitnessBuffer()
274
    {
275 54
        return (new TransactionSerializer())->serialize($this);
276
    }
277
}
278