Completed
Pull Request — master (#270)
by thomas
69:50
created

TxBuilder::bip69()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
ccs 0
cts 0
cp 0
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php
2
3
namespace BitWasp\Bitcoin\Transaction\Factory;
4
5
use BitWasp\Bitcoin\Address\AddressInterface;
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\Locktime;
10
use BitWasp\Bitcoin\Script\Script;
11
use BitWasp\Bitcoin\Script\ScriptFactory;
12
use BitWasp\Bitcoin\Script\ScriptInterface;
13
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
14
use BitWasp\Bitcoin\Transaction\Bip69\Bip69;
15
use BitWasp\Bitcoin\Transaction\OutPoint;
16
use BitWasp\Bitcoin\Transaction\OutPointInterface;
17
use BitWasp\Bitcoin\Transaction\Transaction;
18
use BitWasp\Bitcoin\Transaction\TransactionInput;
19
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
20
use BitWasp\Bitcoin\Transaction\TransactionInterface;
21
use BitWasp\Bitcoin\Transaction\TransactionOutput;
22
use BitWasp\Bitcoin\Transaction\TransactionOutputInterface;
23
use BitWasp\Buffertools\Buffer;
24
use BitWasp\Buffertools\BufferInterface;
25
26
class TxBuilder
27
{
28
    /**
29
     * @var int
30
     */
31
    private $nVersion;
32
33
    /**
34
     * @var array
35
     */
36
    private $inputs;
37
38
    /**
39
     * @var array
40
     */
41
    private $outputs;
42
43
    /**
44
     * @var array
45
     */
46
    private $witness;
47
48
    /**
49
     * @var int
50
     */
51
    private $nLockTime;
52 921
53
    public function __construct()
54 921
    {
55 921
        $this->reset();
56
    }
57
58
    /**
59
     * @return $this
60 921
     */
61
    public function reset()
62 921
    {
63 921
        $this->nVersion = 1;
64 921
        $this->inputs = [];
65 921
        $this->outputs = [];
66 921
        $this->witness = [];
67 921
        $this->nLockTime = 0;
68
        return $this;
69
    }
70
71
    /**
72
     * @return TransactionInterface
73 915
     */
74
    private function makeTransaction()
75 915
    {
76 915
        return new Transaction(
77 915
            $this->nVersion,
78 915
            new TransactionInputCollection($this->inputs),
79 915
            new TransactionOutputCollection($this->outputs),
80 915
            new TransactionWitnessCollection($this->witness),
81 915
            $this->nLockTime
82
        );
83
    }
84
85
    /**
86
     * @return TransactionInterface
87 909
     */
88
    public function get()
89 909
    {
90
        return $this->makeTransaction();
91
    }
92
93
    /**
94
     * @return TransactionInterface
95 30
     */
96
    public function getAndReset()
97 30
    {
98 30
        $transaction = $this->makeTransaction();
99 30
        $this->reset();
100
        return $transaction;
101
    }
102
103
    /**
104
     * @param int $nVersion
105
     * @return $this
106 18
     */
107
    public function version($nVersion)
108 18
    {
109 18
        $this->nVersion = $nVersion;
110
        return $this;
111
    }
112
113
    /**
114
     * @param BufferInterface $hashPrevOut
115
     * @param int $nPrevOut
116
     * @param Script|null $script
117
     * @param int $nSequence
118
     * @return $this
119 825
     */
120
    public function input($hashPrevOut, $nPrevOut, Script $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
121 825
    {
122 825
        $this->inputs[] = new TransactionInput(
123 825
            new OutPoint(
124
                $hashPrevOut instanceof BufferInterface ? $hashPrevOut : Buffer::hex($hashPrevOut, 32),
125 825
                $nPrevOut
126 825
            ),
127
            $script ?: new Script(),
128 825
            $nSequence
129
        );
130 825
131
        return $this;
132
    }
133
134
    /**
135
     * @param TransactionInputInterface[] $inputs
136
     * @return $this
137 6
     */
138
    public function inputs(array $inputs)
139
    {
140 6
        array_walk($inputs, function (TransactionInputInterface $input) {
141 6
            $this->inputs[] = $input;
142
        });
143 6
144
        return $this;
145
    }
146
147
    /**
148
     * @param integer $value
149
     * @param ScriptInterface $script
150
     * @return $this
151 201
     */
152
    public function output($value, ScriptInterface $script)
153 201
    {
154 201
        $this->outputs[] = new TransactionOutput($value, $script);
155
        return $this;
156
    }
157
158
    /**
159
     * @param TransactionOutputInterface[] $outputs
160
     * @return $this
161 87
     */
162 87
    public function outputs(array $outputs)
163
    {
164 6
        array_walk($outputs, function (TransactionOutputInterface $output) {
165 6
            $this->outputs[] = $output;
166
        });
167 6
168
        return $this;
169
    }
170
171
    /**
172
     * @param ScriptWitnessInterface[] $witness
173
     * @return $this
174
     */
175
    public function witnesses(array $witness)
176
    {
177
        array_walk($witness, function (ScriptWitnessInterface $witness) {
178
            $this->witness[] = $witness;
179
        });
180
181
        return $this;
182
    }
183
184
    /**
185
     * @param int $locktime
186
     * @return $this
187 18
     */
188
    public function locktime($locktime)
189 18
    {
190 18
        $this->nLockTime = $locktime;
191
        return $this;
192
    }
193
194
    /**
195
     * @param Locktime $lockTime
196
     * @param int $nTimestamp
197
     * @return $this
198
     * @throws \Exception
199 6
     */
200
    public function lockToTimestamp(Locktime $lockTime, $nTimestamp)
201 6
    {
202 6
        $this->locktime($lockTime->fromTimestamp($nTimestamp));
203
        return $this;
204
    }
205
206
    /**
207
     * @param Locktime $lockTime
208
     * @param int $blockHeight
209
     * @return $this
210
     * @throws \Exception
211 6
     */
212
    public function lockToBlockHeight(Locktime $lockTime, $blockHeight)
213 6
    {
214 6
        $this->locktime($lockTime->fromBlockHeight($blockHeight));
215
        return $this;
216
    }
217
218
    /**
219
     * @param OutPointInterface $outpoint
220
     * @param ScriptInterface|null $script
221
     * @param int $nSequence
222
     * @return $this
223 54
     */
224
    public function spendOutPoint(OutPointInterface $outpoint, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
225 54
    {
226 54
        $this->inputs[] = new TransactionInput(
227 54
            $outpoint,
228
            $script ?: new Script(),
229 54
            $nSequence
230
        );
231 54
232
        return $this;
233
    }
234
235
    /**
236
     * @param TransactionInterface $transaction
237
     * @param int $outputToSpend
238
     * @param ScriptInterface|null $script
239
     * @param int $nSequence
240
     * @return $this
241 87
     */
242
    public function spendOutputFrom(TransactionInterface $transaction, $outputToSpend, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
243
    {
244 87
        // Check TransactionOutput exists in $tx
245 87
        $transaction->getOutput($outputToSpend);
246 87
        $this->input(
247 87
            $transaction->getTxId(),
248 87
            $outputToSpend,
249
            $script,
0 ignored issues
show
Bug introduced by
It seems like $script defined by parameter $script on line 242 can also be of type object<BitWasp\Bitcoin\Script\ScriptInterface>; however, BitWasp\Bitcoin\Transact...tory\TxBuilder::input() does only seem to accept null|object<BitWasp\Bitcoin\Script\Script>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
250 87
            $nSequence
251
        );
252 87
253
        return $this;
254
    }
255
256
    /**
257
     * Create an output paying $value to an Address.
258
     *
259
     * @param int $value
260
     * @param AddressInterface $address
261
     * @return $this
262 108
     */
263
    public function payToAddress($value, AddressInterface $address)
264
    {
265 108
        // Create Script from address, then create an output.
266 108
        $this->output(
267 108
            $value,
268 108
            ScriptFactory::scriptPubKey()->payToAddress($address)
269
        );
270 108
271
        return $this;
272
    }
273
274
    /**
275
     * Sorts the transaction inputs and outputs lexicographically,
276
     * according to BIP69
277
     *
278
     * @param Bip69 $bip69
279
     * @return $this
280
     */
281
    public function bip69(Bip69 $bip69)
282
    {
283
        $this->inputs = $bip69->sortInputs($this->inputs);
284
        $this->outputs = $bip69->sortOutputs($this->outputs);
285
286
        return $this;
287
    }
288
}
289