Module: OpenAssets::Util

Extended by:
Bitcoin::Util
Includes:
Bitcoin::Util
Included in:
OpenAssets, Api, Protocol::AssetDefinitionLoader, Protocol::MarkerOutput, Protocol::MarkerOutput, Protocol::TransactionOutput, Transaction::TransactionBuilder
Defined in:
lib/openassets/util.rb

Constant Summary collapse

OA_NAMESPACE =

namespace of Open Asset

19
OA_VERSION_BYTE =

version byte for Open Assets Address

23
OA_VERSION_BYTE_TESTNET =
115

Instance Method Summary collapse

Instance Method Details

#address_to_oa_address(btc_address) ⇒ String

convert bitcoin address to open assets address

Parameters:

  • btc_address (String)

    The Bitcoin address.

Returns:

  • (String)

    The Open Assets Address.



17
18
19
20
21
22
23
24
# File 'lib/openassets/util.rb', line 17

def address_to_oa_address(btc_address)
  btc_hex = decode_base58(btc_address)
  btc_hex = '0' +btc_hex if btc_hex.size==47
  address = btc_hex[0..-9] # bitcoin address without checksum
  named_addr = OA_NAMESPACE.to_s(16) + address
  oa_checksum = checksum(named_addr)
  encode_base58(named_addr + oa_checksum)
end

#coin_to_satoshi(coin) ⇒ String

Convert coin unit to satoshi.

Parameters:

  • coin (String)

    The amount of bitcoin

Returns:

  • (String)

    The amount of satoshi.



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

def coin_to_satoshi(coin)
  BigDecimal(coin) * BigDecimal(100000000)
end

#decode_leb128(value) ⇒ Object

LEB128 decode



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/openassets/util.rb', line 63

def decode_leb128(value)
  results = []
  sio = StringIO.new
  value.htb.each_byte{|b|
    sio.putc(b)
    if b < 128
      results << LEB128.decode_unsigned(sio)
      sio = StringIO.new
    end
  }
  results
end

#encode_leb128(value) ⇒ Object

LEB128 encode



58
59
60
# File 'lib/openassets/util.rb', line 58

def encode_leb128(value)
  LEB128.encode_unsigned(value).read.bth
end

#generate_asset_id(pub_key) ⇒ Object

generate asset ID from public key.



37
38
39
# File 'lib/openassets/util.rb', line 37

def generate_asset_id(pub_key)
  pubkey_hash_to_asset_id(hash160(pub_key))
end

#hash_to_asset_id(hash) ⇒ Object



52
53
54
55
# File 'lib/openassets/util.rb', line 52

def hash_to_asset_id(hash)
  hash = oa_version_byte.to_s(16) + hash # add version byte to script hash
  encode_base58(hash + checksum(hash)) # add checksum & encode
end

#oa_address_to_address(oa_address) ⇒ String

convert open assets address to bitcoin address

Parameters:

  • oa_address (String)

    The Open Assets Address.

Returns:

  • (String)

    The Bitcoin address.



29
30
31
32
33
34
# File 'lib/openassets/util.rb', line 29

def oa_address_to_address(oa_address)
  decode_address = decode_base58(oa_address)
  btc_addr = decode_address[2..-9]
  btc_checksum = checksum(btc_addr)
  encode_base58(btc_addr + btc_checksum)
end

#pubkey_hash_to_asset_id(pubkey_hash) ⇒ Object



41
42
43
44
45
46
# File 'lib/openassets/util.rb', line 41

def pubkey_hash_to_asset_id(pubkey_hash)
  # gen P2PKH script hash
  # P2PKH script = OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
  # (76=OP_DUP, a9=OP_HASH160, 14=Bytes to push, 88=OP_EQUALVERIFY, ac=OP_CHECKSIG)
  hash_to_asset_id(hash160(["76", "a9", "14", pubkey_hash, "88", "ac"].join))
end

#read_leb128(data, offset = 0) ⇒ [Integer, Integer]

read leb128 value

Parameters:

  • data (String)

    reading data

  • offset (Integer) (defaults to: 0)

    start position when reading from data.

Returns:

  • ([Integer, Integer])

    decoded integer value and the reading byte length.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/openassets/util.rb', line 148

def read_leb128(data, offset = 0)
  bytes = [data].pack('H*').bytes
  result = 0
  shift = 0
  while true
    return [nil, offset] if bytes.length < 1 + offset
    byte = bytes[offset..(offset + 1)][0]
    result |= (byte & 0x7f) << shift
    break if byte & 0x80 == 0
    shift += 7
    offset += 1
  end
  [result, offset + 1]
end

#read_var_integer(data, offset = 0) ⇒ [Integer, Integer]

Parameters:

  • data (String)

    reading data

  • offset (Integer) (defaults to: 0)

    the position when reading from data.

Returns:

  • ([Integer, Integer])

    decoded integer value and the reading byte length.

Raises:

  • (ArgumentError)


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/openassets/util.rb', line 127

def read_var_integer(data, offset = 0)
  raise ArgumentError, "data is nil." unless data
  packed = [data].pack('H*')
  return [nil, 0] if packed.bytesize < 1+offset
  bytes = packed.bytes[offset..(offset + 9)] # 9 is variable integer max storage length.
  first_byte = bytes[0]
  if first_byte < 0xfd
    [first_byte, offset + 1]
  elsif first_byte == 0xfd
    [calc_var_integer_val(bytes[1..2]), offset + 3]
  elsif first_byte == 0xfe
    [calc_var_integer_val(bytes[1..4]), offset + 5]
  elsif first_byte == 0xff
    [calc_var_integer_val(bytes[1..8]), offset + 9]
  end
end

#satoshi_to_coin(satoshi) ⇒ String

Convert satoshi to coin.

Parameters:

  • satoshi (Integer)

    The amount of satoshi unit.

Returns:

  • (String)

    The amount of coin.



83
84
85
# File 'lib/openassets/util.rb', line 83

def satoshi_to_coin(satoshi)
  "%.8f" % (satoshi / 100000000.0)
end

#script_to_address(script) ⇒ String

Get address from script.

Parameters:

  • script (Bitcoin::Script)

    The output script.

Returns:

  • (String)

    The Bitcoin address. if the script dose not contains address, return nil.



97
98
99
100
101
102
103
# File 'lib/openassets/util.rb', line 97

def script_to_address(script)
  return script.get_pubkey_address    if script.is_pubkey?
  return script.get_hash160_address   if script.is_hash160?
  return script.get_multisig_addresses  if script.is_multisig?
  return script.get_p2sh_address      if script.is_p2sh?
  nil
end

#script_to_asset_id(script) ⇒ Object



48
49
50
# File 'lib/openassets/util.rb', line 48

def script_to_asset_id(script)
  hash_to_asset_id(hash160(script))
end

#to_bytes(string) ⇒ Object



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

def to_bytes(string)
  string.each_char.each_slice(2).map{|v|v.join}
end

#valid_asset_id?(asset_id) ⇒ Boolean

validate asset ID

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
# File 'lib/openassets/util.rb', line 113

def valid_asset_id?(asset_id)
  return false if asset_id.nil? || asset_id.length != 34
  decoded = decode_base58(asset_id)
  return false if  decoded[0,2].to_i(16) != oa_version_byte
  p2pkh_script_hash = decoded[2..-9]
  address = hash160_to_address(p2pkh_script_hash)
  valid_address?(address)
end

#validate_address(addresses) ⇒ Object

validate bitcoin address



106
107
108
109
110
# File 'lib/openassets/util.rb', line 106

def validate_address(addresses)
  addresses.each{|a|
    raise ArgumentError, "#{a} is invalid bitcoin address. " unless valid_address?(a)
  }
end