Class: Bitcoin::PaymentCode

Inherits:
ExtKey
  • Object
show all
Includes:
HexConverter
Defined in:
lib/bitcoin/payment_code.rb

Overview

BIP47 payment code

Constant Summary collapse

VERSION_BYTE =
'47'
SUPPORT_VERSIONS =
['01']
SUPPORT_SIGNS =
['02', '03']

Constants inherited from ExtKey

ExtKey::MASTER_FINGERPRINT, ExtKey::MAX_DEPTH

Instance Attribute Summary collapse

Attributes inherited from ExtKey

#chain_code, #depth, #key, #number, #parent_fingerprint, #ver

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HexConverter

#to_hex

Methods inherited from ExtKey

#==, #addr, #derive, #ext_pubkey, #fingerprint, #hardened?, #hash160, #identifier, #key_type, parse_from_payload, #priv, #priv_ver_to_pub_ver, #pub, #version, version_from_purpose

Constructor Details

#initializePaymentCode

Returns a new instance of PaymentCode.



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

def initialize
  @version = '01'
  @features_bits = '00'
  @reserve_field = '0' * 26
end

Instance Attribute Details

#signObject

Returns the value of attribute sign.



9
10
11
# File 'lib/bitcoin/payment_code.rb', line 9

def sign
  @sign
end

#x_valueObject

Returns the value of attribute x_value.



8
9
10
# File 'lib/bitcoin/payment_code.rb', line 8

def x_value
  @x_value
end

Class Method Details

.from_base58(base58_payment_code) ⇒ Object

decode base58 encoded payment code

Raises:

  • (ArgumentError)


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/bitcoin/payment_code.rb', line 54

def self.from_base58(base58_payment_code)
  hex = Bitcoin::Base58.decode(base58_payment_code)
  version = hex[2..3]
  sign = hex[6..7]
  public_key = hex[8..71]
  payment_code = hex[0...-8]

  raise ArgumentError, 'invalid version byte' unless hex[0..1] == VERSION_BYTE
  raise ArgumentError, 'invalid version' unless PaymentCode.support_version?(version)
  raise ArgumentError, 'invalid sign' unless PaymentCode.support_sign?(sign)
  raise ArgumentError, Errors::Messages::INVALID_PUBLIC_KEY unless Bitcoin::Key.new(pubkey: sign + public_key).fully_valid_pubkey?
  raise ArgumentError, Errors::Messages::INVALID_CHECKSUM unless Bitcoin.calc_checksum(payment_code) == hex[-8..-1]

  x_value = payment_code[8..71]
  chain_code_hex = payment_code[72..135]

  payment_code_pubkey = PaymentCode.new
  payment_code_pubkey.depth = 3
  payment_code_pubkey.sign = sign
  payment_code_pubkey.x_value = x_value
  payment_code_pubkey.chain_code = [chain_code_hex].pack('H*')

  payment_code_pubkey.to_payload
end

.generate_master(seed) ⇒ Object

generate master key from seed.



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/bitcoin/payment_code.rb', line 23

def self.generate_master(seed)
  master_ext_key = super.derive(47, harden=true).derive(0, harden=true).derive(0, harden=true)
  compressed_pubkey = master_ext_key.pub

  payment_code = PaymentCode.new
  payment_code.depth = master_ext_key.depth
  payment_code.key = master_ext_key.key
  payment_code.sign = compressed_pubkey[0..1]
  payment_code.x_value = compressed_pubkey[2..-1]
  payment_code.chain_code = master_ext_key.chain_code
  payment_code
end

.support_sign?(sign) ⇒ Boolean

check whether sign is supported version bytes.

Returns:

  • (Boolean)


85
86
87
# File 'lib/bitcoin/payment_code.rb', line 85

def self.support_sign?(sign)
  SUPPORT_SIGNS.include?(sign)
end

.support_version?(version) ⇒ Boolean

check whether version is supported version bytes.

Returns:

  • (Boolean)


80
81
82
# File 'lib/bitcoin/payment_code.rb', line 80

def self.support_version?(version)
  SUPPORT_VERSIONS.include?(version)
end

Instance Method Details

#notification_addressObject

get notification address



48
49
50
# File 'lib/bitcoin/payment_code.rb', line 48

def notification_address
  ext_pubkey.derive(0).addr
end

#to_base58Object

Base58 encoded payment code



37
38
39
40
# File 'lib/bitcoin/payment_code.rb', line 37

def to_base58
  payment_code_with_version_byte = VERSION_BYTE + to_hex
  Bitcoin::Base58.encode(payment_code_with_version_byte + Bitcoin.calc_checksum(payment_code_with_version_byte))
end

#to_payloadObject

serialize payment code



43
44
45
# File 'lib/bitcoin/payment_code.rb', line 43

def to_payload
  @version.htb << @features_bits.htb << @sign.htb << @x_value.htb << @chain_code << @reserve_field.htb
end