Module: Bitcoin::Util

Overview

bitcoin utility. following methods can be used as follows.

Bitcoin.pack_var_int(5)

Instance Method Summary collapse

Instance Method Details

#byte_to_bit(byte) ⇒ Object

byte convert to the sequence of bits packed eight in a byte with the least significant bit first.



81
82
83
# File 'lib/bitcoin/util.rb', line 81

def byte_to_bit(byte)
  byte.unpack1('b*')
end

#calc_checksum(hex) ⇒ Object



130
131
132
# File 'lib/bitcoin/util.rb', line 130

def calc_checksum(hex)
  double_sha256(hex.htb).bth[0..7]
end

#decode_base58_address(addr) ⇒ Array

decode Base58 check encoding address.

Parameters:

Returns:

  • (Array)

    hex and address version



120
121
122
123
124
125
126
127
128
# File 'lib/bitcoin/util.rb', line 120

def decode_base58_address(addr)
  hex = Base58.decode(addr)
  if hex.size == 50 && calc_checksum(hex[0...-8]) == hex[-8..-1]
    raise 'Invalid version bytes.' unless [Bitcoin.chain_params.address_version, Bitcoin.chain_params.p2sh_version].include?(hex[0..1])
    [hex[2...-8], hex[0..1]]
  else
    raise 'Invalid address.'
  end
end

#double_sha256(payload) ⇒ Object



76
77
78
# File 'lib/bitcoin/util.rb', line 76

def double_sha256(payload)
  sha256(sha256(payload))
end

#encode_base58_address(hex, addr_version) ⇒ String

encode Base58 check address.

Parameters:

  • hex (String)

    the address payload.

  • addr_version (String)

    the address version for P2PKH and P2SH.

Returns:

  • (String)

    Base58 check encoding address.



112
113
114
115
# File 'lib/bitcoin/util.rb', line 112

def encode_base58_address(hex, addr_version)
  base = addr_version + hex
  Base58.encode(base + calc_checksum(base))
end

#hash160(hex) ⇒ Object

generate sha256-ripemd160 hash for value



95
96
97
# File 'lib/bitcoin/util.rb', line 95

def hash160(hex)
  Digest::RMD160.hexdigest(Digest::SHA256.digest(hex.htb))
end

#hkdf_sha256(ikm, salt, info, length = 32) ⇒ String

Run HKDF.

Parameters:

  • ikm (String)

    The input keying material with binary format.

  • salt (String)

    The salt with binary format.

  • info (String)

    The context and application specific information with binary format.

  • length (Integer) (defaults to: 32)

    The output length in octets.

Returns:

  • (String)

    The result of HKDF with binary format.



144
145
146
# File 'lib/bitcoin/util.rb', line 144

def hkdf_sha256(ikm, salt, info, length = 32)
  OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: length, hash: "SHA256")
end

#hmac_sha256(key, data) ⇒ Object



134
135
136
# File 'lib/bitcoin/util.rb', line 134

def hmac_sha256(key, data)
  Bitcoin.hmac_sha256(key, data)
end

#pack_boolean(b) ⇒ Object



63
64
65
# File 'lib/bitcoin/util.rb', line 63

def pack_boolean(b)
  b ? [0x01].pack('C') : [0x00].pack('C')
end

#pack_var_int(i) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/bitcoin/util.rb', line 20

def pack_var_int(i)
  if i <  0xfd
    [i].pack('C')
  elsif i <= 0xffff
    [0xfd, i].pack('Cv')
  elsif i <= 0xffffffff
    [0xfe, i].pack('CV')
  elsif i <= 0xffffffffffffffff
    [0xff, i].pack('CQ')
  else
    raise "int(#{i}) too large!"
  end
end

#pack_var_string(payload) ⇒ Object



11
12
13
# File 'lib/bitcoin/util.rb', line 11

def pack_var_string(payload)
  pack_var_int(payload.bytesize) + payload
end

#padding_zero(binary, bytesize) ⇒ String

padding zero to the left of binary string until bytesize.

Parameters:

  • binary (String)

    string

  • bytesize (Integer)

    total bytesize.

Returns:

  • (String)

    padded binary string.



89
90
91
92
# File 'lib/bitcoin/util.rb', line 89

def padding_zero(binary, bytesize)
  return binary unless binary.bytesize < bytesize
  ('00' * (bytesize - binary.bytesize)).htb + binary
end

#sha256(payload) ⇒ Object



72
73
74
# File 'lib/bitcoin/util.rb', line 72

def sha256(payload)
  Digest::SHA256.digest(payload)
end

#tagged_hash(tag, msg) ⇒ String

Generate tagged hash value.

Parameters:

  • tag (String)

    tag value.

  • msg (String)

    the message to be hashed.

Returns:

  • (String)

    the hash value with binary format.



103
104
105
106
# File 'lib/bitcoin/util.rb', line 103

def tagged_hash(tag, msg)
  tag_hash = Digest::SHA256.digest(tag)
  Digest::SHA256.digest(tag_hash + tag_hash + msg)
end

#unpack_boolean(payload) ⇒ Object



67
68
69
70
# File 'lib/bitcoin/util.rb', line 67

def unpack_boolean(payload)
  data, payload = payload.unpack('Ca*')
  [(data.zero? ? false : true), payload]
end

#unpack_var_int(payload) ⇒ Object

Returns an integer for a valid payload, otherwise nil.

Returns:

  • an integer for a valid payload, otherwise nil



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/bitcoin/util.rb', line 35

def unpack_var_int(payload)
  case payload.unpack1('C')
  when 0xfd
    payload.unpack('xva*')
  when 0xfe
    payload.unpack('xVa*')
  when 0xff
    payload.unpack('xQa*')
  else
    payload.unpack('Ca*')
  end
end

#unpack_var_int_from_io(buf) ⇒ Object

Returns an integer for a valid payload, otherwise nil.

Returns:

  • an integer for a valid payload, otherwise nil



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bitcoin/util.rb', line 49

def unpack_var_int_from_io(buf)
  uchar = buf.read(1)&.unpack1('C')
  case uchar
  when 0xfd
    buf.read(2)&.unpack1('v')
  when 0xfe
    buf.read(4)&.unpack1('V')
  when 0xff
    buf.read(8)&.unpack1('Q')
  else
    uchar
  end
end

#unpack_var_string(payload) ⇒ Object



15
16
17
18
# File 'lib/bitcoin/util.rb', line 15

def unpack_var_string(payload)
  size, payload = unpack_var_int(payload)
  size > 0 ? payload.unpack("a#{size}a*") : [nil, payload]
end

#valid_address?(addr) ⇒ Boolean

check whether addr is valid address.

Parameters:

  • addr (String)

    an address

Returns:

  • (Boolean)

    if valid address return true, otherwise false.



151
152
153
154
155
156
157
158
# File 'lib/bitcoin/util.rb', line 151

def valid_address?(addr)
  begin
    Bitcoin::Script.parse_from_addr(addr)
    true
  rescue Exception
    false
  end
end