bitcoinrb 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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