TransactionInput::getRelativeBlockLock()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Transaction;
6
7
use BitWasp\Bitcoin\Bitcoin;
8
use BitWasp\Bitcoin\Script\ScriptInterface;
9
use BitWasp\Bitcoin\Serializable;
10
use BitWasp\Bitcoin\Serializer\Transaction\OutPointSerializer;
11
use BitWasp\Bitcoin\Serializer\Transaction\TransactionInputSerializer;
12
use BitWasp\Buffertools\BufferInterface;
13
14
class TransactionInput extends Serializable implements TransactionInputInterface
15
{
16
    /**
17
     * @var OutPointInterface
18
     */
19
    private $outPoint;
20
21
    /**
22
     * @var ScriptInterface
23
     */
24
    private $script;
25
26
    /**
27
     * @var int
28
     */
29
    private $sequence;
30
31
    /**
32
     * @param OutPointInterface $outPoint
33
     * @param ScriptInterface $script
34
     * @param int $sequence
35
     */
36 5277
    public function __construct(OutPointInterface $outPoint, ScriptInterface $script, int $sequence = self::SEQUENCE_FINAL)
37
    {
38 5277
        $this->outPoint = $outPoint;
39 5277
        $this->script = $script;
40 5277
        $this->sequence = $sequence;
41 5277
    }
42
43
    /**
44
     * @return OutPointInterface
45
     */
46 5262
    public function getOutPoint(): OutPointInterface
47
    {
48 5262
        return $this->outPoint;
49
    }
50
51
    /**
52
     * @return ScriptInterface
53
     */
54 5292
    public function getScript(): ScriptInterface
55
    {
56 5292
        return $this->script;
57
    }
58
59
    /**
60
     * @return int
61
     */
62 5270
    public function getSequence(): int
63
    {
64 5270
        return $this->sequence;
65
    }
66
67
    /**
68
     * @param TransactionInputInterface $other
69
     * @return bool
70
     */
71 9
    public function equals(TransactionInputInterface $other): bool
72
    {
73 9
        if (!$this->outPoint->equals($other->getOutPoint())) {
74 2
            return false;
75
        }
76
77 9
        if (!$this->script->equals($other->getScript())) {
78 1
            return false;
79
        }
80
81 9
        return gmp_cmp(gmp_init($this->sequence), gmp_init($other->getSequence())) === 0;
82
    }
83
84
    /**
85
     * Check whether this transaction is a Coinbase transaction
86
     *
87
     * @return bool
88
     */
89 4
    public function isCoinbase(): bool
90
    {
91 4
        $outpoint = $this->outPoint;
92 4
        return $outpoint->getTxId()->getBinary() === str_pad('', 32, "\x00")
93 4
            && $outpoint->getVout() == 0xffffffff;
94
    }
95
96
    /**
97
     * @return bool
98
     */
99 12
    public function isFinal(): bool
100
    {
101 12
        $math = Bitcoin::getMath();
102 12
        return $math->cmp(gmp_init($this->getSequence(), 10), gmp_init(self::SEQUENCE_FINAL, 10)) === 0;
0 ignored issues
show
Bug introduced by
It seems like gmp_init(self::SEQUENCE_FINAL, 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

102
        return $math->cmp(gmp_init($this->getSequence(), 10), /** @scrutinizer ignore-type */ gmp_init(self::SEQUENCE_FINAL, 10)) === 0;
Loading history...
Bug introduced by
It seems like gmp_init($this->getSequence(), 10) can also be of type resource; however, parameter $first 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

102
        return $math->cmp(/** @scrutinizer ignore-type */ gmp_init($this->getSequence(), 10), gmp_init(self::SEQUENCE_FINAL, 10)) === 0;
Loading history...
103
    }
104
105
    /**
106
     * @return bool
107
     */
108 2
    public function isSequenceLockDisabled(): bool
109
    {
110 2
        if ($this->isCoinbase()) {
111 1
            return true;
112
        }
113
114 2
        return ($this->sequence & self::SEQUENCE_LOCKTIME_DISABLE_FLAG) !== 0;
115
    }
116
117
    /**
118
     * @return bool
119
     */
120 1
    public function isLockedToTime(): bool
121
    {
122 1
        return !$this->isSequenceLockDisabled() && (($this->sequence & self::SEQUENCE_LOCKTIME_TYPE_FLAG) === self::SEQUENCE_LOCKTIME_TYPE_FLAG);
123
    }
124
125
    /**
126
     * @return bool
127
     */
128 1
    public function isLockedToBlock(): bool
129
    {
130 1
        return !$this->isSequenceLockDisabled() && (($this->sequence & self::SEQUENCE_LOCKTIME_TYPE_FLAG) === 0);
131
    }
132
133
    /**
134
     * @return int
135
     */
136 1
    public function getRelativeTimeLock(): int
137
    {
138 1
        if (!$this->isLockedToTime()) {
139
            throw new \RuntimeException('Cannot decode time based locktime when disable flag set/timelock flag unset/tx is coinbase');
140
        }
141
142
        // Multiply by 512 to convert locktime to seconds
143 1
        return ($this->sequence & self::SEQUENCE_LOCKTIME_MASK) * 512;
144
    }
145
146
    /**
147
     * @return int
148
     */
149 1
    public function getRelativeBlockLock(): int
150
    {
151 1
        if (!$this->isLockedToBlock()) {
152
            throw new \RuntimeException('Cannot decode block locktime when disable flag set/timelock flag set/tx is coinbase');
153
        }
154
155 1
        return $this->sequence & self::SEQUENCE_LOCKTIME_MASK;
156
    }
157
158
    /**
159
     * @return BufferInterface
160
     */
161 1
    public function getBuffer(): BufferInterface
162
    {
163 1
        return (new TransactionInputSerializer(new OutPointSerializer()))->serialize($this);
164
    }
165
}
166