MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / ParseKeyPath

Function ParseKeyPath

src/script/descriptor.cpp:1851–1915  ·  view source on GitHub ↗

* Parse a key path, being passed a split list of elements (the first element is ignored because it is always the key). * * @param[in] split BIP32 path string, using either ' or h for hardened derivation * @param[out] out Vector of parsed key paths * @param[out] apostrophe only updated if hardened derivation is found * @param[out] error parsing error message * @param[in] allow_multipath Allow

Source from the content-addressed store, hash-verified

1849 * @returns false if parsing failed
1850 **/
1851[[nodiscard]] bool ParseKeyPath(const std::vector<std::span<const char>>& split, std::vector<KeyPath>& out, bool& apostrophe, std::string& error, bool allow_multipath, bool& has_hardened)
1852{
1853 KeyPath path;
1854 struct MultipathSubstitutes {
1855 size_t placeholder_index;
1856 std::vector<uint32_t> values;
1857 };
1858 std::optional<MultipathSubstitutes> substitutes;
1859 has_hardened = false;
1860
1861 for (size_t i = 1; i < split.size(); ++i) {
1862 const std::span<const char>& elem = split[i];
1863
1864 // Check if element contains multipath specifier
1865 if (!elem.empty() && elem.front() == '<' && elem.back() == '>') {
1866 if (!allow_multipath) {
1867 error = strprintf("Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1868 return false;
1869 }
1870 if (substitutes) {
1871 error = "Multiple multipath key path specifiers found";
1872 return false;
1873 }
1874
1875 // Parse each possible value
1876 std::vector<std::span<const char>> nums = Split(std::span(elem.begin()+1, elem.end()-1), ";");
1877 if (nums.size() < 2) {
1878 error = "Multipath key path specifiers must have at least two items";
1879 return false;
1880 }
1881
1882 substitutes.emplace();
1883 std::unordered_set<uint32_t> seen_substitutes;
1884 for (const auto& num : nums) {
1885 const auto& op_num = ParseKeyPathNum(num, apostrophe, error, has_hardened);
1886 if (!op_num) return false;
1887 auto [_, inserted] = seen_substitutes.insert(*op_num);
1888 if (!inserted) {
1889 error = strprintf("Duplicated key path value %u in multipath specifier", *op_num);
1890 return false;
1891 }
1892 substitutes->values.emplace_back(*op_num);
1893 }
1894
1895 path.emplace_back(); // Placeholder for multipath segment
1896 substitutes->placeholder_index = path.size() - 1;
1897 } else {
1898 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error, has_hardened);
1899 if (!op_num) return false;
1900 path.emplace_back(*op_num);
1901 }
1902 }
1903
1904 if (!substitutes) {
1905 out.emplace_back(std::move(path));
1906 } else {
1907 // Replace the multipath placeholder with each value while generating paths
1908 for (uint32_t substitute : substitutes->values) {

Callers 2

ParsePubkeyInnerFunction · 0.85
ParsePubkeyFunction · 0.85

Calls 11

ParseKeyPathNumFunction · 0.85
emplaceMethod · 0.80
SplitFunction · 0.50
sizeMethod · 0.45
emptyMethod · 0.45
frontMethod · 0.45
backMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
insertMethod · 0.45
emplace_backMethod · 0.45

Tested by

no test coverage detected