Completed
Pull Request — master (#88)
by thomas
05:05
created

WalletV1::unlock()   D

Complexity

Conditions 15
Paths 144

Size

Total Lines 49
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 240

Importance

Changes 0
Metric Value
cc 15
eloc 26
nc 144
nop 2
dl 0
loc 49
ccs 0
cts 26
cp 0
crap 240
rs 4.8048
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\Bitcoin\BIP32Key;
9
use Blocktrail\SDK\Exceptions\NotImplementedException;
10
11
class WalletV1 extends Wallet {
12
13
    /**
14
     * BIP39 Mnemonic for the master primary private key
15
     *
16
     * @var string
17
     */
18
    protected $primaryMnemonic;
19
20
    /**
21
     * @param BlocktrailSDKInterface        $sdk                        SDK instance used to do requests
22
     * @param string                        $identifier                 identifier of the wallet
23
     * @param string                        $primaryMnemonic
24
     * @param BIP32Key[]                    $primaryPublicKeys
25
     * @param BIP32Key                      $backupPublicKey            should be BIP32 master public key M/
26
     * @param BIP32Key[]                    $blocktrailPublicKeys
27
     * @param int                           $keyIndex
28
     * @param string                        $network
29
     * @param bool                          $testnet
30
     * @param string                        $checksum
31
     */
32 9
    public function __construct(BlocktrailSDKInterface $sdk, $identifier, $primaryMnemonic, array $primaryPublicKeys, $backupPublicKey, array $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, $checksum) {
33 9
        $this->primaryMnemonic = $primaryMnemonic;
34
35 9
        parent::__construct($sdk, $identifier, $primaryPublicKeys, $backupPublicKey, $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, $checksum);
36
    }
37
38
    /**
39
     * unlock wallet so it can be used for payments
40
     *
41
     * @param          $options ['primary_private_key' => key] OR ['passphrase' => pass]
42
     * @param callable $fn
43
     * @return bool
44
     * @throws \Exception
45
     */
46
    public function unlock($options, callable $fn = null) {
47
        // explode the wallet data
48
        $password = isset($options['passphrase']) ? $options['passphrase'] : (isset($options['password']) ? $options['password'] : null);
49
        $primaryMnemonic = $this->primaryMnemonic;
50
        $primaryPrivateKey = isset($options['primary_private_key']) ? $options['primary_private_key'] : null;
51
52
        if ($primaryMnemonic && $primaryPrivateKey) {
53
            throw new \InvalidArgumentException("Can't specify Primary Mnemonic and Primary PrivateKey");
54
        }
55
56
        if (!$primaryMnemonic && !$primaryPrivateKey) {
57
            throw new \InvalidArgumentException("Can't init wallet without Primary Mnemonic or Primary PrivateKey");
58
        }
59
60
        if ($primaryMnemonic && !$password) {
61
            throw new \InvalidArgumentException("Can't init wallet with Primary Mnemonic without a passphrase");
62
        }
63
64
        if ($primaryPrivateKey) {
65
            if (!($primaryPrivateKey instanceof HierarchicalKey)) {
66
                $primaryPrivateKey = HierarchicalKeyFactory::fromExtended($primaryPrivateKey);
67
            }
68
        } else {
69
            // convert the mnemonic to a seed using BIP39 standard
70
            $primarySeed = (new Bip39SeedGenerator())->getSeed($primaryMnemonic, $password);
71
            // create BIP32 private key from the seed
72
            $primaryPrivateKey = HierarchicalKeyFactory::fromEntropy($primarySeed);
73
        }
74
75
        $this->primaryPrivateKey = BIP32Key::create($primaryPrivateKey, "m");
76
77
        // create checksum (address) of the primary privatekey to compare to the stored checksum
78
        $checksum = $this->primaryPrivateKey->key()->getPublicKey()->getAddress()->getAddress();
79
        if ($checksum != $this->checksum) {
80
            throw new \Exception("Checksum [{$checksum}] does not match [{$this->checksum}], most likely due to incorrect password");
81
        }
82
83
        $this->locked = false;
84
85
        // if the response suggests we should upgrade to a different blocktrail cosigning key then we should
86
        if (isset($data['upgrade_key_index'])) {
0 ignored issues
show
Bug introduced by
The variable $data seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
87
            $this->upgradeKeyIndex($data['upgrade_key_index']);
88
        }
89
90
        if ($fn) {
91
            $fn($this);
92
            $this->lock();
93
        }
94
    }
95
96
    /**
97
     * lock the wallet (unsets primary private key)
98
     *
99
     * @return void
100
     */
101
    public function lock() {
102
        $this->primaryPrivateKey = null;
103
        $this->locked = true;
104
    }
105
106
    /**
107
     * change password that is used to store data encrypted on server
108
     *
109
     * @param $newPassword
110
     * @return array backupInfo
111
     * @throws NotImplementedException
112
     */
113
    public function passwordChange($newPassword) {
114
        throw new NotImplementedException();
115
    }
116
}
117