Completed
Pull Request — master (#517)
by thomas
71:26 queued 02:33
created

AddressFactory::fromWitnessProgram()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Address;
4
5
use BitWasp\Bitcoin\Base58;
6
use BitWasp\Bitcoin\Bitcoin;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\KeyInterface;
8
use BitWasp\Bitcoin\Key\PublicKeyFactory;
9
use BitWasp\Bitcoin\Network\NetworkInterface;
10
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
11
use BitWasp\Bitcoin\Script\ScriptInterface;
12
use BitWasp\Bitcoin\Script\ScriptType;
13
use BitWasp\Bitcoin\Script\WitnessProgram;
14
use BitWasp\Bitcoin\SegwitBech32;
15
use BitWasp\Buffertools\BufferInterface;
16
17
class AddressFactory
18
{
19
    /**
20
     * Returns a pay-to-pubkey-hash address for the given public key
21
     *
22
     * @param KeyInterface $key
23 44
     * @return PayToPubKeyHashAddress
24
     */
25 44
    public static function fromKey(KeyInterface $key)
26
    {
27
        return new PayToPubKeyHashAddress($key->getPubKeyHash());
28
    }
29
30
    /**
31
     * Takes the $p2shScript and generates the scriptHash address.
32
     *
33
     * @param ScriptInterface $p2shScript
34 12
     * @return ScriptHashAddress
35
     */
36 12
    public static function fromScript(ScriptInterface $p2shScript)
37
    {
38
        return new ScriptHashAddress($p2shScript->getScriptHash());
39
    }
40
41
    /**
42
     * @param WitnessProgram $wp
43 8
     * @return SegwitAddress
44
     */
45 8
    public static function fromWitnessProgram(WitnessProgram $wp)
46 8
    {
47 8
        return new SegwitAddress($wp);
48
    }
49 4
50 6
    /**
51
     * @param ScriptInterface $outputScript
52 2
     * @return AddressInterface
53
     */
54 4
    public static function fromOutputScript(ScriptInterface $outputScript)
55
    {
56
        $wp = null;
57
        if ($outputScript->isWitness($wp)) {
58
            /** @var WitnessProgram $wp */
59
            return new SegwitAddress($wp);
60
        }
61
62
        $decode = (new OutputClassifier())->decode($outputScript);
63
        switch ($decode->getType()) {
64 42
            case ScriptType::P2PKH:
65
                /** @var BufferInterface $solution */
66 42
                return new PayToPubKeyHashAddress($decode->getSolution());
67 42
            case ScriptType::P2SH:
68 42
                /** @var BufferInterface $solution */
69
                return new ScriptHashAddress($decode->getSolution());
70 42
            default:
71 8
                throw new \RuntimeException('Script type is not associated with an address');
72 34
        }
73 32
    }
74
75 2
    /**
76
     * @param string $address
77
     * @param NetworkInterface $network
78
     * @return AddressInterface
79
     * @throws \BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure
80
     */
81
    public static function fromString($address, NetworkInterface $network = null)
82
    {
83
        $network = $network ?: Bitcoin::getNetwork();
84
85 26
        try {
86
            $data = Base58::decodeCheck($address);
87
            $prefixByte = $data->slice(0, 1)->getHex();
88 26
89 24
            if ($prefixByte === $network->getP2shByte()) {
90 2
                return new ScriptHashAddress($data->slice(1));
91 2
            } else if ($prefixByte === $network->getAddressByte()) {
92
                return new PayToPubKeyHashAddress($data->slice(1));
93
            }
94 26
        } catch (\Exception $e) {
95
            // continue on for Bech32
96
        }
97
98
        try {
99
            return new SegwitAddress(SegwitBech32::decode($address, $network));
100
        } catch (\Exception $e) {
101
            // continue on
102
        }
103
104
        throw new \InvalidArgumentException("Address not recognized");
105 4
    }
106
107 4
    /**
108 4
     * @param string $address
109 4
     * @param NetworkInterface $network
110 2
     * @return bool
111
     * @throws \BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure
112 4
     */
113
    public static function isValidAddress($address, NetworkInterface $network = null)
114
    {
115
        try {
116
            self::fromString($address, $network);
117
            $is_valid = true;
118
        } catch (\Exception $e) {
119
            $is_valid = false;
120
        }
121
122
        return $is_valid;
123
    }
124
125
    /**
126
     * Following a loose definition of 'associated', returns
127
     * the current script types, and a PayToPubKeyHash address for P2PK.
128
     *
129
     * @param ScriptInterface $script
130
     * @return AddressInterface
131
     * @throws \RuntimeException
132
     */
133
    public static function getAssociatedAddress(ScriptInterface $script)
134
    {
135
        $classifier = new OutputClassifier();
136
        $decode = $classifier->decode($script);
137
        if ($decode->getType() === ScriptType::P2PK) {
138
            return PublicKeyFactory::fromHex($decode->getSolution())->getAddress();
139
        } else {
140
            return self::fromOutputScript($script);
141
        }
142
    }
143
}
144