git / moonbite-core / src/libmw/include/mw/models/wallet/KeyChainPath.h · raw

#pragma once// Copyright (c) 2018-2020 David Burkett// Distributed under the MIT software license, see the accompanying// file LICENSE or http://www.opensource.org/licenses/mit-license.php.#include <mw/common/Traits.h>#include <mw/exceptions/DeserializationException.h>#include <cstdint>#include <string>#include <vector>static const uint32_t MINIMUM_HARDENED_INDEX = 0x80000000;class KeyChainPath : public Traits::IPrintable{public:    KeyChainPath(std::vector<uint32_t> keyIndices)        : m_keyIndices(std::move(keyIndices)) { }    //    // Operators    //    bool operator<(const KeyChainPath& other) const { return GetKeyIndices() < other.GetKeyIndices(); }    bool operator==(const KeyChainPath& other) const { return GetKeyIndices() == other.GetKeyIndices(); }    bool operator!=(const KeyChainPath& other) const { return GetKeyIndices() != other.GetKeyIndices(); }    const std::vector<uint32_t>& GetKeyIndices() const { return m_keyIndices; }    /// <summary>    /// Example format: m/0/2'/500    /// </summary>    /// <returns>The formatted BIP32 keychain path.</returns>    std::string Format() const final    {        std::string path = "m";        for (const uint32_t keyIndex : m_keyIndices) {            path += "/";                        if (keyIndex < MINIMUM_HARDENED_INDEX) {                path += std::to_string(keyIndex);            } else {                path += std::to_string(keyIndex - MINIMUM_HARDENED_INDEX) + "'";            }        }        return path;    }    static KeyChainPath FromString(const std::string& path)    {        if (path.empty() || path.at(0) != 'm') {            ThrowDeserialization_F("Invalid path: {}", path);        }        std::vector<uint32_t> indices;        std::vector<std::string> str_indices = StringUtil::Split(path, "/");        for (size_t i = 1; i < str_indices.size(); i++) {            uint32_t key_index = 0;            std::string str_index = str_indices[i];            if (str_index.empty()) {                ThrowDeserialization_F("Invalid path: {}", path);            }            if (str_index.back() == '\'') {                key_index = MINIMUM_HARDENED_INDEX;                str_index = str_index.substr(0, str_index.size() - 1);            }            key_index += std::stoul(str_index);            indices.push_back(key_index);        }        return KeyChainPath(std::move(indices));    }    KeyChainPath GetFirstChild() const    {        std::vector<uint32_t> keyIndicesCopy = m_keyIndices;        keyIndicesCopy.push_back(0);        return KeyChainPath(std::move(keyIndicesCopy));    }    KeyChainPath GetChild(const uint32_t childIndex) const    {        std::vector<uint32_t> keyIndicesCopy = m_keyIndices;        keyIndicesCopy.push_back(childIndex);        return KeyChainPath(std::move(keyIndicesCopy));    }    KeyChainPath GetNextSibling() const    {        assert(!m_keyIndices.empty());        std::vector<uint32_t> keyIndicesCopy = m_keyIndices;        keyIndicesCopy.back()++;        return KeyChainPath(std::move(keyIndicesCopy));    }private:    std::vector<uint32_t> m_keyIndices;};