Completed
Branch master (b7c8d8)
by
unknown
28:56 queued 12:06
created

WalletV1::unlock()   C

Complexity

Conditions 15
Paths 144

Size

Total Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 15.8185

Importance

Changes 0
Metric Value
cc 15
nc 144
nop 2
dl 0
loc 49
ccs 22
cts 26
cp 0.8462
crap 15.8185
rs 5.55
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Blocktrail\SDK;
4
5
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
6
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory;
7
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
8
use Blocktrail\SDK\Address\AddressReaderBase;
9
use Blocktrail\SDK\Bitcoin\BIP32Key;
10
use Blocktrail\SDK\Exceptions\BlocktrailSDKException;
11
use Blocktrail\SDK\Exceptions\NotImplementedException;
12
13
class WalletV1 extends Wallet {
14
15
    /**
16
     * BIP39 Mnemonic for the master primary private key
17
     *
18
     * @var string
19
     */
20
    protected $primaryMnemonic;
21
22
    /**
23
     * @param BlocktrailSDKInterface        $sdk                        SDK instance used to do requests
24
     * @param string                        $identifier                 identifier of the wallet
25
     * @param string                        $primaryMnemonic
26
     * @param BIP32Key[]                    $primaryPublicKeys
27
     * @param BIP32Key                      $backupPublicKey            should be BIP32 master public key M/
28
     * @param BIP32Key[]                    $blocktrailPublicKeys
29
     * @param int                           $keyIndex
30
     * @param string                        $network
31
     * @param bool                          $testnet
32
     * @param bool                          $segwit
33
     * @param AddressReaderBase             $addressReader
34
     * @param string                        $checksum
35
     * @throws                              BlocktrailSDKException
36
     */
37 5
    public function __construct(BlocktrailSDKInterface $sdk, $identifier, $primaryMnemonic, array $primaryPublicKeys, $backupPublicKey, array $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, AddressReaderBase $addressReader, $checksum) {
38 5
        $this->primaryMnemonic = $primaryMnemonic;
39
40 5
        parent::__construct($sdk, $identifier, $primaryPublicKeys, $backupPublicKey, $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, $addressReader, $checksum);
41 5
    }
42
43
    /**
44
     * unlock wallet so it can be used for payments
45
     *
46
     * @param          $options ['primary_private_key' => key] OR ['passphrase' => pass]
47
     * @param callable $fn
48
     * @return bool
49
     * @throws \Exception
50
     */
51 10
    public function unlock($options, callable $fn = null) {
52
        // explode the wallet data
53 10
        $password = isset($options['passphrase']) ? $options['passphrase'] : (isset($options['password']) ? $options['password'] : null);
54 10
        $primaryMnemonic = $this->primaryMnemonic;
55 10
        $primaryPrivateKey = isset($options['primary_private_key']) ? $options['primary_private_key'] : null;
56
57 10
        if ($primaryMnemonic && $primaryPrivateKey) {
58 1
            throw new \InvalidArgumentException("Can't specify Primary Mnemonic and Primary PrivateKey");
59
        }
60
61 10
        if (!$primaryMnemonic && !$primaryPrivateKey) {
62
            throw new \InvalidArgumentException("Can't init wallet without Primary Mnemonic or Primary PrivateKey");
63
        }
64
65 10
        if ($primaryMnemonic && !$password) {
66 1
            throw new \InvalidArgumentException("Can't init wallet with Primary Mnemonic without a passphrase");
67
        }
68
69 9
        if ($primaryPrivateKey) {
70
            if (!($primaryPrivateKey instanceof HierarchicalKey)) {
71
                $primaryPrivateKey = HierarchicalKeyFactory::fromExtended($primaryPrivateKey);
72
            }
73
        } else {
74
            // convert the mnemonic to a seed using BIP39 standard
75 9
            $primarySeed = (new Bip39SeedGenerator())->getSeed($primaryMnemonic, $password);
76
            // create BIP32 private key from the seed
77 9
            $primaryPrivateKey = HierarchicalKeyFactory::fromEntropy($primarySeed);
78
        }
79
80 9
        $this->primaryPrivateKey = BIP32Key::create($primaryPrivateKey, "m");
81
82
        // create checksum (address) of the primary privatekey to compare to the stored checksum
83 9
        $checksum = $this->primaryPrivateKey->key()->getPublicKey()->getAddress()->getAddress();
84 9
        if ($checksum != $this->checksum) {
85 2
            throw new \Exception("Checksum [{$checksum}] does not match [{$this->checksum}], most likely due to incorrect password");
86
        }
87
88 7
        $this->locked = false;
89
90
        // if the response suggests we should upgrade to a different blocktrail cosigning key then we should
91 7
        if (array_key_exists('upgrade_key_index', $options)) {
92
            $this->upgradeKeyIndex($options['upgrade_key_index']);
93
        }
94
95 7
        if ($fn) {
96 1
            $fn($this);
97 1
            $this->lock();
98
        }
99 7
    }
100
101
    /**
102
     * lock the wallet (unsets primary private key)
103
     *
104
     * @return void
105
     */
106 5
    public function lock() {
107 5
        $this->primaryPrivateKey = null;
108 5
        $this->locked = true;
109 5
    }
110
111
    /**
112
     * change password that is used to store data encrypted on server
113
     *
114
     * @param $newPassword
115
     * @return array backupInfo
116
     * @throws NotImplementedException
117
     */
118 1
    public function passwordChange($newPassword) {
119 1
        throw new NotImplementedException();
120
    }
121
}
122