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

WalletV1::lock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
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