Method: Bitcoin::Descriptor::Expression#extract_pubkey

Defined in:
lib/bitcoin/descriptor/expression.rb

#extract_pubkey(key) ⇒ Bitcoin::Key

Extract public key from KEY format.

Parameters:

  • key (String)

    KEY string.

Returns:

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/bitcoin/descriptor/expression.rb', line 53

def extract_pubkey(key)
  if key.start_with?('[') # BIP32 fingerprint
    raise ArgumentError, "Multiple ']' characters found for a single pubkey." if key.count('[') > 1 || key.count(']') > 1
    info = key[1...key.index(']')]
    fingerprint, *paths = info.split('/')
    raise ArgumentError, "Fingerprint '#{fingerprint}' is not hex." unless fingerprint.valid_hex?
    raise ArgumentError, "Fingerprint '#{fingerprint}' is not 4 bytes." unless fingerprint.size == 8
    key = key[(key.index(']') + 1)..-1]
  else
    raise ArgumentError, 'Invalid key origin.' if key.include?(']')
  end

  # check BIP32 derivation path
  key, *paths = key.split('/')

  raise ArgumentError, "No key provided." unless key

  if key.start_with?('xprv')
    key = Bitcoin::ExtKey.from_base58(key)
    key = derive_path(key, paths) if paths
  elsif key.start_with?('xpub')
    key = Bitcoin::ExtPubkey.from_base58(key)
    key = derive_path(key, paths) if paths
  else
    begin
      key = Bitcoin::Key.from_wif(key)
    rescue ArgumentError
      key = if key.length == 64
              Bitcoin::Key.from_xonly_pubkey(key)
            else
              key_type = compressed_key?(key) ? Bitcoin::Key::TYPES[:compressed] : Bitcoin::Key::TYPES[:uncompressed]
              Bitcoin::Key.new(pubkey: key, key_type: key_type)
            end
    end
  end
  key = key.is_a?(Bitcoin::Key) ? key : key.key
  raise ArgumentError, Errors::Messages::INVALID_PUBLIC_KEY unless key.fully_valid_pubkey?
  key
end