Module: MoneyTree::Support

Extended by:
Support
Includes:
OpenSSL
Included in:
Key, Node, Node, Support
Defined in:
lib/money-tree/support.rb

Constant Summary collapse

INT32_MAX =
256 ** [1].pack("L*").size
INT64_MAX =
256 ** [1].pack("Q*").size
BASE58_CHARS =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

Instance Method Summary collapse

Instance Method Details

#base58_to_int(base58_val) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/money-tree/support.rb', line 23

def base58_to_int(base58_val)
  int_val, base = 0, BASE58_CHARS.size
  base58_val.reverse.each_char.with_index do |char, index|
    raise ArgumentError, "Value not a valid Base58 String." unless char_index = BASE58_CHARS.index(char)
    int_val += char_index * (base ** index)
  end
  int_val
end

#bytes_to_hex(bytes) ⇒ Object



125
126
127
# File 'lib/money-tree/support.rb', line 125

def bytes_to_hex(bytes)
  bytes.unpack("H*")[0].downcase
end

#bytes_to_int(bytes, base = 16) ⇒ Object



101
102
103
104
105
106
# File 'lib/money-tree/support.rb', line 101

def bytes_to_int(bytes, base = 16)
  if bytes.is_a?(Array)
    bytes = bytes.pack("C*")
  end
  bytes.unpack("H*")[0].to_i(16)
end

#convert_p2wpkh_p2sh(key_hex, prefix) ⇒ Object



146
147
148
149
150
# File 'lib/money-tree/support.rb', line 146

def convert_p2wpkh_p2sh(key_hex, prefix)
  push_20 = ["0014"].pack("H*")
  script_sig = push_20 + custom_hash_160([key_hex].pack("H*"))
  encode_p2wpkh_p2sh(prefix + custom_hash_160(script_sig))
end

#custom_hash_160(value) ⇒ Object



142
143
144
# File 'lib/money-tree/support.rb', line 142

def custom_hash_160(value)
  [OpenSSL::Digest::RIPEMD160.hexdigest(Digest::SHA256.digest(value))].pack("H*")
end

#decode_base58(base58_val) ⇒ Object Also known as: base58_to_hex



37
38
39
40
41
42
43
# File 'lib/money-tree/support.rb', line 37

def decode_base58(base58_val)
  s = base58_to_int(base58_val).to_s(16); s = (s.bytesize.odd? ? "0" + s : s)
  s = "" if s == "00"
  leading_zero_bytes = (base58_val.match(/^([1]+)/) ? $1 : "").size
  s = ("00" * leading_zero_bytes) + s if leading_zero_bytes > 0
  s
end

#decode_base64(base64) ⇒ Object



87
88
89
# File 'lib/money-tree/support.rb', line 87

def decode_base64(base64)
  Base64.decode64(base64).unpack("H*")[0]
end

#digestify(digest_type, source, opts = {}) ⇒ Object



70
71
72
73
# File 'lib/money-tree/support.rb', line 70

def digestify(digest_type, source, opts = {})
  source = [source].pack("H*") unless opts[:ascii]
  bytes_to_hex Digest.digest(digest_type, source)
end

#encode_base58(hex) ⇒ Object



32
33
34
35
# File 'lib/money-tree/support.rb', line 32

def encode_base58(hex)
  leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : "").size / 2
  ("1" * leading_zero_bytes) + int_to_base58(hex.to_i(16))
end

#encode_base64(hex) ⇒ Object



83
84
85
# File 'lib/money-tree/support.rb', line 83

def encode_base64(hex)
  Base64.encode64([hex].pack("H*")).chomp
end

#encode_p2wpkh_p2sh(value) ⇒ Object



137
138
139
140
# File 'lib/money-tree/support.rb', line 137

def encode_p2wpkh_p2sh(value)
  chk = [Digest::SHA256.hexdigest(Digest::SHA256.digest(value))].pack("H*")[0...4]
  encode_base58 (value + chk).unpack("H*")[0]
end

#from_serialized_base58(base58) ⇒ Object

Raises:

  • (EncodingError)


62
63
64
65
66
67
68
# File 'lib/money-tree/support.rb', line 62

def from_serialized_base58(base58)
  hex = decode_base58 base58
  checksum = hex.slice!(-8..-1)
  compare_checksum = sha256(sha256(hex)).slice(0..7)
  raise EncodingError unless checksum == compare_checksum
  hex
end

#hex_to_bytes(hex) ⇒ Object



129
130
131
# File 'lib/money-tree/support.rb', line 129

def hex_to_bytes(hex)
  [hex].pack("H*")
end

#hex_to_int(hex) ⇒ Object



133
134
135
# File 'lib/money-tree/support.rb', line 133

def hex_to_int(hex)
  hex.to_i(16)
end

#hmac_sha512(key, message) ⇒ Object



91
92
93
94
# File 'lib/money-tree/support.rb', line 91

def hmac_sha512(key, message)
  digest = Digest::SHA512.new
  HMAC.digest digest, key, message
end

#hmac_sha512_hex(key, message) ⇒ Object



96
97
98
99
# File 'lib/money-tree/support.rb', line 96

def hmac_sha512_hex(key, message)
  md = hmac_sha512(key, message)
  md.unpack("H*").first.rjust(64, "0")
end

#int_to_base58(int_val, leading_zero_bytes = 0) ⇒ Object



14
15
16
17
18
19
20
21
# File 'lib/money-tree/support.rb', line 14

def int_to_base58(int_val, leading_zero_bytes = 0)
  base58_val, base = "", BASE58_CHARS.size
  while int_val > 0
    int_val, remainder = int_val.divmod(base)
    base58_val = BASE58_CHARS[remainder] + base58_val
  end
  base58_val
end

#int_to_bytes(i) ⇒ Object



121
122
123
# File 'lib/money-tree/support.rb', line 121

def int_to_bytes(i)
  [int_to_hex(i)].pack("H*")
end

#int_to_hex(i, size = nil) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/money-tree/support.rb', line 108

def int_to_hex(i, size = nil)
  hex = i.to_s(16).downcase
  if (hex.size % 2) != 0
    hex = "#{0}#{hex}"
  end

  if size
    hex.rjust(size, "0")
  else
    hex
  end
end

#ripemd160(source, opts = {}) ⇒ Object



79
80
81
# File 'lib/money-tree/support.rb', line 79

def ripemd160(source, opts = {})
  digestify("RIPEMD160", source, opts)
end

#sha256(source, opts = {}) ⇒ Object



75
76
77
# File 'lib/money-tree/support.rb', line 75

def sha256(source, opts = {})
  digestify("SHA256", source, opts)
end

#to_serialized_base58(hex) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/money-tree/support.rb', line 47

def to_serialized_base58(hex)
  hash = sha256 hex
  hash = sha256 hash
  checksum = hash.slice(0..7)
  address = hex + checksum
  encode_base58 address
end

#to_serialized_bech32(human_readable_part, hex) ⇒ Object



55
56
57
58
59
60
# File 'lib/money-tree/support.rb', line 55

def to_serialized_bech32(human_readable_part, hex)
  segwit_addr = Bech32::SegwitAddr.new
  segwit_addr.hrp = human_readable_part
  segwit_addr.script_pubkey = "0000" + hex
  segwit_addr.addr
end