Completed
Push — master ( 319c7a...cdee94 )
by thomas
79:06 queued 75:43
created

ScriptCreator::int()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
ccs 0
cts 8
cp 0
rs 8.8571
cc 5
eloc 8
nc 3
nop 1
crap 30
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Factory;
4
5
use BitWasp\Bitcoin\Math\Math;
6
use BitWasp\Bitcoin\Script\Interpreter\Number;
7
use BitWasp\Bitcoin\Script\Opcodes;
8
use BitWasp\Bitcoin\Script\Script;
9
use BitWasp\Bitcoin\Script\ScriptInterface;
10
use BitWasp\Bitcoin\Serializable;
11
use BitWasp\Buffertools\Buffer;
12
use BitWasp\Buffertools\Buffertools;
13
use BitWasp\Buffertools\Parser;
14
15
class ScriptCreator
16
{
17
    /**
18
     * @var string
19
     */
20
    private $script = '';
21
22
    /**
23
     * @var Opcodes
24
     */
25
    private $opcodes;
26
27
    /**
28
     * @var Math
29
     */
30
    private $math;
31
32
    /**
33
     * @param Math $math
34
     * @param Opcodes $opcodes
35
     * @param Buffer|null $buffer
36
     */
37 1125
    public function __construct(Math $math, Opcodes $opcodes, Buffer $buffer = null)
38
    {
39 1125
        if ($buffer !== null) {
40 750
            $this->script = $buffer->getBinary();
41 750
        }
42
43 1125
        $this->math = $math;
44 1125
        $this->opcodes = $opcodes;
45 1125
    }
46
47
    /**
48
     * Add an opcode to the script
49
     *
50
     * @param string $name
51
     * @return $this
52
     */
53 297
    public function op($name)
54
    {
55 297
        $code = $this->opcodes->getOpByName($name);
56 291
        $this->script .= chr($code);
57 291
        return $this;
58
    }
59
60
    /**
61
     * Push data into the stack.
62
     *
63
     * @param $data
64
     * @return $this
65
     * @throws \Exception
66
     */
67 375
    public function push(Buffer $data)
68
    {
69 375
        $length = $data->getSize();
70 375
        $parsed = new Parser('', $this->math);
71
72
        /** Note that larger integers are serialized without flipping bits - Big endian */
73
74 375
        if ($length < $this->opcodes->getOpByName('OP_PUSHDATA1')) {
75 357
            $varInt = Buffertools::numToVarInt($length);
76 357
            $data = new Buffer($varInt->getBinary() . $data->getBinary(), null, $this->math);
77 357
            $parsed->writeBytes($data->getSize(), $data);
78 357
        } else {
79 36
            if ($length <= 0xff) {
80 24
                $lengthSize = 1;
81 36
            } elseif ($length <= 0xffff) {
82 6
                $lengthSize = 2;
83 6
            } else {
84 6
                $lengthSize = 4;
85
            }
86
87 36
            $op = $this->opcodes->getOpByName('OP_PUSHDATA' . $lengthSize);
88
            $parsed
89 36
                ->writeBytes(1, Buffer::int($op))
90 36
                ->writeBytes($lengthSize, Buffer::int($length), true)
91 36
                ->writeBytes($length, $data);
92
        }
93
94 375
        $this->script .= $parsed->getBuffer()->getBinary();
95 375
        return $this;
96
    }
97
98
    /**
99
     * @param int $n
100
     * @return $this
101
     */
102
    public function int($n)
103
    {
104
        if ($n === 0) {
105
            $this->script .= chr(Opcodes::OP_0);
106
        } else if ($n === -1 || ($n >= 1 && $n <= 16)) {
107
            $this->script .= chr($n + (Opcodes::OP_1 - 1));
108
        } else {
109
            $this->script .= Number::int($n)->getBinary();
110
        }
111
112
        return $this;
113
    }
114
115
    /**
116
     * @param Serializable $object
117
     * @return $this
118
     */
119
    public function pushSerializable(Serializable $object)
120
    {
121
        $this->push($object->getBuffer());
122
        return $this;
123
    }
124
125
    /**
126
     * @param Serializable[] $serializable
127
     * @return $this
128
     */
129
    public function pushSerializableArray(array $serializable)
130
    {
131
        foreach ($serializable as $object) {
132
            $this->pushSerializable($object);
133
        }
134
135
        return $this;
136
    }
137
138
    /**
139
     * @param ScriptInterface $script
140
     * @return $this
141
     */
142 6
    public function concat(ScriptInterface $script)
143
    {
144 6
        $this->script .= $script->getBinary();
145 6
        return $this;
146
    }
147
148
    /**
149
     * @return ScriptInterface
150
     */
151 1119
    public function getScript()
152
    {
153 1119
        return new Script(new Buffer($this->script, null, $this->math), $this->opcodes);
154
    }
155
}
156