2015-07-22 20:23:42 +00:00
|
|
|
#pragma once
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
|
|
|
|
|
|
|
|
|
#include <graphene/chain/protocol/types.hpp>
|
2015-07-29 19:50:12 +00:00
|
|
|
|
2015-07-22 20:23:42 +00:00
|
|
|
#include <QObject>
|
2015-07-23 13:32:29 +00:00
|
|
|
#include <QList>
|
|
|
|
|
#include <QPair>
|
2015-07-29 19:50:12 +00:00
|
|
|
#include <QtQml>
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::set;
|
|
|
|
|
using fc::flat_set;
|
|
|
|
|
using std::map;
|
|
|
|
|
using graphene::chain::public_key_type;
|
|
|
|
|
using graphene::chain::digest_type;
|
|
|
|
|
using graphene::chain::signature_type;
|
|
|
|
|
using fc::optional;
|
|
|
|
|
|
2015-07-29 21:56:37 +00:00
|
|
|
class Transaction;
|
|
|
|
|
|
2015-07-29 19:50:12 +00:00
|
|
|
QString toQString(public_key_type k);
|
2015-07-23 14:56:07 +00:00
|
|
|
|
2015-07-22 20:23:42 +00:00
|
|
|
struct key_data
|
|
|
|
|
{
|
|
|
|
|
string label; /** unique label assigned to this key */
|
2015-07-23 13:32:29 +00:00
|
|
|
/** encrypted as a packed std::string containing a wif private key */
|
2015-07-23 14:56:07 +00:00
|
|
|
vector<char> encrypted_private_key;
|
|
|
|
|
int32_t brain_sequence = -1;
|
|
|
|
|
optional<public_key_type> owner; /// if this key was derived from an owner key + sequence
|
2015-07-22 20:23:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct wallet_file
|
|
|
|
|
{
|
2015-07-22 20:59:22 +00:00
|
|
|
vector<char> encrypted_brain_key;
|
|
|
|
|
fc::sha512 brain_key_digest;
|
|
|
|
|
vector<char> encrypted_master_key;
|
|
|
|
|
fc::sha512 master_key_digest;
|
2015-07-22 20:23:42 +00:00
|
|
|
map<public_key_type, key_data> encrypted_private_keys;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @class Wallet
|
|
|
|
|
* @brief Securely maintains a set of labeled public and private keys
|
2015-07-23 13:32:29 +00:00
|
|
|
*
|
|
|
|
|
* @note this API is designed for use with QML which does not support exceptions so
|
|
|
|
|
* all errors are passed via return values.
|
2015-07-22 20:23:42 +00:00
|
|
|
*/
|
|
|
|
|
class Wallet : public QObject
|
|
|
|
|
{
|
2015-07-23 14:56:07 +00:00
|
|
|
Q_OBJECT
|
2015-07-24 19:55:58 +00:00
|
|
|
Q_PROPERTY(bool isOpen READ isOpen NOTIFY isOpenChanged)
|
|
|
|
|
Q_PROPERTY(bool isLocked READ isLocked NOTIFY isLockedChanged)
|
2015-07-22 20:23:42 +00:00
|
|
|
public:
|
2015-07-23 14:56:07 +00:00
|
|
|
Wallet( QObject* parent = nullptr );
|
2015-07-22 20:23:42 +00:00
|
|
|
~Wallet();
|
|
|
|
|
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool open(QString file_path);
|
2015-07-22 20:23:42 +00:00
|
|
|
Q_INVOKABLE bool close();
|
2015-07-29 19:50:12 +00:00
|
|
|
bool isOpen()const;
|
2015-07-22 20:23:42 +00:00
|
|
|
Q_INVOKABLE bool save();
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool saveAs(QString file_path);
|
|
|
|
|
Q_INVOKABLE bool create(QString file_path, QString password, QString brain_key = QString());
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/** required to generate new owner keys */
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool loadBrainKey(QString brain_key);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/** removes brain key to secure owner keys */
|
|
|
|
|
Q_INVOKABLE bool purgeBrainKey();
|
|
|
|
|
Q_INVOKABLE bool hasBrainKey()const;
|
|
|
|
|
|
|
|
|
|
/** @pre hasBrainKey() */
|
2015-07-22 20:59:22 +00:00
|
|
|
Q_INVOKABLE QString getBrainKey();
|
2015-07-22 20:23:42 +00:00
|
|
|
|
2015-07-29 19:50:12 +00:00
|
|
|
bool isLocked()const;
|
|
|
|
|
Q_INVOKABLE bool unlock(QString password);
|
2015-07-22 22:37:00 +00:00
|
|
|
Q_INVOKABLE bool lock();
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool changePassword(QString new_password);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @pre !isLocked();
|
|
|
|
|
* @post save()
|
2015-07-24 17:57:47 +00:00
|
|
|
* @return WIF private key
|
2015-07-22 20:23:42 +00:00
|
|
|
*/
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE QString getActivePrivateKey(QString owner_public_key, uint32_t sequence);
|
|
|
|
|
Q_INVOKABLE QString getActivePublicKey(QString owner_public_key, uint32_t sequence);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @pre !isLocked();
|
|
|
|
|
* @pre hasBrainKey();
|
|
|
|
|
* @post save()
|
2015-07-24 17:57:47 +00:00
|
|
|
* @return WIF private key
|
2015-07-22 20:23:42 +00:00
|
|
|
*/
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE QString getOwnerPrivateKey(uint32_t sequence);
|
|
|
|
|
Q_INVOKABLE QString getOwnerPublicKey(uint32_t sequence);
|
|
|
|
|
Q_INVOKABLE QString getPublicKey(QString wif_private_key)const;
|
2015-07-22 20:23:42 +00:00
|
|
|
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE QString getKeyLabel(QString pubkey);
|
|
|
|
|
Q_INVOKABLE bool setKeyLabel(QString pubkey, QString label);
|
|
|
|
|
Q_INVOKABLE QString getPublicKey(QString label);
|
|
|
|
|
Q_INVOKABLE QString getPrivateKey(QString pubkey);
|
|
|
|
|
Q_INVOKABLE bool hasPrivateKey(QString pubkey, bool include_with_brain_key = false);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/** imports a public key and assigns it a label */
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool importPublicKey(QString pubkey, QString label = QString());
|
2015-07-22 20:23:42 +00:00
|
|
|
|
2015-07-24 17:57:47 +00:00
|
|
|
/**
|
2015-07-22 20:23:42 +00:00
|
|
|
* @param wifkey a private key in (WIF) Wallet Import Format
|
2015-07-24 17:57:47 +00:00
|
|
|
* @pre !isLocked()
|
2015-07-22 20:23:42 +00:00
|
|
|
**/
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool importPrivateKey(QString wifkey, QString label = QString());
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/** removes the key, its lablel and its private key */
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool removePublicKey(QString pubkey);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/** removes only the private key, keeping the public key and label */
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE bool removePrivateKey(QString pubkey);
|
2015-07-22 20:23:42 +00:00
|
|
|
|
2015-07-23 13:32:29 +00:00
|
|
|
/**
|
|
|
|
|
* @param only_if_private filter any public keys for which the wallet lacks a private key
|
|
|
|
|
* @return a list of PUBLICKEY, LABEL for all known public keys
|
|
|
|
|
*/
|
2015-07-29 19:50:12 +00:00
|
|
|
Q_INVOKABLE QList<QPair<QString,QString>> getAllPublicKeys(bool only_if_private)const;
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @pre !isLocked()
|
|
|
|
|
*/
|
2015-07-29 21:56:37 +00:00
|
|
|
Q_INVOKABLE void sign(Transaction* transaction) const;
|
2015-07-29 19:50:12 +00:00
|
|
|
vector<signature_type> signDigest(const digest_type& d,
|
|
|
|
|
const set<public_key_type>& keys)const;
|
2015-07-22 20:23:42 +00:00
|
|
|
|
|
|
|
|
const flat_set<public_key_type>& getAvailablePrivateKeys()const;
|
|
|
|
|
|
2015-07-23 14:56:07 +00:00
|
|
|
Q_SIGNALS:
|
2015-07-29 19:50:12 +00:00
|
|
|
void isLockedChanged(bool state);
|
|
|
|
|
void isOpenChanged(bool state);
|
2015-07-23 14:56:07 +00:00
|
|
|
|
2015-07-22 20:23:42 +00:00
|
|
|
private:
|
|
|
|
|
fc::path _wallet_file_path;
|
|
|
|
|
wallet_file _data;
|
2015-07-22 20:59:22 +00:00
|
|
|
/** used to decrypt all of the encrypted private keys */
|
2015-07-22 20:23:42 +00:00
|
|
|
fc::sha512 _decrypted_master_key;
|
|
|
|
|
flat_set<public_key_type> _available_private_keys;
|
|
|
|
|
map<QString,QString> _label_to_key;
|
2015-07-22 20:59:22 +00:00
|
|
|
QString _brain_key;
|
2015-07-22 20:23:42 +00:00
|
|
|
};
|
2015-07-29 19:50:12 +00:00
|
|
|
QML_DECLARE_TYPE(Wallet)
|
|
|
|
|
|
|
|
|
|
FC_REFLECT( key_data, (label)(encrypted_private_key)(brain_sequence)(owner) )
|
|
|
|
|
FC_REFLECT( wallet_file,
|
|
|
|
|
(encrypted_brain_key)
|
|
|
|
|
(brain_key_digest)
|
|
|
|
|
(encrypted_master_key)
|
|
|
|
|
(master_key_digest)
|
|
|
|
|
(encrypted_private_keys)
|
|
|
|
|
)
|