Completed
Pull Request — master (#517)
by thomas
73:24
created

SegwitBech32::decode()   C

Complexity

Conditions 8
Paths 14

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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