bitcoinrb 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/bitcoinrb.gemspec +7 -3
  4. data/exe/bitcoinrb-cli +1 -1
  5. data/exe/bitcoinrbd +9 -23
  6. data/lib/bitcoin/block.rb +66 -0
  7. data/lib/bitcoin/block_header.rb +33 -1
  8. data/lib/bitcoin/chain_params.rb +11 -4
  9. data/lib/bitcoin/chainparams/mainnet.yml +9 -2
  10. data/lib/bitcoin/chainparams/regtest.yml +9 -1
  11. data/lib/bitcoin/chainparams/testnet.yml +9 -1
  12. data/lib/bitcoin/constants.rb +13 -0
  13. data/lib/bitcoin/ext_key.rb +2 -1
  14. data/lib/bitcoin/merkle_tree.rb +50 -51
  15. data/lib/bitcoin/message/block.rb +5 -0
  16. data/lib/bitcoin/message.rb +5 -5
  17. data/lib/bitcoin/network/connection.rb +58 -0
  18. data/lib/bitcoin/network/message_handler.rb +192 -0
  19. data/lib/bitcoin/network/peer.rb +55 -0
  20. data/lib/bitcoin/network/peer_discovery.rb +34 -0
  21. data/lib/bitcoin/network/pool.rb +74 -0
  22. data/lib/bitcoin/network.rb +14 -0
  23. data/lib/bitcoin/node/spv.rb +39 -0
  24. data/lib/bitcoin/node/spv_block_chain.rb +15 -0
  25. data/lib/bitcoin/node.rb +6 -0
  26. data/lib/bitcoin/script/script.rb +13 -0
  27. data/lib/bitcoin/store/spv_block_store.rb +11 -0
  28. data/lib/bitcoin/store.rb +7 -0
  29. data/lib/bitcoin/tx.rb +11 -0
  30. data/lib/bitcoin/tx_out.rb +2 -0
  31. data/lib/bitcoin/validation.rb +33 -11
  32. data/lib/bitcoin/version.rb +1 -1
  33. data/lib/bitcoin.rb +5 -2
  34. data/lib/openassets/marker_output.rb +14 -0
  35. data/lib/openassets/payload.rb +45 -0
  36. data/lib/openassets.rb +8 -0
  37. metadata +59 -8
  38. data/lib/bitcoin/connection.rb +0 -68
  39. data/lib/bitcoin/message/handler.rb +0 -183
  40. data/lib/bitcoin/nodes/spv/cli.rb +0 -12
  41. data/lib/bitcoin/nodes/spv/daemon.rb +0 -21
  42. data/lib/bitcoin/nodes/spv.rb +0 -13
  43. data/lib/bitcoin/nodes.rb +0 -5
@@ -0,0 +1,192 @@
1
+ module Bitcoin
2
+ module Network
3
+
4
+ # P2P message handler used by peer connection class.
5
+ module MessageHandler
6
+
7
+ # handle p2p message.
8
+ def handle(message)
9
+ logger.info "handle message #{message.bth}"
10
+ begin
11
+ parse(message)
12
+ rescue Bitcoin::Message::Error => e
13
+ logger.error("invalid header magic. #{e.message}")
14
+ close
15
+ end
16
+ end
17
+
18
+ def parse(message)
19
+ @message += message
20
+ command, payload, rest = parse_header
21
+ return unless command
22
+
23
+ handle_command(command, payload)
24
+ @message = ""
25
+ parse(rest) if rest && rest.bytesize > 0
26
+ end
27
+
28
+ def parse_header
29
+ head_magic = Bitcoin.chain_params.magic_head
30
+ return if @message.nil? || @message.size < MESSAGE_HEADER_SIZE
31
+
32
+ magic, command, length, checksum = @message.unpack('a4A12Va4')
33
+ raise Bitcoin::Message::Error, "invalid header magic. #{magic.bth}" unless magic.bth == head_magic
34
+
35
+ payload = @message[MESSAGE_HEADER_SIZE...(MESSAGE_HEADER_SIZE + length)]
36
+ return if payload.size < length
37
+ raise Bitcoin::Message::Error, "header checksum mismatch. #{checksum.bth}" unless Bitcoin.double_sha256(payload)[0...4] == checksum
38
+
39
+ rest = @message[(MESSAGE_HEADER_SIZE + length)..-1]
40
+ [command, payload, rest]
41
+ end
42
+
43
+ def handle_command(command, payload)
44
+ logger.info("[#{addr}] process command #{command}. payload = #{payload.bth}")
45
+ case command
46
+ when Bitcoin::Message::Version::COMMAND
47
+ on_version(Bitcoin::Message::Version.parse_from_payload(payload))
48
+ when Bitcoin::Message::VerAck::COMMAND
49
+ on_ver_ack
50
+ when Bitcoin::Message::GetAddr::COMMAND
51
+ on_get_addr
52
+ when Bitcoin::Message::Addr::COMMAND
53
+ on_addr(Bitcoin::Message::Addr.parse_from_payload(payload))
54
+ when Bitcoin::Message::SendHeaders::COMMAND
55
+ on_send_headers
56
+ when Bitcoin::Message::FeeFilter::COMMAND
57
+ on_fee_filter(Bitcoin::Message::FeeFilter.parse_from_payload(payload))
58
+ when Bitcoin::Message::Ping::COMMAND
59
+ on_ping(Bitcoin::Message::Ping.parse_from_payload(payload))
60
+ when Bitcoin::Message::Pong::COMMAND
61
+ on_pong(Bitcoin::Message::Pong.parse_from_payload(payload))
62
+ when Bitcoin::Message::GetHeaders::COMMAND
63
+ on_get_headers(Bitcoin::Message::GetHeaders.parse_from_payload(payload))
64
+ when Bitcoin::Message::Headers::COMMAND
65
+ on_headers(Bitcoin::Message::Headers.parse_from_payload(payload))
66
+ when Bitcoin::Message::Block::COMMAND
67
+ on_block(Bitcoin::Message::Block.parse_from_payload(payload))
68
+ when Bitcoin::Message::Tx::COMMAND
69
+ on_tx(Bitcoin::Message::Tx.parse_from_payload(payload))
70
+ when Bitcoin::Message::NotFound::COMMAND
71
+ on_not_found(Bitcoin::Message::NotFound.parse_from_payload(payload))
72
+ when Bitcoin::Message::MemPool::COMMAND
73
+ on_mem_pool
74
+ when Bitcoin::Message::Reject::COMMAND
75
+ on_reject(Bitcoin::Message::Reject.parse_from_payload(payload))
76
+ when Bitcoin::Message::SendCmpct::COMMAND
77
+ on_send_cmpct(Bitcoin::Message::SendCmpct.parse_from_payload(payload))
78
+ when Bitcoin::Message::Inv::COMMAND
79
+ on_inv(Bitcoin::Message::Inv.parse_from_payload(payload))
80
+ else
81
+ logger.warn("unsupported command received. #{command}")
82
+ close("with command #{command}")
83
+ end
84
+ end
85
+
86
+ def send_message(msg)
87
+ logger.info "send message #{msg.class::COMMAND}"
88
+ send_data(msg.to_pkt)
89
+ end
90
+
91
+ # start handshake
92
+ def begin_handshake
93
+ logger.info "begin handshake with #{addr}"
94
+ ver = Bitcoin::Message::Version.new(remote_addr: addr, start_height: 0) # TODO use start_height in wallet
95
+ send_message(ver)
96
+ end
97
+
98
+ def handshake_done
99
+ logger.info 'handshake finished.'
100
+ @connected = true
101
+ post_handshake
102
+ end
103
+
104
+ def on_version(version)
105
+ logger.info("receive version message. #{version.build_json}")
106
+ @version = version
107
+ send_message(Bitcoin::Message::VerAck.new)
108
+ end
109
+
110
+ def on_ver_ack
111
+ logger.info('receive verack message.')
112
+ handshake_done
113
+ end
114
+
115
+ def on_get_addr
116
+ logger.info('receive getaddr message.')
117
+ end
118
+
119
+ def on_addr(addr)
120
+ logger.info("receive addr message. #{addr.build_json}")
121
+ # TODO
122
+ end
123
+
124
+ def on_send_headers
125
+ logger.info('receive sendheaders message.')
126
+ @sendheaders = true
127
+ end
128
+
129
+ def on_fee_filter(fee_filter)
130
+ logger.info("receive feefilter message. #{fee_filter.build_json}")
131
+ @fee_rate = fee_filter.fee_rate
132
+ end
133
+
134
+ def on_ping(ping)
135
+ logger.info("receive ping message. #{ping.build_json}")
136
+ send_message(ping.to_response)
137
+ end
138
+
139
+ def on_pong(pong)
140
+ logger.info("receive pong message. #{pong.build_json}")
141
+ # TODO calculate response
142
+ end
143
+
144
+ def on_get_headers(headers)
145
+ logger.info("receive getheaders message. #{headers.build_json}")
146
+ # TODO
147
+ end
148
+
149
+ def on_headers(headers)
150
+ logger.info("receive headers message. #{headers.build_json}")
151
+ # TODO
152
+ end
153
+
154
+ def on_block(block)
155
+ logger.info("receive block message. #{block.build_json}")
156
+ # TODO
157
+ end
158
+
159
+ def on_tx(tx)
160
+ logger.info("receive tx message. #{tx.build_json}")
161
+ # TODO
162
+ end
163
+
164
+ def on_not_found(not_found)
165
+ logger.info("receive notfound message. #{not_found.build_json}")
166
+ # TODO
167
+ end
168
+
169
+ def on_mem_pool
170
+ logger.info('receive mempool message.')
171
+ # TODO return mempool tx
172
+ end
173
+
174
+ def on_reject(reject)
175
+ logger.warn("receive reject message. #{reject.build_json}")
176
+ # TODO
177
+ end
178
+
179
+ def on_send_cmpct(cmpct)
180
+ logger.info("receive sendcmpct message. #{cmpct.build_json}")
181
+ # TODO if mode is high and version is 1, relay block with cmpctblock message
182
+ end
183
+
184
+ def on_inv(inv)
185
+ logger.info("receive inv message. #{inv.build_json}")
186
+ # TODO
187
+ end
188
+
189
+
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,55 @@
1
+ module Bitcoin
2
+ module Network
3
+
4
+ # remote peer class.
5
+ class Peer
6
+
7
+ # remote peer info
8
+ attr_reader :host
9
+ attr_reader :port
10
+ # remote peer connection
11
+ attr_accessor :conn
12
+ attr_accessor :connected
13
+ # parent pool
14
+ attr_reader :pool
15
+ attr_accessor :fee_rate
16
+
17
+ def initialize(host, port, pool)
18
+ @host = host
19
+ @port = port
20
+ @pool = pool
21
+ @connected = false
22
+ end
23
+
24
+ def connect
25
+ self.conn ||= EM.connect(host, port, Bitcoin::Network::Connection, self)
26
+ end
27
+
28
+ def connected?
29
+ @connected
30
+ end
31
+
32
+ def addr
33
+ "#{host}:#{port}"
34
+ end
35
+
36
+ def post_handshake
37
+ @connected = true
38
+ pool.handle_new_peer(self)
39
+ end
40
+
41
+ # broadcast tx.
42
+ def broadcast_tx(tx)
43
+ send_message(Bitcoin::Message::Tx.new(tx, ))
44
+ end
45
+
46
+ # check the remote peer support segwit.
47
+ def support_segwit?
48
+ return false unless conn.version
49
+ conn.version.services & Bitcoin::Message::SERVICE_FLAGS[:witness] > 0
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Bitcoin
2
+ module Network
3
+
4
+ class PeerDiscovery
5
+
6
+ attr_reader :logger
7
+
8
+ def initialize
9
+ @logger = Bitcoin::Logger.create(:debug)
10
+ end
11
+
12
+ # get peer addresses, from DNS seeds.
13
+ def peers
14
+ # TODO add find from previous connected peer at first.
15
+ find_from_dns_seeds
16
+ end
17
+
18
+ private
19
+
20
+ def find_from_dns_seeds
21
+ logger.debug 'discover peer address from DNS seeds.'
22
+ Bitcoin.chain_params.dns_seeds.map {|seed|
23
+ begin
24
+ Socket.getaddrinfo(seed, Bitcoin.chain_params.default_port).map{|a|a[2]}.uniq
25
+ rescue SocketError => e
26
+ logger.error "SocketError occurred when load DNS seed: #{seed}, error: #{e.message}"
27
+ end
28
+ }.flatten
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,74 @@
1
+ module Bitcoin
2
+
3
+ module Network
4
+
5
+ # Time between pings automatically sent out for latency probing and keepalive (in seconds).
6
+ PING_INTERVAL = 2 * 60
7
+ # Time after which to disconnect, after waiting for a ping response (or inactivity).
8
+ TIMEOUT_INTERVAL = 20 * 60
9
+ # Maximum number of automatic outgoing nodes
10
+ MAX_OUTBOUND_CONNECTIONS = 4
11
+
12
+ # peer pool class.
13
+ class Pool
14
+
15
+ attr_reader :peers # active peers
16
+ attr_reader :pending_peers # currently connecting peer
17
+ attr_reader :chain
18
+ attr_reader :max_outbound
19
+ attr_reader :logger
20
+ attr_reader :peer_discovery
21
+ attr_accessor :started
22
+
23
+ def initialize
24
+ @peers = []
25
+ @pending_peers = []
26
+ @max_outbound = MAX_OUTBOUND_CONNECTIONS
27
+ @chain = Bitcoin::Node::SPVBlockChain.new
28
+ @logger = Bitcoin::Logger.create(:debug)
29
+ @peer_discovery = PeerDiscovery.new
30
+ @started = false
31
+ end
32
+
33
+ # connecting other peers and begin network activity.
34
+ def start
35
+ raise 'Cannot start a peer pool twice.' if started
36
+ logger.debug 'Start connecting other pears.'
37
+ addr_list = peer_discovery.peers
38
+ port = Bitcoin.chain_params.default_port
39
+ Parallel.map(addr_list, in_processes: 3) do |ip|
40
+ if peers.size < MAX_OUTBOUND_CONNECTIONS
41
+ EM.run do
42
+ peer = Peer.new(ip, port, self)
43
+ pending_peers << peer
44
+ peer.connect
45
+ end
46
+ end
47
+ end
48
+ @started = true
49
+ end
50
+
51
+ # detect new peer connection.
52
+ def handle_new_peer(peer)
53
+ logger.debug "connected new peer #{peer.addr}"
54
+ peers << peer
55
+ pending_peers.delete(peer)
56
+ end
57
+
58
+ # terminate peers.
59
+ def terminate
60
+ peers.each {|peer| peer.close('terminate')}
61
+ @peers = []
62
+ @started = false
63
+ end
64
+
65
+ def broadcast(tx)
66
+ peers.each {|peer| peer.broadcast(tx) }
67
+ end
68
+
69
+ private
70
+
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ require 'parallel'
2
+ require 'eventmachine'
3
+
4
+ module Bitcoin
5
+ module Network
6
+
7
+ autoload :MessageHandler, 'bitcoin/network/message_handler'
8
+ autoload :Connection, 'bitcoin/network/connection'
9
+ autoload :Pool, 'bitcoin/network/pool'
10
+ autoload :Peer, 'bitcoin/network/peer'
11
+ autoload :PeerDiscovery, 'bitcoin/network/peer_discovery'
12
+
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ module Bitcoin
2
+ module Node
3
+
4
+ # SPV class
5
+ class SPV
6
+
7
+ attr_reader :pool
8
+ attr_reader :logger
9
+ attr_accessor :running
10
+
11
+ def initialize
12
+ @pool = Bitcoin::Network::Pool.new
13
+ @logger = Bitcoin::Logger.create(:debug)
14
+ @running = false
15
+ end
16
+
17
+ # open the node.
18
+ def run
19
+ return if running
20
+ logger.debug 'SPV node start running.'
21
+ pool.start
22
+ end
23
+
24
+ # close the node.
25
+ def shutdown
26
+ pool.terminate
27
+ logger.debug 'SPV node shutdown.'
28
+ end
29
+
30
+ # broadcast a transaction
31
+ def broadcast(tx)
32
+ pool.broadcast(tx)
33
+ logger.debug "broadcast tx: #{tx.to_payload.bth}"
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module Bitcoin
2
+ module Node
3
+
4
+ class SPVBlockChain
5
+
6
+ attr_reader :block_store
7
+
8
+ def initialize(block_store = Bitcoin::Store::SPVBlockStore.new)
9
+ @block_store = block_store
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ module Bitcoin
2
+ module Node
3
+ autoload :SPV, 'bitcoin/node/spv'
4
+ autoload :SPVBlockChain, 'bitcoin/node/spv_block_chain'
5
+ end
6
+ end
@@ -159,6 +159,11 @@ module Bitcoin
159
159
  (chunks.size == 1 || chunks[1].opcode <= OP_16)
160
160
  end
161
161
 
162
+ def op_return_data
163
+ return nil unless op_return?
164
+ chunks[1].pushed_data
165
+ end
166
+
162
167
  # whether data push only script which dose not include other opcode
163
168
  def push_only?
164
169
  chunks.each do |c|
@@ -184,6 +189,14 @@ module Bitcoin
184
189
  false
185
190
  end
186
191
 
192
+ # get witness commitment
193
+ def witness_commitment
194
+ return nil if !op_return? || op_return_data.bytesize < 36
195
+ buf = StringIO.new(op_return_data)
196
+ return nil unless buf.read(4).bth == WITNESS_COMMITMENT_HEADER
197
+ buf.read(32).bth
198
+ end
199
+
187
200
  # If this script is witness program, return its script code,
188
201
  # otherwise returns the self payload. ScriptInterpreter does not use this.
189
202
  def to_script_code(skip_separator_index = 0)
@@ -0,0 +1,11 @@
1
+ module Bitcoin
2
+
3
+ module Store
4
+
5
+ class SPVBlockStore
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,7 @@
1
+ module Bitcoin
2
+ module Store
3
+
4
+ autoload :SPVBlockStore, 'bitcoin/store/spv_block_store'
5
+
6
+ end
7
+ end
data/lib/bitcoin/tx.rb CHANGED
@@ -71,6 +71,17 @@ module Bitcoin
71
71
  Bitcoin.double_sha256(to_payload).reverse.bth
72
72
  end
73
73
 
74
+ # get the witness commitment of coinbase tx.
75
+ # if this tx does not coinbase or not have commitment, return nil.
76
+ def witness_commitment
77
+ return nil unless coinbase_tx?
78
+ outputs.each do |output|
79
+ commitment = output.script_pubkey.witness_commitment
80
+ return commitment if commitment
81
+ end
82
+ nil
83
+ end
84
+
74
85
  def to_payload
75
86
  witness? ? serialize_witness_format : serialize_old_format
76
87
  end
@@ -3,6 +3,8 @@ module Bitcoin
3
3
  # transaction output
4
4
  class TxOut
5
5
 
6
+ include OpenAssets::MarkerOutput
7
+
6
8
  attr_accessor :value
7
9
  attr_accessor :script_pubkey
8
10
 
@@ -6,47 +6,69 @@ module Bitcoin
6
6
  def check_tx(tx, state)
7
7
  # Basic checks that don't depend on any context
8
8
  if tx.inputs.empty?
9
- return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-vin-empty')
9
+ return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vin-empty')
10
10
  end
11
11
 
12
12
  if tx.outputs.empty?
13
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-vout-empty')
13
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-empty')
14
14
  end
15
15
 
16
16
  # Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
17
17
  if tx.serialize_old_format.bytesize * Bitcoin::WITNESS_SCALE_FACTOR > Bitcoin::MAX_BLOCK_WEIGHT
18
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-oversize')
18
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-oversize')
19
19
  end
20
20
 
21
21
  # Check for negative or overflow output values
22
22
  amount = 0
23
23
  tx.outputs.each do |o|
24
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-vout-negative') if o.value < 0
25
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-vout-toolarge') if MAX_MONEY < o.value
24
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-negative') if o.value < 0
25
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge') if MAX_MONEY < o.value
26
26
  amount += o.value
27
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-vout-toolarge') if MAX_MONEY < amount
27
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge') if MAX_MONEY < amount
28
28
  end
29
29
 
30
30
  # Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
31
31
  out_points = tx.inputs.map{|i|i.out_point.to_payload}
32
32
  unless out_points.size == out_points.uniq.size
33
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-inputs-duplicate')
33
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-inputs-duplicate')
34
34
  end
35
35
 
36
36
  if tx.coinbase_tx?
37
37
  if tx.inputs[0].script_sig.size < 2 || tx.inputs[0].script_sig.size > 100
38
- return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-cb-length')
38
+ return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-cb-length')
39
39
  end
40
40
  else
41
41
  tx.inputs.each do |i|
42
42
  if i.out_point.nil? || !i.out_point.valid?
43
- return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_resoin: 'bad-txns-prevout-null')
43
+ return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-prevout-null')
44
44
  end
45
45
  end
46
46
  end
47
47
  true
48
48
  end
49
49
 
50
+ # check proof of work
51
+ def check_block_header(header, state)
52
+ header.hash
53
+ header.bits
54
+
55
+ end
56
+
57
+ def check_block(block, state)
58
+ # check block header
59
+ return false unless check_block_header(block.header, state)
60
+
61
+ # check merkle root
62
+
63
+ # size limits
64
+
65
+ # first tx is coinbase?
66
+
67
+ # check tx count
68
+
69
+ # check sigop count
70
+ end
71
+
50
72
  end
51
73
 
52
74
  class ValidationState
@@ -67,9 +89,9 @@ module Bitcoin
67
89
  @corruption_possible = false
68
90
  end
69
91
 
70
- def DoS(level, ret: false, reject_code: 0, reject_resoin: '', corruption_in: false, debug_message: '')
92
+ def DoS(level, ret: false, reject_code: 0, reject_reason: '', corruption_in: false, debug_message: '')
71
93
  @reject_code = reject_code
72
- @reject_reason = reject_resoin
94
+ @reject_reason = reject_reason
73
95
  @corruption_possible = corruption_in
74
96
  @debug_message = debug_message
75
97
  return ret if mode == MODE[:error]
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/bitcoin.rb CHANGED
@@ -5,14 +5,15 @@ require 'securerandom'
5
5
  require 'json'
6
6
  require 'bech32'
7
7
  require 'ffi'
8
+ require_relative 'openassets'
8
9
 
9
10
  module Bitcoin
10
11
 
11
12
  autoload :Util, 'bitcoin/util'
12
13
  autoload :ChainParams, 'bitcoin/chain_params'
13
14
  autoload :Message, 'bitcoin/message'
14
- autoload :Connection, 'bitcoin/connection'
15
15
  autoload :Logger, 'bitcoin/logger'
16
+ autoload :Block, 'bitcoin/block'
16
17
  autoload :BlockHeader, 'bitcoin/block_header'
17
18
  autoload :Tx, 'bitcoin/tx'
18
19
  autoload :Script, 'bitcoin/script/script'
@@ -27,11 +28,13 @@ module Bitcoin
27
28
  autoload :Key, 'bitcoin/key'
28
29
  autoload :ExtKey, 'bitcoin/ext_key'
29
30
  autoload :Opcodes, 'bitcoin/opcodes'
30
- autoload :Node, 'bitcoin/nodes'
31
+ autoload :Node, 'bitcoin/node'
31
32
  autoload :Base58, 'bitcoin/base58'
32
33
  autoload :Secp256k1, 'bitcoin/secp256k1'
33
34
  autoload :Mnemonic, 'bitcoin/mnemonic'
34
35
  autoload :ValidationState, 'bitcoin/validation'
36
+ autoload :Network, 'bitcoin/network'
37
+ autoload :Store, 'bitcoin/store'
35
38
 
36
39
  require_relative 'bitcoin/constants'
37
40
 
@@ -0,0 +1,14 @@
1
+ module OpenAssets
2
+
3
+ module MarkerOutput
4
+
5
+ # whether this output is marker output for open assets.
6
+ def open_assets_marker?
7
+ return false unless script_pubkey.op_return?
8
+ payload = Payload.parse_from_payload(script_pubkey.op_return_data)
9
+ !payload.nil?
10
+ end
11
+
12
+ end
13
+
14
+ end