bitcoin-ruby 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +2 -7
- data/COPYING +1 -1
- data/Gemfile +2 -6
- data/Gemfile.lock +34 -0
- data/README.rdoc +16 -68
- data/Rakefile +3 -6
- data/bin/bitcoin_shell +0 -1
- data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
- data/lib/bitcoin.rb +350 -296
- data/lib/bitcoin/builder.rb +3 -1
- data/lib/bitcoin/connection.rb +2 -1
- data/lib/bitcoin/contracthash.rb +76 -0
- data/lib/bitcoin/dogecoin.rb +97 -0
- data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
- data/lib/bitcoin/ffi/openssl.rb +98 -2
- data/lib/bitcoin/ffi/secp256k1.rb +144 -0
- data/lib/bitcoin/key.rb +12 -2
- data/lib/bitcoin/logger.rb +3 -12
- data/lib/bitcoin/protocol/block.rb +3 -9
- data/lib/bitcoin/protocol/parser.rb +6 -2
- data/lib/bitcoin/protocol/tx.rb +44 -13
- data/lib/bitcoin/protocol/txin.rb +4 -2
- data/lib/bitcoin/protocol/txout.rb +2 -2
- data/lib/bitcoin/script.rb +212 -37
- data/lib/bitcoin/trezor/mnemonic.rb +130 -0
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bitcoin_spec.rb +32 -3
- data/spec/bitcoin/builder_spec.rb +18 -0
- data/spec/bitcoin/contracthash_spec.rb +45 -0
- data/spec/bitcoin/dogecoin_spec.rb +176 -0
- data/spec/bitcoin/ffi_openssl.rb +45 -0
- data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
- data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
- data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
- data/spec/bitcoin/fixtures/coinbase.json +24 -0
- data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
- data/spec/bitcoin/protocol/block_spec.rb +0 -22
- data/spec/bitcoin/protocol/tx_spec.rb +145 -2
- data/spec/bitcoin/script/script_spec.rb +282 -0
- data/spec/bitcoin/secp256k1_spec.rb +48 -0
- data/spec/bitcoin/spec_helper.rb +0 -51
- data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
- metadata +48 -98
- data/bin/bitcoin_dns_seed +0 -130
- data/bin/bitcoin_gui +0 -80
- data/bin/bitcoin_node +0 -153
- data/bin/bitcoin_node_cli +0 -81
- data/bin/bitcoin_wallet +0 -402
- data/doc/CONFIG.rdoc +0 -66
- data/doc/EXAMPLES.rdoc +0 -13
- data/doc/NAMECOIN.rdoc +0 -34
- data/doc/NODE.rdoc +0 -225
- data/doc/STORAGE.rdoc +0 -33
- data/doc/WALLET.rdoc +0 -102
- data/examples/balance.rb +0 -66
- data/examples/forwarder.rb +0 -73
- data/examples/index_nhash.rb +0 -24
- data/examples/reindex_p2sh_addrs.rb +0 -44
- data/examples/relay_tx.rb +0 -22
- data/examples/verify_tx.rb +0 -57
- data/lib/bitcoin/config.rb +0 -58
- data/lib/bitcoin/gui/addr_view.rb +0 -44
- data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
- data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
- data/lib/bitcoin/gui/conn_view.rb +0 -38
- data/lib/bitcoin/gui/connection.rb +0 -70
- data/lib/bitcoin/gui/em_gtk.rb +0 -30
- data/lib/bitcoin/gui/gui.builder +0 -1643
- data/lib/bitcoin/gui/gui.rb +0 -292
- data/lib/bitcoin/gui/helpers.rb +0 -115
- data/lib/bitcoin/gui/tree_view.rb +0 -84
- data/lib/bitcoin/gui/tx_view.rb +0 -69
- data/lib/bitcoin/namecoin.rb +0 -280
- data/lib/bitcoin/network/command_client.rb +0 -104
- data/lib/bitcoin/network/command_handler.rb +0 -570
- data/lib/bitcoin/network/connection_handler.rb +0 -387
- data/lib/bitcoin/network/node.rb +0 -565
- data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
- data/lib/bitcoin/storage/models.rb +0 -171
- data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
- data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
- data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
- data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
- data/lib/bitcoin/storage/storage.rb +0 -517
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
- data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
- data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
- data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
- data/lib/bitcoin/validation.rb +0 -400
- data/lib/bitcoin/wallet/coinselector.rb +0 -33
- data/lib/bitcoin/wallet/keygenerator.rb +0 -77
- data/lib/bitcoin/wallet/keystore.rb +0 -207
- data/lib/bitcoin/wallet/txdp.rb +0 -118
- data/lib/bitcoin/wallet/wallet.rb +0 -281
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
- data/spec/bitcoin/namecoin_spec.rb +0 -182
- data/spec/bitcoin/node/command_api_spec.rb +0 -663
- data/spec/bitcoin/storage/models_spec.rb +0 -104
- data/spec/bitcoin/storage/reorg_spec.rb +0 -236
- data/spec/bitcoin/storage/storage_spec.rb +0 -387
- data/spec/bitcoin/storage/validation_spec.rb +0 -300
- data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
- data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
- data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
- data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
- data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
data/lib/bitcoin/gui/tx_view.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
module Bitcoin::Gui
|
4
|
-
class TxView < TreeView
|
5
|
-
|
6
|
-
def initialize gui, replace = nil
|
7
|
-
super(gui, :tx_view, [
|
8
|
-
[GObject::TYPE_STRING, "Type"],
|
9
|
-
[GObject::TYPE_STRING, "Hash"],
|
10
|
-
[GObject::TYPE_STRING, "Value", :format_value_col],
|
11
|
-
[GObject::TYPE_INT, "Confirmations"],
|
12
|
-
[GObject::TYPE_STRING, "Direction"],
|
13
|
-
])
|
14
|
-
GObject.signal_connect(@view, "row-activated") do |view, path, column|
|
15
|
-
res, iter = @model.get_iter(path)
|
16
|
-
next unless res
|
17
|
-
tx_hash = @model.get_value(iter, 1).get_string
|
18
|
-
@gui.display_tx(tx_hash)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def update txouts
|
23
|
-
EM.defer do
|
24
|
-
@model.clear
|
25
|
-
txouts.each do |txout|
|
26
|
-
row = @model.append(nil)
|
27
|
-
@model.set_value(row, 0, txout.type.to_s)
|
28
|
-
@model.set_value(row, 1, txout.get_tx.hash)
|
29
|
-
@model.set_value(row, 2, txout.value.to_s)
|
30
|
-
@model.set_value(row, 3, txout.get_tx.confirmations)
|
31
|
-
@model.set_value(row, 4, "incoming")
|
32
|
-
if txin = txout.get_next_in
|
33
|
-
row = @model.append(nil)
|
34
|
-
@model.set_value(row, 0, txout.type.to_s)
|
35
|
-
@model.set_value(row, 1, txin.get_tx.hash)
|
36
|
-
@model.set_value(row, 2, (0 - txout.value).to_s)
|
37
|
-
@model.set_value(row, 3, txin.get_tx.confirmations)
|
38
|
-
@model.set_value(row, 4, "outgoing")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
@view.set_model @model
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class TxInView < TreeView
|
47
|
-
def initialize gui, replace = nil
|
48
|
-
super(gui, [
|
49
|
-
[GObject::TYPE_STRING, "Type"],
|
50
|
-
[GObject::TYPE_STRING, "From"],
|
51
|
-
[GObject::TYPE_STRING, "Value", :format_value_col]
|
52
|
-
])
|
53
|
-
old = @gui.builder.get_object("tx_view")
|
54
|
-
end
|
55
|
-
|
56
|
-
def update txins
|
57
|
-
@model.clear
|
58
|
-
txins.each do |txin|
|
59
|
-
txout = txin.get_prev_out
|
60
|
-
row = @model.append(nil)
|
61
|
-
@model.set_value(row, 0, txout.type.to_s)
|
62
|
-
@model.set_value(row, 1, txout.get_addresses.join(", "))
|
63
|
-
@model.set_value(row, 2, txout.value.to_s)
|
64
|
-
end
|
65
|
-
@view.set_model @model
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
data/lib/bitcoin/namecoin.rb
DELETED
@@ -1,280 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
# This module includes (almost) everything necessary to add namecoin support
|
4
|
-
# to bitcoin-ruby. When switching to a :namecoin network, it will load its
|
5
|
-
# functionality into the Script class and the Storage backend.
|
6
|
-
# The only things not included here should be parsing the AuxPow, which is
|
7
|
-
# done in Protocol::Block directly, and passing the txout to #store_name from
|
8
|
-
# the storage backend.
|
9
|
-
module Bitcoin::Namecoin
|
10
|
-
|
11
|
-
def self.load
|
12
|
-
Bitcoin::Script.class_eval { include Script }
|
13
|
-
Bitcoin::Storage::Backends::StoreBase.class_eval { include Storage::Backend }
|
14
|
-
Bitcoin::Storage::Models.class_eval { include Storage::Models }
|
15
|
-
end
|
16
|
-
|
17
|
-
# name_new must have 12 confirmations before corresponding name_firstupdate is valid.
|
18
|
-
FIRSTUPDATE_LIMIT = 12
|
19
|
-
|
20
|
-
# number of blocks after which a name expires.
|
21
|
-
EXPIRATION_DEPTH = 36000
|
22
|
-
|
23
|
-
# Namecoin-specific Script methods for parsing and creating of namecoin scripts,
|
24
|
-
# as well as methods to extract address, name_hash, name and value.
|
25
|
-
module Script
|
26
|
-
|
27
|
-
def self.included(base)
|
28
|
-
base.constants.each {|c| const_set(c, base.const_get(c)) unless constants.include?(c) }
|
29
|
-
base.class_eval do
|
30
|
-
|
31
|
-
# get the hash160 for this hash160, namecoin or pubkey script
|
32
|
-
def get_hash160
|
33
|
-
return @chunks[2..-3][0].unpack("H*")[0] if is_hash160?
|
34
|
-
return @chunks[-3].unpack("H*")[0] if is_namecoin?
|
35
|
-
return @chunks[-2].unpack("H*")[0] if is_p2sh?
|
36
|
-
return Bitcoin.hash160(get_pubkey) if is_pubkey?
|
37
|
-
end
|
38
|
-
|
39
|
-
# get all addresses this script corresponds to (if possible)
|
40
|
-
def get_addresses
|
41
|
-
return [get_pubkey_address] if is_pubkey?
|
42
|
-
return [get_hash160_address] if is_hash160? || is_namecoin?
|
43
|
-
return get_multisig_addresses if is_multisig?
|
44
|
-
end
|
45
|
-
|
46
|
-
# get type of this tx
|
47
|
-
def type
|
48
|
-
if is_name_new?; :name_new
|
49
|
-
elsif is_name_firstupdate?; :name_firstupdate
|
50
|
-
elsif is_name_update?; :name_update
|
51
|
-
elsif is_hash160?; :hash160
|
52
|
-
elsif is_pubkey?; :pubkey
|
53
|
-
elsif is_multisig?; :multisig
|
54
|
-
elsif is_p2sh?; :p2sh
|
55
|
-
else; :unknown
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# is namecoin name_new script
|
60
|
-
# OP_1 name_hash OP_2DROP <hash160_script>
|
61
|
-
def is_name_new?
|
62
|
-
return false if @chunks.size < 8
|
63
|
-
[-8, -6, -5, -4, -2, -1].map {|i| @chunks[i] } ==
|
64
|
-
[OP_1, OP_2DROP, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG]
|
65
|
-
end
|
66
|
-
|
67
|
-
# is namecoin name_firstupdate script
|
68
|
-
# OP_2 name rand value OP_2DROP OP_2DROP <hash160_script>
|
69
|
-
def is_name_firstupdate?
|
70
|
-
return false if @chunks.size < 11
|
71
|
-
[-11, -7, -6, -5, -4, -2, -1].map {|i| @chunks[i] } ==
|
72
|
-
[82, OP_2DROP, OP_2DROP, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG]
|
73
|
-
end
|
74
|
-
|
75
|
-
# is namecoin name_update script
|
76
|
-
# OP_3 name value OP_2DROP OP_DROP <hash160_script>
|
77
|
-
def is_name_update?
|
78
|
-
return false if @chunks.size < 10
|
79
|
-
[-10, -7, -6, -5, -4, -2, -1].map {|i| @chunks[i] } ==
|
80
|
-
[83, OP_2DROP, OP_DROP, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG]
|
81
|
-
end
|
82
|
-
|
83
|
-
# is any kind of namecoin script
|
84
|
-
def is_namecoin?
|
85
|
-
is_name_new? || is_name_firstupdate? || is_name_update?
|
86
|
-
end
|
87
|
-
|
88
|
-
# get the name_hash of a namecoin name_new script
|
89
|
-
def get_namecoin_hash
|
90
|
-
return @chunks[-7].hth if is_name_new?
|
91
|
-
if is_name_firstupdate?
|
92
|
-
name = @chunks[-10].to_s.hth
|
93
|
-
rand = @chunks[-9].to_s.hth
|
94
|
-
return Bitcoin.hash160(rand + name)
|
95
|
-
end
|
96
|
-
rescue
|
97
|
-
nil
|
98
|
-
end
|
99
|
-
|
100
|
-
# get the name of a namecoin name_firstupdate or name_update script
|
101
|
-
def get_namecoin_name
|
102
|
-
return @chunks[-10] if is_name_firstupdate?
|
103
|
-
return @chunks[-9] if is_name_update?
|
104
|
-
end
|
105
|
-
|
106
|
-
# get the value of a namecoin name_firstupdate or name_update script
|
107
|
-
def get_namecoin_value
|
108
|
-
@chunks[-8] if is_name_firstupdate? || is_name_update?
|
109
|
-
end
|
110
|
-
|
111
|
-
# generate name_new tx for given +name+ and +address+.
|
112
|
-
# the +caller+ should be the object that creates the script.
|
113
|
-
# it gets the used random value passed to #set_rand.
|
114
|
-
# OP_1 name_hash OP_2DROP <hash160_script>
|
115
|
-
def self.to_name_new_script(caller, name, address)
|
116
|
-
rand = rand(2**64).to_s(16).rjust(16, '0')
|
117
|
-
name_hash = Bitcoin.hash160(rand + name.unpack("H*")[0])
|
118
|
-
caller.set_rand rand # TODO: this is still ugly
|
119
|
-
[ [ "51", "14", name_hash, "6d" ].join ].pack("H*") + to_address_script(address)
|
120
|
-
end
|
121
|
-
|
122
|
-
# generate name_firstupdate tx for given +name+, +rand+, +value+ and +address+.
|
123
|
-
# OP_2 name rand value OP_2DROP OP_2DROP <hash160_script>
|
124
|
-
def self.to_name_firstupdate_script(name, rand, value, address)
|
125
|
-
[ [ "52", name.bytesize.to_s(16).rjust(2, '0'), name.hth,
|
126
|
-
rand.htb.bytesize.to_s(16).rjust(2, '0'), rand,
|
127
|
-
value.bytesize.to_s(16).rjust(2, '0'), value.hth,
|
128
|
-
"6d", "6d" ].join ].pack("H*") + to_address_script(address)
|
129
|
-
end
|
130
|
-
|
131
|
-
# generate name_update script for given +name+, +value+ and +address+.
|
132
|
-
# OP_3 name value OP_2DROP OP_DROP <hash160_script>
|
133
|
-
def self.to_name_update_script(name, value, address)
|
134
|
-
[ [ "53", name.bytesize.to_s(16).rjust(2, '0'), name.hth,
|
135
|
-
value.bytesize.to_s(16).rjust(2, '0'), value.hth,
|
136
|
-
"6d", "75" ].join ].pack("H*") + to_address_script(address)
|
137
|
-
end
|
138
|
-
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
# Namecoin-specific storage methods.
|
145
|
-
# The storage backend only needs to check txout scripts with #is_namecoin? and
|
146
|
-
# pass them to #store_name.
|
147
|
-
# TODO: move rules into Validation
|
148
|
-
module Storage
|
149
|
-
|
150
|
-
module Backend
|
151
|
-
|
152
|
-
def self.included(base)
|
153
|
-
base.constants.each {|c| const_set(c, base.const_get(c)) unless constants.include?(c) }
|
154
|
-
base.class_eval do
|
155
|
-
|
156
|
-
# if this is a namecoin script, update the names index
|
157
|
-
def store_name(script, txout_id)
|
158
|
-
if script.type == :name_new
|
159
|
-
log.debug { "name_new #{script.get_namecoin_hash}" }
|
160
|
-
@db[:names].insert({
|
161
|
-
:txout_id => txout_id,
|
162
|
-
:hash => script.get_namecoin_hash })
|
163
|
-
elsif script.type == :name_firstupdate
|
164
|
-
name_hash = script.get_namecoin_hash
|
165
|
-
name_new = @db[:names].where(:hash => name_hash).order(:txout_id).first
|
166
|
-
if self.class.name =~ /UtxoStore/
|
167
|
-
txout = @db[:utxo][id: name_new[:txout_id]] if name_new
|
168
|
-
blk = @db[:blk][id: txout[:blk_id]] if txout
|
169
|
-
else
|
170
|
-
txout = @db[:txout][id: name_new[:txout_id]] if name_new
|
171
|
-
tx = @db[:tx][id: txout[:tx_id]] if txout
|
172
|
-
blk_tx = @db[:blk_tx][tx_id: tx[:id]] if tx
|
173
|
-
blk = @db[:blk][id: blk_tx[:blk_id]] if blk_tx
|
174
|
-
end
|
175
|
-
|
176
|
-
unless name_new && blk && blk[:chain] == 0
|
177
|
-
log.debug { "name_new not found: #{name_hash}" }
|
178
|
-
return nil
|
179
|
-
end
|
180
|
-
|
181
|
-
unless blk[:depth] <= get_depth - Bitcoin::Namecoin::FIRSTUPDATE_LIMIT
|
182
|
-
log.debug { "name_new not yet valid: #{name_hash}" }
|
183
|
-
return nil
|
184
|
-
end
|
185
|
-
|
186
|
-
log.debug { "#{script.type}: #{script.get_namecoin_name}" }
|
187
|
-
@db[:names].where(:txout_id => name_new[:txout_id], :name => nil).update({
|
188
|
-
:name => script.get_namecoin_name.to_s.to_sequel_blob })
|
189
|
-
@db[:names].insert({
|
190
|
-
:txout_id => txout_id,
|
191
|
-
:hash => name_hash,
|
192
|
-
:name => script.get_namecoin_name.to_s.to_sequel_blob,
|
193
|
-
:value => script.get_namecoin_value.to_s.to_sequel_blob })
|
194
|
-
elsif script.type == :name_update
|
195
|
-
log.debug { "#{script.type}: #{script.get_namecoin_name}" }
|
196
|
-
@db[:names].insert({
|
197
|
-
:txout_id => txout_id,
|
198
|
-
:name => script.get_namecoin_name.to_s.to_sequel_blob,
|
199
|
-
:value => script.get_namecoin_value.to_s.to_sequel_blob })
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def name_show name
|
204
|
-
names = @db[:names].where(:name => name.to_sequel_blob).order(:txout_id).reverse
|
205
|
-
return nil unless names.any?
|
206
|
-
wrap_name(names.first)
|
207
|
-
end
|
208
|
-
alias :get_name :name_show
|
209
|
-
|
210
|
-
def name_history name
|
211
|
-
history = @db[:names].where(:name => name.to_sequel_blob)
|
212
|
-
.where("value IS NOT NULL").order(:txout_id).map {|n| wrap_name(n) }
|
213
|
-
history.select! {|n| n.get_tx.blk_id } unless self.class.name =~ /Utxo/
|
214
|
-
history
|
215
|
-
end
|
216
|
-
|
217
|
-
def get_name_by_txout_id txout_id
|
218
|
-
wrap_name(@db[:names][:txout_id => txout_id])
|
219
|
-
end
|
220
|
-
|
221
|
-
def wrap_name(data)
|
222
|
-
return nil unless data
|
223
|
-
Bitcoin::Storage::Models::Name.new(self, data)
|
224
|
-
end
|
225
|
-
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
end
|
230
|
-
|
231
|
-
module Models
|
232
|
-
|
233
|
-
class Name
|
234
|
-
|
235
|
-
attr_reader :store, :txout_id, :hash, :name, :value
|
236
|
-
|
237
|
-
def initialize store, data
|
238
|
-
@store = store
|
239
|
-
@txout_id = data[:txout_id]
|
240
|
-
@hash = data[:hash]
|
241
|
-
@name = data[:name]
|
242
|
-
@value = data[:value]
|
243
|
-
end
|
244
|
-
|
245
|
-
def get_txout
|
246
|
-
if @txout_id.is_a?(Array)
|
247
|
-
@store.get_tx(@txout_id[0]).out[@txout_id[1]]
|
248
|
-
else
|
249
|
-
@store.get_txout_by_id(@txout_id)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def get_address
|
254
|
-
get_txout.get_address
|
255
|
-
end
|
256
|
-
|
257
|
-
def get_tx
|
258
|
-
get_txout.get_tx rescue nil
|
259
|
-
end
|
260
|
-
|
261
|
-
def get_block
|
262
|
-
get_tx.get_block rescue nil
|
263
|
-
end
|
264
|
-
|
265
|
-
def expires_in
|
266
|
-
Bitcoin::Namecoin::EXPIRATION_DEPTH - (@store.get_depth - get_block.depth) rescue nil
|
267
|
-
end
|
268
|
-
|
269
|
-
def as_json(opts = {})
|
270
|
-
{ name: @name, value: @value, txid: get_tx.hash,
|
271
|
-
address: get_address, expires_in: expires_in }
|
272
|
-
end
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
end
|
277
|
-
|
278
|
-
end
|
279
|
-
|
280
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
# Client to connect to CommandHandler and issue requests or register for events
|
6
|
-
class Bitcoin::Network::CommandClient < EM::Connection
|
7
|
-
|
8
|
-
# create new client connecting to +host+:+port+ and executing callbacks from +block+,
|
9
|
-
# passing +args+ in.
|
10
|
-
# CommandClient.connect(host, port) do
|
11
|
-
# on_connected { request("info") }
|
12
|
-
# on_info {|i| p i}
|
13
|
-
# end
|
14
|
-
def initialize host, port, block, *args
|
15
|
-
@host, @port = host, port
|
16
|
-
@args = args
|
17
|
-
@callbacks = {}
|
18
|
-
@block = block
|
19
|
-
instance_eval &block if block
|
20
|
-
@buffer = BufferedTokenizer.new("\x00")
|
21
|
-
@connection_attempts = 0
|
22
|
-
@requests = {}
|
23
|
-
@i = 0
|
24
|
-
end
|
25
|
-
|
26
|
-
def log;
|
27
|
-
@log ||= Bitcoin::Logger.create(:client)
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.connect host, port, *args, &block
|
31
|
-
client = EM.connect(host, port.to_i, self, host, port.to_i, block, *args)
|
32
|
-
end
|
33
|
-
|
34
|
-
# call +connected+ callback
|
35
|
-
def post_init
|
36
|
-
log.debug { "Connected" }
|
37
|
-
request(:connected) { callback(:connected) }
|
38
|
-
end
|
39
|
-
|
40
|
-
# call +disconnected+ callback and try to reconnect
|
41
|
-
def unbind
|
42
|
-
log.debug { "Disconnected." }
|
43
|
-
callback :disconnected
|
44
|
-
EM.add_timer(@connection_attempts) do
|
45
|
-
@connection_attempts += 1
|
46
|
-
reconnect(@host, @port)
|
47
|
-
post_init
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# request command +cmd+ with +args+ from the server
|
52
|
-
def request cmd, params = nil, &block
|
53
|
-
id = @i += 1
|
54
|
-
@requests[id] = block if block
|
55
|
-
log.debug { "request: #{cmd} #{args.inspect}" }
|
56
|
-
register_monitor_callbacks(params) if cmd.to_sym == :monitor
|
57
|
-
request = { id: id, method: cmd }
|
58
|
-
request[:params] = params if params
|
59
|
-
send_data(request.to_json + "\x00")
|
60
|
-
end
|
61
|
-
|
62
|
-
# receive response from server
|
63
|
-
def receive_data data
|
64
|
-
@connection_attempts = 0
|
65
|
-
@buffer.extract(data).each do |packet|
|
66
|
-
response = JSON.parse(packet)
|
67
|
-
log.debug { d = response['result'].inspect
|
68
|
-
"response: #{response['method']} #{d[0...50]}#{d.size > 50 ? '...' : ''}" }
|
69
|
-
if cb = @requests[response['id']]
|
70
|
-
cb.call(response['result'])
|
71
|
-
else
|
72
|
-
callback(:response, response['method'], response['result'])
|
73
|
-
callback(response['method'].to_sym, response['result'])
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# call the callback specified by +name+ passing in +args+
|
79
|
-
def callback name, *args
|
80
|
-
cb = @callbacks[name.to_sym]
|
81
|
-
return unless cb
|
82
|
-
log.debug { "callback: #{name}" }
|
83
|
-
cb.call(*args)
|
84
|
-
end
|
85
|
-
|
86
|
-
# register callback methods
|
87
|
-
def method_missing(name, *args, &block)
|
88
|
-
if name =~ /^on_/
|
89
|
-
@callbacks[name.to_s.split("on_")[1].to_sym] = block
|
90
|
-
log.debug { "callback #{name} registered" }
|
91
|
-
else
|
92
|
-
super(name, *args)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# register callbacks for monitor
|
97
|
-
def register_monitor_callbacks params
|
98
|
-
on_monitor do |data|
|
99
|
-
next if data.is_a?(Hash) && data.keys == ["id"]
|
100
|
-
callback(params["channel"], data)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|