Class: Stellar::Util::StrKey

Inherits:
Object
  • Object
show all
Defined in:
lib/stellar/util/strkey.rb

Constant Summary collapse

VERSION_BYTES =
{
  account_id: [6 << 3].pack("C"), # Base32-encodes to 'G...'
  seed: [18 << 3].pack("C"), # Base32-encodes to 'S...'
  pre_auth_tx: [19 << 3].pack("C"), # Base32-encodes to 'T...'
  hash_x: [23 << 3].pack("C") # Base32-encodes to 'X...'
}

Class Method Summary collapse

Class Method Details

.check_decode(expected_version, str) ⇒ Object

Raises:

  • (ArgumentError)

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/stellar/util/strkey.rb', line 45

def self.check_decode(expected_version, str)
  decoded = begin
    Base32.decode(str)
  rescue
    raise ArgumentError, "Invalid base32 string"
  end
  version_byte = decoded[0]
  payload = decoded[1...-2]
  check = decoded[-2..-1]
  version = VERSION_BYTES.key(version_byte)

  raise ArgumentError, "invalid encoded string" if str != Base32.encode(decoded).tr("=", "")
  raise ArgumentError, "Unexpected version: #{version.inspect}" if version != expected_version
  raise ArgumentError, "Invalid checksum" if check != checksum(decoded[0...-2])
  payload
end

.check_encode(version, byte_str) ⇒ Object

Raises:

  • (ArgumentError)

14
15
16
17
18
19
20
21
22
# File 'lib/stellar/util/strkey.rb', line 14

def self.check_encode(version, byte_str)
  version_byte = VERSION_BYTES[version]
  raise ArgumentError, "Invalid version: #{version}" if version_byte.blank?
  payload = version_byte + byte_str.dup.force_encoding("BINARY")
  check = checksum(payload)
  # TODO: sort out, is it 100% safe to remove padding
  # SEP-23 says yes, but shit happens
  Base32.encode(payload + check).tr("=", "")
end

.checksum(bytes) ⇒ Object

return the “XModem CRC16” (CCITT-like, but with 0-init and MSB first) packed into a string in little-endian order


64
65
66
67
# File 'lib/stellar/util/strkey.rb', line 64

def self.checksum(bytes)
  crc = Digest::CRC16XModem.checksum(bytes)
  [crc].pack("S<")
end

.decode_muxed_account(strkey) ⇒ Stellar::MuxedAccount

Returns a Stellar::MuxedAccount, forcing the ed25519 discriminant

Parameters:

  • strkey (String)

    address string to decode

Returns:


41
42
43
# File 'lib/stellar/util/strkey.rb', line 41

def self.(strkey)
  Stellar::MuxedAccount.new(:key_type_ed25519, check_decode(:account_id, strkey))
end

.encode_muxed_account(muxed_account) ⇒ String

Converts an Stellar::MuxedAccount to its string representation, forcing the ed25519 representation.

Parameters:

Returns:

  • (String)

    “G..”-like address


27
28
29
30
31
32
33
34
35
# File 'lib/stellar/util/strkey.rb', line 27

def self.()
  ed25519 = if .switch == Stellar::CryptoKeyType.key_type_ed25519
    .ed25519!
  else
    .med25519!.ed25519
  end

  check_encode(:account_id, ed25519)
end