Module: Bluzelle::Utils

Included in:
Swarm::Client, Swarm::Cosmos
Defined in:
lib/bluzelle/utils.rb

Class Method Summary collapse

Class Method Details

.bech32_convert_bits(bytes, from_bits: 8, to_bits: 5, pad: false) ⇒ Object



57
58
59
# File 'lib/bluzelle/utils.rb', line 57

def bech32_convert_bits(bytes, from_bits: 8, to_bits: 5, pad: false)
  Bitcoin::Bech32.convert_bits(bytes, from_bits: from_bits, to_bits: to_bits, pad: pad)
end

.bech32_encode(prefix, word) ⇒ Object



53
54
55
# File 'lib/bluzelle/utils.rb', line 53

def bech32_encode(prefix, word)
  Bitcoin::Bech32.encode(prefix, word)
end

.bip32_from_seed(seed) ⇒ Object



81
82
83
# File 'lib/bluzelle/utils.rb', line 81

def bip32_from_seed(seed)
  MoneyTree::Master.new(seed_hex: seed)
end

.bip39_mnemonic_to_seed(mnemonic) ⇒ Object



61
62
63
# File 'lib/bluzelle/utils.rb', line 61

def bip39_mnemonic_to_seed(mnemonic)
  BipMnemonic.to_seed(mnemonic: mnemonic)
end

.compressed_pub_key(key) ⇒ Object



75
76
77
78
79
# File 'lib/bluzelle/utils.rb', line 75

def compressed_pub_key(key)
  public_key = key.public_key
  public_key.group.point_conversion_form = :compressed
  public_key.to_hex.rjust(66, '0')
end

.convert_lease(lease) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/bluzelle/utils.rb', line 102

def convert_lease(lease)
  return '0' if lease.nil?

  seconds = 0

  seconds += lease.dig(:days).nil? ? 0 : (lease.dig(:days).to_i * 24 * 60 * 60)
  seconds += lease.dig(:hours).nil? ? 0 : (lease.dig(:hours).to_i * 60 * 60)
  seconds += lease.dig(:minutes).nil? ? 0 : (lease.dig(:minutes).to_i * 60)
  seconds += lease.dig(:seconds).nil? ? 0 : lease.dig(:seconds).to_i

  (seconds / Constants::BLOCK_TIME_IN_SECONDS).to_s
end

.create_ec_pair(private_key) ⇒ Object



85
86
87
# File 'lib/bluzelle/utils.rb', line 85

def create_ec_pair(private_key)
  Bitcoin::Key.new(private_key, nil, { compressed: false })
end

.decode_json(str) ⇒ Object



161
162
163
# File 'lib/bluzelle/utils.rb', line 161

def decode_json(str)
  JSON.parse(str)
end

.ecdsa_sign(payload, private_key) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/bluzelle/utils.rb', line 149

def ecdsa_sign(payload, private_key)
  pk = Secp256k1::PrivateKey.new(privkey: hex_to_bin(private_key), raw: true)
  rs = pk.ecdsa_sign(payload)
  r = rs.slice(0, 32).read_string.reverse
  s = rs.slice(32, 32).read_string.reverse
  "#{r}#{s}"
end

.encode_json(obj) ⇒ Object



157
158
159
# File 'lib/bluzelle/utils.rb', line 157

def encode_json(obj)
  JSON.generate(obj)
end

.extract_error_message(str) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/bluzelle/utils.rb', line 169

def extract_error_message(str)
  offset1 = str.index(': ')

  return str if offset1.nil?

  prefix = str.slice(0, offset1)

  case prefix
  when 'insufficient fee'
    return str.slice(offset1 + 2, str.length)
  end

  offset2 = str.index(': ', offset1 + 1)
  str[(offset1 + 2)..(offset2 - 1)]
end

.get_address(pub_key) ⇒ Object



35
36
37
38
39
# File 'lib/bluzelle/utils.rb', line 35

def get_address(pub_key)
  hash = rmd_160_digest(sha_256_digest([pub_key].pack('H*')))
  word = bech32_convert_bits(to_bytes(hash))
  bech32_encode(Constants::PREFIX, word)
end

.get_ec_private_key(mnemonic) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/bluzelle/utils.rb', line 13

def get_ec_private_key(mnemonic)
  seed = bip39_mnemonic_to_seed(mnemonic)
  node = bip32_from_seed(seed)
  child = node.node_for_path(Constants::PATH)
  ec_pair = create_ec_pair(child.private_key.to_hex)
  ec_pair.priv
end

.get_ec_public_key_from_priv(priv) ⇒ Object



21
22
23
24
# File 'lib/bluzelle/utils.rb', line 21

def get_ec_public_key_from_priv(priv)
  key = open_key(priv)
  compressed_pub_key(key)
end

.hex_to_bin(hex_str) ⇒ Object



165
166
167
# File 'lib/bluzelle/utils.rb', line 165

def hex_to_bin(hex_str)
  [hex_str].pack('H*')
end

.make_random_string(length = 32) ⇒ Object



89
90
91
92
93
94
95
96
# File 'lib/bluzelle/utils.rb', line 89

def make_random_string(length = 32)
  random_string = ''
  chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.chars

  1.upto(length) { random_string << chars.sample }

  random_string
end

.open_key(priv) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/bluzelle/utils.rb', line 65

def open_key(priv)
  group = OpenSSL::PKey::EC::Group.new('secp256k1')
  key = OpenSSL::PKey::EC.new(group)

  key.private_key = OpenSSL::BN.new(priv, 16)
  key.public_key = group.generator.mul(key.private_key)

  key
end

.rmd_160_digest(hex) ⇒ Object



45
46
47
# File 'lib/bluzelle/utils.rb', line 45

def rmd_160_digest(hex)
  Digest::RMD160.digest hex
end

.sha_256_digest(hex) ⇒ Object



49
50
51
# File 'lib/bluzelle/utils.rb', line 49

def sha_256_digest(hex)
  Digest::SHA256.digest hex
end

.sort_hash(hash) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/bluzelle/utils.rb', line 115

def sort_hash(hash)
  hash_clone = hash.clone

  hash_clone.each do |key, value|
    hash_clone[key] = sort_hash(value) if value.is_a?(Hash)

    next unless value.is_a?(Array)

    arr = []

    hash_clone[key].each do |el|
      arr << sort_hash(el)
    end

    hash_clone[key] = arr
  end

  hash_clone.sort.to_h
end

.stringify_keys(hash) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/bluzelle/utils.rb', line 135

def stringify_keys(hash)
  res = {}

  hash.each do |key, value|
    if value.is_a?(Hash)
      res[key.to_s] = stringify_keys(value)
      next
    end
    res[key.to_s] = value
  end

  res
end

.to_base64(str) ⇒ Object



98
99
100
# File 'lib/bluzelle/utils.rb', line 98

def to_base64(str)
  Base64.strict_encode64(str)
end

.to_bytes(obj) ⇒ Object



41
42
43
# File 'lib/bluzelle/utils.rb', line 41

def to_bytes(obj)
  obj.bytes
end

.validate_address(address, mnemonic) ⇒ Object



26
27
28
29
30
31
32
33
# File 'lib/bluzelle/utils.rb', line 26

def validate_address(address, mnemonic)
  priv_key = get_ec_private_key(mnemonic)
  pub_key = get_ec_public_key_from_priv(priv_key)

  if get_address(pub_key) != address
    raise ArgumentError, 'Bad credentials - verify your address and mnemonic'
  end
end