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

AddressFactory::fromWitnessProgram()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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