Completed
Push — master ( 015b1e...e1c455 )
by thomas
67:33 queued 36:12
created

TxBuilder::bip69()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 10
ccs 0
cts 6
cp 0
rs 9.4285
c 2
b 0
f 0
cc 1
eloc 6
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
53 921
    public function __construct()
54
    {
55 921
        $this->reset();
56 921
    }
57
58
    /**
59
     * @return $this
60
     */
61 921
    public function reset()
62
    {
63 921
        $this->nVersion = 1;
64 921
        $this->inputs = [];
65 921
        $this->outputs = [];
66 921
        $this->witness = [];
67 921
        $this->nLockTime = 0;
68 921
        return $this;
69
    }
70
71
    /**
72
     * @return TransactionInterface
73
     */
74 915
    private function makeTransaction()
75
    {
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 915
        );
83
    }
84
85
    /**
86
     * @return TransactionInterface
87
     */
88 909
    public function get()
89
    {
90 909
        return $this->makeTransaction();
91
    }
92
93
    /**
94
     * @return TransactionInterface
95
     */
96 30
    public function getAndReset()
97
    {
98 30
        $transaction = $this->makeTransaction();
99 30
        $this->reset();
100 30
        return $transaction;
101
    }
102
103
    /**
104
     * @param int $nVersion
105
     * @return $this
106
     */
107 18
    public function version($nVersion)
108
    {
109 18
        $this->nVersion = $nVersion;
110 18
        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
     */
120 825
    public function input($hashPrevOut, $nPrevOut, Script $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
121
    {
122 825
        $this->inputs[] = new TransactionInput(
123 825
            new OutPoint(
124 825
                $hashPrevOut instanceof BufferInterface ? $hashPrevOut : Buffer::hex($hashPrevOut, 32),
125
                $nPrevOut
126 825
            ),
127 825
            $script ?: new Script(),
128
            $nSequence
129 825
        );
130
131 825
        return $this;
132
    }
133
134
    /**
135
     * @param TransactionInputInterface[] $inputs
136
     * @return $this
137
     */
138 6
    public function inputs(array $inputs)
139
    {
140
        array_walk($inputs, function (TransactionInputInterface $input) {
141 6
            $this->inputs[] = $input;
142 6
        });
143
144 6
        return $this;
145
    }
146
147
    /**
148
     * @param integer $value
149
     * @param ScriptInterface $script
150
     * @return $this
151
     */
152 201
    public function output($value, ScriptInterface $script)
153
    {
154 201
        $this->outputs[] = new TransactionOutput($value, $script);
155 201
        return $this;
156
    }
157
158
    /**
159
     * @param TransactionOutputInterface[] $outputs
160
     * @return $this
161
     */
162 6
    public function outputs(array $outputs)
163
    {
164
        array_walk($outputs, function (TransactionOutputInterface $output) {
165 6
            $this->outputs[] = $output;
166 6
        });
167
168 6
        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
     */
188 18
    public function locktime($locktime)
189
    {
190 18
        $this->nLockTime = $locktime;
191 18
        return $this;
192
    }
193
194
    /**
195
     * @param Locktime $lockTime
196
     * @param int $nTimestamp
197
     * @return $this
198
     * @throws \Exception
199
     */
200 6
    public function lockToTimestamp(Locktime $lockTime, $nTimestamp)
201
    {
202 6
        $this->locktime($lockTime->fromTimestamp($nTimestamp));
203 6
        return $this;
204
    }
205
206
    /**
207
     * @param Locktime $lockTime
208
     * @param int $blockHeight
209
     * @return $this
210
     * @throws \Exception
211
     */
212 6
    public function lockToBlockHeight(Locktime $lockTime, $blockHeight)
213
    {
214 6
        $this->locktime($lockTime->fromBlockHeight($blockHeight));
215 6
        return $this;
216
    }
217
218
    /**
219
     * @param OutPointInterface $outpoint
220
     * @param ScriptInterface|null $script
221
     * @param int $nSequence
222
     * @return $this
223
     */
224 54
    public function spendOutPoint(OutPointInterface $outpoint, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
225
    {
226 54
        $this->inputs[] = new TransactionInput(
227 54
            $outpoint,
228 54
            $script ?: new Script(),
229
            $nSequence
230 54
        );
231
232 54
        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
     */
242 87
    public function spendOutputFrom(TransactionInterface $transaction, $outputToSpend, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
243
    {
244
        // Check TransactionOutput exists in $tx
245 87
        $transaction->getOutput($outputToSpend);
246 87
        $this->input(
247 87
            $transaction->getTxId(),
248 87
            $outputToSpend,
249 87
            $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
            $nSequence
251 87
        );
252
253 87
        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
     */
263 108
    public function payToAddress($value, AddressInterface $address)
264
    {
265
        // Create Script from address, then create an output.
266 108
        $this->output(
267 108
            $value,
268 108
            ScriptFactory::scriptPubKey()->payToAddress($address)
269 108
        );
270
271 108
        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
        list ($inputs, $witness) = $bip69->sortInputsAndWitness($this->inputs, $this->witness);
284
285
        $this->inputs = $inputs;
286
        $this->outputs = $bip69->sortOutputs($this->outputs);
287
        $this->witness = $witness;
288
289
        return $this;
290
    }
291
}
292