Completed
Pull Request — master (#517)
by thomas
20:48
created

SegwitBech32::decode()   C

Complexity

Conditions 8
Paths 14

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 18
nc 14
nop 2
dl 0
loc 31
ccs 18
cts 18
cp 1
crap 8
rs 5.3846
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin;
4
5
use BitWasp\Bitcoin\Exceptions\Bech32Exception;
6
use BitWasp\Bitcoin\Network\NetworkInterface;
7
use BitWasp\Bitcoin\Script\WitnessProgram;
8
use BitWasp\Buffertools\Buffer;
9
10
class SegwitBech32
11
{
12
    /**
13
     * Takes the $hrp and $witnessProgram and produces a native segwit
14
     * address.
15
     *
16
     * @param WitnessProgram $witnessProgram
17
     * @param NetworkInterface $network
18
     * @return string
19
     */
20 14
    public static function encode(WitnessProgram $witnessProgram, NetworkInterface $network = null)
21
    {
22
        // do this first, why bother encoding if the network doesn't support it..
23 14
        $hrp = ($network ?: Bitcoin::getNetwork())->getSegwitBech32Prefix();
24 14
        $programChars = array_values(unpack('C*', $witnessProgram->getProgram()->getBinary()));
25 14
        $programBits = Bech32::convertBits($programChars, count($programChars), 8, 5, true);
26 14
        $encodeData = array_merge([$witnessProgram->getVersion()], $programBits);
27
28 14
        return Bech32::encode($hrp, $encodeData);
29
    }
30
31
    /**
32
     * Decodes the provided $bech32 string, validating against
33
     * the chosen prefix.
34
     *
35
     * @param string $bech32
36
     * @param NetworkInterface $network
37
     * @return WitnessProgram
38
     * @throws Bech32Exception
39
     */
40 40
    public static function decode($bech32, NetworkInterface $network = null)
41
    {
42 40
        $hrp = ($network ? $network : Bitcoin::getNetwork())->getSegwitBech32Prefix();
43
44 40
        list ($hrpGot, $data) = Bech32::decode($bech32);
45 36
        if ($hrpGot !== $hrp) {
46 14
            throw new Bech32Exception('Invalid prefix for address');
47
        }
48
49 34
        $decoded = Bech32::convertBits(array_slice($data, 1), count($data) - 1, 5, 8, false);
50 30
        $decodeLen = count($decoded);
51 30
        if ($decodeLen < 2 || $decodeLen > 40) {
52 4
            throw new Bech32Exception('Invalid segwit address');
53
        }
54
55 26
        if ($data[0] > 16) {
56 2
            throw new Bech32Exception('Invalid witness program version');
57
        }
58
59 24
        $bytes = '';
60 24
        foreach ($decoded as $char) {
61 24
            $bytes .= chr($char);
62
        }
63 24
        $decoded = new Buffer($bytes);
64
65 24
        if (0 === $data[0]) {
66 18
            return WitnessProgram::v0($decoded);
67
        }
68
69 6
        return new WitnessProgram($data[0], $decoded);
70
    }
71
}
72