Math::decodeCompact()   B
last analyzed

Complexity

Conditions 10
Paths 33

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 10.017

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 18
c 1
b 0
f 0
nc 33
nop 3
dl 0
loc 28
ccs 17
cts 18
cp 0.9444
crap 10.017
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Math;
6
7
use Mdanter\Ecc\Math\GmpMath;
8
use Mdanter\Ecc\Util\NumberSize;
9
10
class Math extends GmpMath
11
{
12
13
    /**
14
     * @param \GMP $integer
15
     * @return bool
16
     */
17 54
    public function isEven(\GMP $integer): bool
18
    {
19 54
        return $this->cmp($this->mod($integer, gmp_init(2)), gmp_init(0)) === 0;
0 ignored issues
show
Bug introduced by
It seems like gmp_init(2) can also be of type resource; however, parameter $modulus of Mdanter\Ecc\Math\GmpMath::mod() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

19
        return $this->cmp($this->mod($integer, /** @scrutinizer ignore-type */ gmp_init(2)), gmp_init(0)) === 0;
Loading history...
Bug introduced by
It seems like gmp_init(0) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

19
        return $this->cmp($this->mod($integer, gmp_init(2)), /** @scrutinizer ignore-type */ gmp_init(0)) === 0;
Loading history...
20
    }
21
22
    /**
23
     * @param \GMP $int
24
     * @param \GMP $otherInt
25
     * @return \GMP
26
     */
27 1695
    public function bitwiseOr(\GMP $int, \GMP $otherInt): \GMP
28
    {
29 1695
        return gmp_or($int, $otherInt);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_or($int, $otherInt) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
30
    }
31
32
    /**
33
     * Similar to gmp_div_qr, return a tuple containing the
34
     * result and the remainder
35
     *
36
     * @param \GMP $dividend
37
     * @param \GMP $divisor
38
     * @return array
39
     */
40
    public function divQr(\GMP $dividend, \GMP $divisor): array
41
    {
42
        // $div = n / q
43
        $div = $this->div($dividend, $divisor);
44
        // $remainder = n - (n / q) * q
45
        $remainder = $this->sub($dividend, $this->mul($div, $divisor));
46
        return [$div, $remainder];
47
    }
48
49
    /**
50
     * @param int $compact
51
     * @param bool|false $isNegative
52
     * @param bool|false $isOverflow
53
     * @return \GMP
54
     */
55 210
    public function decodeCompact($compact, &$isNegative, &$isOverflow): \GMP
56
    {
57 210
        if ($compact < 0 || $compact > pow(2, 32) - 1) {
58
            throw new \RuntimeException('Compact integer must be 32bit');
59
        }
60
61 210
        $compact = gmp_init($compact, 10);
62 210
        $size = $this->rightShift($compact, 24);
0 ignored issues
show
Bug introduced by
It seems like $compact can also be of type resource; however, parameter $number of Mdanter\Ecc\Math\GmpMath::rightShift() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
        $size = $this->rightShift(/** @scrutinizer ignore-type */ $compact, 24);
Loading history...
63 210
        $word = $this->bitwiseAnd($compact, gmp_init(0x007fffff, 10));
0 ignored issues
show
Bug introduced by
It seems like $compact can also be of type resource; however, parameter $first of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $word = $this->bitwiseAnd(/** @scrutinizer ignore-type */ $compact, gmp_init(0x007fffff, 10));
Loading history...
Bug introduced by
It seems like gmp_init(8388607, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $word = $this->bitwiseAnd($compact, /** @scrutinizer ignore-type */ gmp_init(0x007fffff, 10));
Loading history...
64 210
        if ($this->cmp($size, gmp_init(3)) <= 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(3) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
        if ($this->cmp($size, /** @scrutinizer ignore-type */ gmp_init(3)) <= 0) {
Loading history...
65 13
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub(gmp_init(3, 10), $size)));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(8, 10) can also be of type resource; however, parameter $multiplier of Mdanter\Ecc\Math\GmpMath::mul() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            $positions = (int) $this->toString($this->mul(/** @scrutinizer ignore-type */ gmp_init(8, 10), $this->sub(gmp_init(3, 10), $size)));
Loading history...
Bug introduced by
It seems like gmp_init(3, 10) can also be of type resource; however, parameter $minuend of Mdanter\Ecc\Math\GmpMath::sub() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub(/** @scrutinizer ignore-type */ gmp_init(3, 10), $size)));
Loading history...
66 13
            $word = $this->rightShift($word, $positions);
67
        } else {
68 197
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub($size, gmp_init(3, 10))));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(3, 10) can also be of type resource; however, parameter $subtrahend of Mdanter\Ecc\Math\GmpMath::sub() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub($size, /** @scrutinizer ignore-type */ gmp_init(3, 10))));
Loading history...
69 197
            $word = $this->leftShift($word, $positions);
70
        }
71
72
        // isNegative: $word !== 0 && $uint32 & 0x00800000 !== 0
73
        // isOverflow: $word !== 0 && (($size > 34) || ($word > 0xff && $size > 33) || ($word > 0xffff && $size > 32))
74 210
        $zero = gmp_init(0);
75 210
        $isNegative = ($this->cmp($word, $zero) !== 0) && ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000)), $zero) === 1);
76 210
        $isOverflow = $this->cmp($word, $zero) !== 0 && (
77 199
                ($this->cmp($size, gmp_init(34, 10)) > 0)
78 198
                || ($this->cmp($word, gmp_init(0xff, 10)) > 0 && $this->cmp($size, gmp_init(33, 10)) > 0)
79 210
                || ($this->cmp($word, gmp_init(0xffff, 10)) > 0 && $this->cmp($size, gmp_init(32, 10)) > 0)
80
            );
81
82 210
        return $word;
83
    }
84
85
    /**
86
     * @param \GMP $integer
87
     * @return \GMP
88
     */
89 18
    public function getLow64(\GMP $integer): \GMP
90
    {
91 18
        $bits = gmp_strval($integer, 2);
92 18
        $bits = substr($bits, 0, 64);
93 18
        $bits = str_pad($bits, 64, '0', STR_PAD_LEFT);
94 18
        return gmp_init($bits, 2);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_init($bits, 2) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
95
    }
96
97
    /**
98
     * @param \GMP $int
99
     * @param int $byteSize
100
     * @return string
101
     */
102
    public function fixedSizeInt(\GMP $int, int $byteSize): string
103
    {
104
        $two = gmp_init(2);
105
        $maskShift = gmp_pow($two, 8);
106
        $mask = gmp_mul(gmp_init(255), gmp_pow($two, 256));
107
108
        $x = '';
109
        for ($i = $byteSize - 1; $i >= 0; $i--) {
110
            $mask = gmp_div($mask, $maskShift);
111
            $x .= pack('C', gmp_strval(gmp_div(gmp_and($int, $mask), gmp_pow($two, $i * 8)), 10));
112
        }
113
114
        return $x;
115
    }
116
117
    /**
118
     * @param \GMP $integer
119
     * @param bool $fNegative
120
     * @return \GMP
121
     */
122 18
    public function encodeCompact(\GMP $integer, bool $fNegative): \GMP
123
    {
124 18
        if (!is_bool($fNegative)) {
0 ignored issues
show
introduced by
The condition is_bool($fNegative) is always true.
Loading history...
125
            throw new \InvalidArgumentException('CompactInteger::read() - flag must be boolean!');
126
        }
127
128 18
        $size = (int) NumberSize::bnNumBytes($this, $integer);
129 18
        if ($size <= 3) {
130 14
            $compact = $this->leftShift($this->getLow64($integer), (8 * (3 - $size)));
131
        } else {
132 4
            $compact = $this->rightShift($integer, 8 * ($size - 3));
133 4
            $compact = $this->getLow64($compact);
134
        }
135
136 18
        if ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000, 10)), gmp_init(0, 10)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(0, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        if ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000, 10)), /** @scrutinizer ignore-type */ gmp_init(0, 10)) > 0) {
Loading history...
Bug introduced by
It seems like gmp_init(8388608, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        if ($this->cmp($this->bitwiseAnd($compact, /** @scrutinizer ignore-type */ gmp_init(0x00800000, 10)), gmp_init(0, 10)) > 0) {
Loading history...
137 1
            $compact = $this->rightShift($compact, 8);
138 1
            $size = $size + 1;
139
        }
140
141 18
        $compact = $this->bitwiseOr($compact, $this->leftShift(gmp_init($size, 10), 24));
0 ignored issues
show
Bug introduced by
It seems like gmp_init($size, 10) can also be of type resource; however, parameter $number of Mdanter\Ecc\Math\GmpMath::leftShift() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

141
        $compact = $this->bitwiseOr($compact, $this->leftShift(/** @scrutinizer ignore-type */ gmp_init($size, 10), 24));
Loading history...
142 18
        if ($fNegative && $this->cmp($this->bitwiseAnd($compact, gmp_init(0x007fffff, 10)), gmp_init(0, 10)) > 0) { /// ?
143 2
            $compact = $this->bitwiseOr($compact, gmp_init(0x00800000, 10));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(8388608, 10) can also be of type resource; however, parameter $otherInt of BitWasp\Bitcoin\Math\Math::bitwiseOr() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
            $compact = $this->bitwiseOr($compact, /** @scrutinizer ignore-type */ gmp_init(0x00800000, 10));
Loading history...
144
        }
145
146 18
        return $compact;
147
    }
148
}
149