Completed
Pull Request — master (#517)
by thomas
68:51 queued 66:33
created

SegwitBech32::decode()   C

Complexity

Conditions 8
Paths 14

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 19
nc 14
nop 2
dl 0
loc 32
ccs 19
cts 19
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
        $network = $network ?: Bitcoin::getNetwork();
24 14
        $hrp = $network->getSegwitBech32Prefix();
25
26 14
        $programChars = array_values(unpack('C*', $witnessProgram->getProgram()->getBinary()));
27 14
        $programBits = Bech32::convertBits($programChars, count($programChars), 8, 5, true);
28 14
        $encodeData = array_merge([$witnessProgram->getVersion()], $programBits);
29
30 14
        return Bech32::encode($hrp, $encodeData);
31
    }
32
33
    /**
34
     * Decodes the provided $bech32 string, validating against
35
     * the chosen prefix.
36
     *
37
     * @param string $bech32
38
     * @param NetworkInterface $network
39
     * @return WitnessProgram
40
     * @throws Bech32Exception
41
     */
42 40
    public static function decode($bech32, NetworkInterface $network = null)
43
    {
44 40
        $network = $network ?: Bitcoin::getNetwork();
45 40
        $hrp = $network->getSegwitBech32Prefix();
46
47 40
        list ($hrpGot, $data) = Bech32::decode($bech32);
48 36
        if ($hrpGot !== $hrp) {
49 14
            throw new Bech32Exception('Invalid prefix for address');
50
        }
51
52 34
        $decoded = Bech32::convertBits(array_slice($data, 1), count($data) - 1, 5, 8, false);
53 30
        $decodeLen = count($decoded);
54 30
        if ($decodeLen < 2 || $decodeLen > 40) {
55 4
            throw new Bech32Exception('Invalid segwit address');
56
        }
57
58 26
        if ($data[0] > 16) {
59 2
            throw new Bech32Exception('Invalid witness program version');
60
        }
61
62 24
        $bytes = '';
63 24
        foreach ($decoded as $char) {
64 24
            $bytes .= chr($char);
65
        }
66 24
        $decoded = new Buffer($bytes);
67
68 24
        if (0 === $data[0]) {
69 18
            return WitnessProgram::v0($decoded);
70
        }
71
72 6
        return new WitnessProgram($data[0], $decoded);
73
    }
74
}
75