Class: BTC::Address

Inherits:
Object
  • Object
show all
Includes:
Opcodes
Defined in:
lib/btcruby/address.rb

Direct Known Subclasses

AssetAddress, BitcoinPaymentAddress, WIF

Constant Summary collapse

@@registered_classes =
[]

Constants included from Opcodes

Opcodes::OPCODE_NAME_TO_VALUE, Opcodes::OPCODE_VALUE_TO_NAME, Opcodes::OP_0, Opcodes::OP_0NOTEQUAL, Opcodes::OP_1, Opcodes::OP_10, Opcodes::OP_11, Opcodes::OP_12, Opcodes::OP_13, Opcodes::OP_14, Opcodes::OP_15, Opcodes::OP_16, Opcodes::OP_1ADD, Opcodes::OP_1NEGATE, Opcodes::OP_1SUB, Opcodes::OP_2, Opcodes::OP_2DIV, Opcodes::OP_2DROP, Opcodes::OP_2DUP, Opcodes::OP_2MUL, Opcodes::OP_2OVER, Opcodes::OP_2ROT, Opcodes::OP_2SWAP, Opcodes::OP_3, Opcodes::OP_3DUP, Opcodes::OP_4, Opcodes::OP_5, Opcodes::OP_6, Opcodes::OP_7, Opcodes::OP_8, Opcodes::OP_9, Opcodes::OP_ABS, Opcodes::OP_ADD, Opcodes::OP_AND, Opcodes::OP_BOOLAND, Opcodes::OP_BOOLOR, Opcodes::OP_CAT, Opcodes::OP_CHECKLOCKTIMEVERIFY, Opcodes::OP_CHECKMULTISIG, Opcodes::OP_CHECKMULTISIGVERIFY, Opcodes::OP_CHECKSIG, Opcodes::OP_CHECKSIGVERIFY, Opcodes::OP_CODESEPARATOR, Opcodes::OP_DEPTH, Opcodes::OP_DIV, Opcodes::OP_DROP, Opcodes::OP_DUP, Opcodes::OP_ELSE, Opcodes::OP_ENDIF, Opcodes::OP_EQUAL, Opcodes::OP_EQUALVERIFY, Opcodes::OP_FALSE, Opcodes::OP_FROMALTSTACK, Opcodes::OP_GREATERTHAN, Opcodes::OP_GREATERTHANOREQUAL, Opcodes::OP_HASH160, Opcodes::OP_HASH256, Opcodes::OP_IF, Opcodes::OP_IFDUP, Opcodes::OP_INVALIDOPCODE, Opcodes::OP_INVERT, Opcodes::OP_LEFT, Opcodes::OP_LESSTHAN, Opcodes::OP_LESSTHANOREQUAL, Opcodes::OP_LSHIFT, Opcodes::OP_MAX, Opcodes::OP_MIN, Opcodes::OP_MOD, Opcodes::OP_MUL, Opcodes::OP_NEGATE, Opcodes::OP_NIP, Opcodes::OP_NOP, Opcodes::OP_NOP1, Opcodes::OP_NOP10, Opcodes::OP_NOP2, Opcodes::OP_NOP3, Opcodes::OP_NOP4, Opcodes::OP_NOP5, Opcodes::OP_NOP6, Opcodes::OP_NOP7, Opcodes::OP_NOP8, Opcodes::OP_NOP9, Opcodes::OP_NOT, Opcodes::OP_NOTIF, Opcodes::OP_NUMEQUAL, Opcodes::OP_NUMEQUALVERIFY, Opcodes::OP_NUMNOTEQUAL, Opcodes::OP_OR, Opcodes::OP_OVER, Opcodes::OP_PICK, Opcodes::OP_PUSHDATA1, Opcodes::OP_PUSHDATA2, Opcodes::OP_PUSHDATA4, Opcodes::OP_RESERVED, Opcodes::OP_RESERVED1, Opcodes::OP_RESERVED2, Opcodes::OP_RETURN, Opcodes::OP_RIGHT, Opcodes::OP_RIPEMD160, Opcodes::OP_ROLL, Opcodes::OP_ROT, Opcodes::OP_RSHIFT, Opcodes::OP_SHA1, Opcodes::OP_SHA256, Opcodes::OP_SIZE, Opcodes::OP_SUB, Opcodes::OP_SUBSTR, Opcodes::OP_SWAP, Opcodes::OP_TOALTSTACK, Opcodes::OP_TRUE, Opcodes::OP_TUCK, Opcodes::OP_VER, Opcodes::OP_VERIF, Opcodes::OP_VERIFY, Opcodes::OP_VERNOTIF, Opcodes::OP_WITHIN, Opcodes::OP_XOR

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.mux_parse_raw_data(raw_data, _string = nil) ⇒ Object

Attempts to parse with a proper subclass



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/btcruby/address.rb', line 48

def self.mux_parse_raw_data(raw_data, _string = nil)
  result = nil
  @@registered_classes.each do |cls|
    if result = cls.parse_raw_data(raw_data, _string)
      break
    end
  end
  if !result
    raise ArgumentError, "Unknown kind of address: #{_string}. Registered types: #{@@registered_classes}"
  end
  if !result.is_a?(self)
    raise ArgumentError, "Argument must be an instance of #{self}, not #{result.class}."
  end
  return result
end

.parse(string_or_address) ⇒ Object

Decodes address from a Base58Check-encoded string

Raises:

  • (ArgumentError)


34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/btcruby/address.rb', line 34

def self.parse(string_or_address)
  raise ArgumentError, "Argument is missing" if !string_or_address
  if string_or_address.is_a?(self)
    return string_or_address
  elsif string_or_address.is_a?(Address)
    raise ArgumentError, "Argument must be an instance of #{self}, not #{string_or_address.class}."
  end
  string = string_or_address
  raise ArgumentError, "String is expected" if !string.is_a?(String)
  raw_data = Base58.data_from_base58check(string)
  self.mux_parse_raw_data(raw_data, string)
end

.parse_raw_data(raw_data, _string = nil) ⇒ Object

Internal method to parse address from raw binary data. Subclasses should implement to return a valid instance or nil if the provided data does not correspond to that subclass. Default implementation assumes 1-byte version prefix and implementation of mainnet_version and testnet_version class methods.

Raises:

  • (ArgumentError)


67
68
69
70
71
72
73
74
75
76
77
# File 'lib/btcruby/address.rb', line 67

def self.parse_raw_data(raw_data, _string = nil)
  raise ArgumentError, "Raw data is missing" if !raw_data
  if raw_data.bytesize < 2 # should contain at least a version byte and some content
    raise FormatError, "Failed to decode BTC::Address: raw data is too short"
  end
  version = raw_data.bytes.first
  if self.mainnet_version == version || self.testnet_version == version
    return self.new(string: _string, _raw_data: raw_data)
  end
  return nil
end

.register_class(cls) ⇒ Object

Subclasses should register themselves so they can be parsed via BTC::Address.parse()



80
81
82
# File 'lib/btcruby/address.rb', line 80

def self.register_class(cls)
  @@registered_classes << cls
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?

Two instances are equal when they have the same contents and versions.



113
114
115
116
# File 'lib/btcruby/address.rb', line 113

def ==(other)
  return false if !other
  data == other.data && version == other.version
end

#dataObject

Returns binary contents of the address (without version byte and checksum).



103
104
105
# File 'lib/btcruby/address.rb', line 103

def data
  @data
end

#hashObject



119
120
121
# File 'lib/btcruby/address.rb', line 119

def hash
  data.hash
end

#inspectObject



148
149
150
# File 'lib/btcruby/address.rb', line 148

def inspect
  %{#<#{self.class}:#{to_s}>}
end

#mainnet?Boolean

Whether this address is usable on mainnet.

Returns:

  • (Boolean)


129
130
131
# File 'lib/btcruby/address.rb', line 129

def mainnet?
  self.network.mainnet?
end

#networkObject



84
85
86
87
88
89
90
91
92
# File 'lib/btcruby/address.rb', line 84

def network
  @network ||= if !@version
    BTC::Network.default
  elsif @version == self.class.mainnet_version
    BTC::Network.mainnet
  else
    BTC::Network.testnet
  end
end

#p2pkh?Boolean

Whether this address is pay-to-public-key-hash (classic address which is a hash of a single public key).

Returns:

  • (Boolean)


139
140
141
# File 'lib/btcruby/address.rb', line 139

def p2pkh?
  false
end

#p2sh?Boolean

Whether this address is pay-to-script-hash.

Returns:

  • (Boolean)


144
145
146
# File 'lib/btcruby/address.rb', line 144

def p2sh?
  false
end

#public_addressObject

Returns a public version of the address. For public addresses (P2PKH and P2SH) returns self.



108
109
110
# File 'lib/btcruby/address.rb', line 108

def public_address
  self
end

#testnet?Boolean

Whether this address is usable on testnet.

Returns:

  • (Boolean)


134
135
136
# File 'lib/btcruby/address.rb', line 134

def testnet?
  self.network.testnet?
end

#to_sObject

Returns Base58Check representation of an address.



124
125
126
# File 'lib/btcruby/address.rb', line 124

def to_s
  @base58check_string ||= Base58.base58check_from_data(self.data_for_base58check_encoding)
end

#versionObject



94
95
96
97
98
99
100
# File 'lib/btcruby/address.rb', line 94

def version
  @version ||= if self.network.mainnet?
    self.class.mainnet_version
  else
    self.class.testnet_version
  end
end