btcruby 1.0.5 → 1.0.6
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.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/RELEASE_NOTES.md +6 -0
- data/lib/btcruby/address.rb +5 -1
- data/lib/btcruby/transaction_input.rb +1 -0
- data/lib/btcruby/transaction_outpoint.rb +11 -1
- data/lib/btcruby/transaction_output.rb +2 -1
- data/lib/btcruby/version.rb +1 -1
- metadata +28 -18
- data/.gitignore +0 -20
- data/FAQ.md +0 -7
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -18
- data/HOWTO.md +0 -17
- data/Rakefile +0 -6
- data/TODO.txt +0 -40
- data/bin/console +0 -19
- data/btcruby.gemspec +0 -20
- data/sample_code/creating_a_p2sh_multisig_address.rb +0 -21
- data/sample_code/creating_a_transaction_manually.rb +0 -44
- data/sample_code/generating_an_address.rb +0 -20
- data/sample_code/using_transaction_builder.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b9b9d085300b3e99129f1512fa8b0b7794a4aa4
|
4
|
+
data.tar.gz: 7fc8e5d75b7518afd548c7c5dbf49b7c98ec7f7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 408fcbdd2fdc406a450382dcce2c86744a7c718f5a4d770a3a7c714f56a28b674d51a450968a2af857bac8c8390f37438efc8db8ef6e5003dc35a4623b3d5204
|
7
|
+
data.tar.gz: 48b073e59fa89922faa469dff926beff3261ef762270efd18de1ba31aabb5506ff84d7297d582192d392d7daee4fec7bb284ee04e0d5445e920dd9df62ead358
|
data/README.md
CHANGED
data/RELEASE_NOTES.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
BTCRuby Release Notes
|
3
3
|
=====================
|
4
4
|
|
5
|
+
1.0.6 (July 13, 2015)
|
6
|
+
--------------------
|
7
|
+
|
8
|
+
* Consistent aliasing between `==` and `eql?`
|
9
|
+
* `TransactionOutpoint` implements `hash` method so it can be used as a key in a dictionary.
|
10
|
+
|
5
11
|
1.0.5 (July 8, 2015)
|
6
12
|
--------------------
|
7
13
|
|
data/lib/btcruby/address.rb
CHANGED
@@ -111,9 +111,13 @@ module BTC
|
|
111
111
|
# Two instances are equal when they have the same contents and versions.
|
112
112
|
def ==(other)
|
113
113
|
return false if !other
|
114
|
-
|
114
|
+
data == other.data && version == other.version
|
115
115
|
end
|
116
116
|
alias_method :eql?, :==
|
117
|
+
|
118
|
+
def hash
|
119
|
+
data.hash
|
120
|
+
end
|
117
121
|
|
118
122
|
# Returns Base58Check representation of an address.
|
119
123
|
def to_s
|
@@ -22,7 +22,17 @@ module BTC
|
|
22
22
|
def outpoint_id
|
23
23
|
%{#{transaction_id}:#{index}}
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
index == other.index &&
|
28
|
+
transaction_hash == other.transaction_hash
|
29
|
+
end
|
30
|
+
alias_method :eql?, :==
|
31
|
+
|
32
|
+
def hash
|
33
|
+
transaction_hash.hash ^ index
|
34
|
+
end
|
35
|
+
|
26
36
|
def to_s
|
27
37
|
outpoint_id
|
28
38
|
end
|
@@ -275,9 +275,10 @@ module BTC
|
|
275
275
|
|
276
276
|
def ==(other)
|
277
277
|
return true if super(other)
|
278
|
-
return true if
|
278
|
+
return true if data == other.data
|
279
279
|
return false
|
280
280
|
end
|
281
|
+
alias_method :eql?, :==
|
281
282
|
|
282
283
|
# Makes a deep copy of a transaction output
|
283
284
|
def dup
|
data/lib/btcruby/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: btcruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Andreev
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-07-
|
12
|
+
date: 2015-07-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -31,24 +31,15 @@ dependencies:
|
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.9.3
|
34
|
-
description:
|
34
|
+
description: Bitcoin toolkit for Ruby
|
35
35
|
email: oleganza+btcruby@gmail.com
|
36
36
|
executables: []
|
37
37
|
extensions: []
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
|
-
- ".gitignore"
|
41
|
-
- FAQ.md
|
42
|
-
- Gemfile
|
43
|
-
- Gemfile.lock
|
44
|
-
- HOWTO.md
|
45
40
|
- LICENSE
|
46
41
|
- README.md
|
47
42
|
- RELEASE_NOTES.md
|
48
|
-
- Rakefile
|
49
|
-
- TODO.txt
|
50
|
-
- bin/console
|
51
|
-
- btcruby.gemspec
|
52
43
|
- documentation/address.md
|
53
44
|
- documentation/base58.md
|
54
45
|
- documentation/block.md
|
@@ -127,10 +118,6 @@ files:
|
|
127
118
|
- lib/btcruby/version.rb
|
128
119
|
- lib/btcruby/wif.rb
|
129
120
|
- lib/btcruby/wire_format.rb
|
130
|
-
- sample_code/creating_a_p2sh_multisig_address.rb
|
131
|
-
- sample_code/creating_a_transaction_manually.rb
|
132
|
-
- sample_code/generating_an_address.rb
|
133
|
-
- sample_code/using_transaction_builder.rb
|
134
121
|
- spec/address_spec.rb
|
135
122
|
- spec/all.rb
|
136
123
|
- spec/base58_spec.rb
|
@@ -179,5 +166,28 @@ rubyforge_project: btcruby
|
|
179
166
|
rubygems_version: 2.4.5
|
180
167
|
signing_key:
|
181
168
|
specification_version: 4
|
182
|
-
summary:
|
183
|
-
test_files:
|
169
|
+
summary: Rich library for building awesome Bitcoin apps.
|
170
|
+
test_files:
|
171
|
+
- spec/address_spec.rb
|
172
|
+
- spec/base58_spec.rb
|
173
|
+
- spec/block_header_spec.rb
|
174
|
+
- spec/block_spec.rb
|
175
|
+
- spec/currency_formatter_spec.rb
|
176
|
+
- spec/data_spec.rb
|
177
|
+
- spec/diagnostics_spec.rb
|
178
|
+
- spec/key_spec.rb
|
179
|
+
- spec/keychain_spec.rb
|
180
|
+
- spec/merkle_tree_spec.rb
|
181
|
+
- spec/network_spec.rb
|
182
|
+
- spec/open_assets/asset_address_spec.rb
|
183
|
+
- spec/open_assets/asset_id_spec.rb
|
184
|
+
- spec/open_assets/asset_marker_spec.rb
|
185
|
+
- spec/open_assets/asset_processor_spec.rb
|
186
|
+
- spec/open_assets/asset_transaction_builder_spec.rb
|
187
|
+
- spec/open_assets/asset_transaction_spec.rb
|
188
|
+
- spec/open_assets/issuance_id_spec.rb
|
189
|
+
- spec/proof_of_work_spec.rb
|
190
|
+
- spec/script_spec.rb
|
191
|
+
- spec/transaction_builder_spec.rb
|
192
|
+
- spec/transaction_spec.rb
|
193
|
+
- spec/wire_format_spec.rb
|
data/.gitignore
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
build/
|
2
|
-
*.pbxuser
|
3
|
-
!default.pbxuser
|
4
|
-
*.mode1v3
|
5
|
-
!default.mode1v3
|
6
|
-
*.mode2v3
|
7
|
-
!default.mode2v3
|
8
|
-
*.perspectivev3
|
9
|
-
!default.perspectivev3
|
10
|
-
xcuserdata
|
11
|
-
*.xccheckout
|
12
|
-
*.moved-aside
|
13
|
-
DerivedData
|
14
|
-
*.hmap
|
15
|
-
*.ipa
|
16
|
-
*.xcuserstate
|
17
|
-
*.xcodeproj
|
18
|
-
*.xcodeproj/
|
19
|
-
*.gem
|
20
|
-
.ruby-version
|
data/FAQ.md
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
data/HOWTO.md
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# BTCRuby HOWTO
|
2
|
-
|
3
|
-
* [Generating Private/Public Keys](#generating-privatepublic-keys)
|
4
|
-
|
5
|
-
## Generating Private/Public Keys
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
require 'btcruby'
|
9
|
-
require 'btcruby/extensions'
|
10
|
-
|
11
|
-
key = BTC::Key.random
|
12
|
-
|
13
|
-
prv = key.to_wif # => L2yVhzwp5F7NXUmP31j274MPjnWi7WbFs3qRJEcdrjyBZ9jmEdWb
|
14
|
-
pub = key.address.to_s # => 15M8ocGxsWtaenLQy6hDKXeLHqQgG3ebpB
|
15
|
-
|
16
|
-
puts [prv, pub].join(" - ")
|
17
|
-
```
|
data/Rakefile
DELETED
data/TODO.txt
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
|
2
|
-
TODO:
|
3
|
-
|
4
|
-
- verify integrity of the block after reading: hash all txs in a merkle root and compare with the declared merkle root.
|
5
|
-
- add BIP70 payment request support
|
6
|
-
- add convenience methods to handle BIP44 accounts in BTC::Keychain (like in CoreBitcoin)
|
7
|
-
- add Bitcoin URI support to encode and parse `bitcoin:` URIs.
|
8
|
-
|
9
|
-
+ replace factory methods like `C.with_data` or `C.with_key` with initializer since we now throw exceptions instead of returning nil on input errors.
|
10
|
-
+ block and block header classes
|
11
|
-
+ redesigned transaction builder to return a result object like in CoreBitcoin
|
12
|
-
+ data helpers
|
13
|
-
+ tests
|
14
|
-
+ base58
|
15
|
-
+ addresses
|
16
|
-
+ simplify API for addresses: Address.address_with_string() -> Address.with_string()
|
17
|
-
+ add test for private key address
|
18
|
-
+ keys and signatures support
|
19
|
-
+ canonical signature
|
20
|
-
+ deterministic signatures: k = HMAC-SHA256(hash, privkey)
|
21
|
-
+ add ffi to Gemspec as a dependency
|
22
|
-
+ transaction parsing and composing
|
23
|
-
+ script parsing and composing
|
24
|
-
+ tx import/export in bitcoin-QT dictionary format
|
25
|
-
+ add docs for to_wif/from_wif
|
26
|
-
+ add diagnostics to check canonicality of the signature
|
27
|
-
+ BIP32 implementation: Keychain
|
28
|
-
+ base58/base58check mess: untangle
|
29
|
-
+ specs and fixes for zero-padded private keys
|
30
|
-
+ clearer testnet/mainnet API for Script
|
31
|
-
+ fee computation for transactions
|
32
|
-
+ signature_hash for transaction
|
33
|
-
+ transaction builder
|
34
|
-
+ tx ID conversion to/from hash
|
35
|
-
+ helper properties for Transaction and inputs/outputs to hold extra data received from APIs.
|
36
|
-
|
37
|
-
- test tool to detect broken or non-canonical transactions
|
38
|
-
|
39
|
-
- compact signatures support
|
40
|
-
|
data/bin/console
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require_relative '../lib/btcruby.rb'
|
3
|
-
require_relative '../lib/btcruby/extensions.rb'
|
4
|
-
|
5
|
-
include BTC
|
6
|
-
|
7
|
-
require 'irb'
|
8
|
-
require 'irb/completion'
|
9
|
-
|
10
|
-
# IRB.conf[:PROMPT]||={}
|
11
|
-
# IRB.conf[:PROMPT][:BTC_PROMPT] = { # name of prompt mode
|
12
|
-
# :AUTO_INDENT => true, # enables auto-indent mode
|
13
|
-
# :PROMPT_I => %{>>}, # normal prompt
|
14
|
-
# :PROMPT_S => %{">}, # prompt for continuated strings
|
15
|
-
# :PROMPT_C => %{*>}, # prompt for continuated statement
|
16
|
-
# :RETURN => "=>%s\n" # format to return value
|
17
|
-
# }
|
18
|
-
# IRB.conf[:PROMPT_MODE] = :BTC_PROMPT
|
19
|
-
IRB.start
|
data/btcruby.gemspec
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
#encoding: UTF-8
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "btcruby/version"
|
4
|
-
|
5
|
-
files = `git ls-files`.split("\n")
|
6
|
-
|
7
|
-
Gem::Specification.new do |s|
|
8
|
-
s.name = "btcruby"
|
9
|
-
s.email = "oleganza+btcruby@gmail.com"
|
10
|
-
s.version = BTC::VERSION
|
11
|
-
s.description = "Ruby library for interacting with Bitcoin."
|
12
|
-
s.summary = "Ruby library for interacting with Bitcoin."
|
13
|
-
s.authors = ["Oleg Andreev", "Ryan Smith"]
|
14
|
-
s.homepage = "https://github.com/oleganza/btcruby"
|
15
|
-
s.rubyforge_project = "btcruby"
|
16
|
-
s.license = "MIT"
|
17
|
-
s.files = files
|
18
|
-
s.require_paths = ["lib"]
|
19
|
-
s.add_runtime_dependency 'ffi', '~> 1.9', '>= 1.9.3'
|
20
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# Creating a P2SH multisig address
|
2
|
-
# --------------------------------
|
3
|
-
#
|
4
|
-
# To create a P2SH multisig address you will need a set of public keys.
|
5
|
-
# In the example below we generate three random keys and compose 2-of-3 multisig script
|
6
|
-
# which is then transformed into a P2SH address. To redeem from this address you will need
|
7
|
-
# not only two signatures, but also the original multisig script.
|
8
|
-
|
9
|
-
require_relative "../lib/btcruby.rb"
|
10
|
-
|
11
|
-
keys = [BTC::Key.random, BTC::Key.random, BTC::Key.random]
|
12
|
-
pubkeys = keys.map(&:public_key)
|
13
|
-
|
14
|
-
multisig_script = BTC::Script.multisig_script(public_keys: pubkeys, signatures_required: 2)
|
15
|
-
puts multisig_script.to_s # => "OP_2 03e4e14a... 03b4b3f7... 030fa2ec... OP_3 OP_CHECKMULTISIG"
|
16
|
-
|
17
|
-
p2sh_script = multisig_script.p2sh_script
|
18
|
-
puts p2sh_script.to_s # => "OP_HASH160 26f5b7ad4e890c07b8c55fc551e39d6693c5e984 OP_EQUAL"
|
19
|
-
|
20
|
-
address = p2sh_script.standard_address
|
21
|
-
puts address.to_s # => 35F1xaoodzRZUBJHi6TgA85qPjXQcW8XsQ
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# Creating a transaction manually
|
2
|
-
# -------------------------------
|
3
|
-
#
|
4
|
-
# To manually create a transaction, you will need to specify raw inputs,
|
5
|
-
# compute the signature and compose a signature script for each input and
|
6
|
-
# take care of calculating a change amount correctly.
|
7
|
-
|
8
|
-
require_relative "../lib/btcruby.rb"
|
9
|
-
|
10
|
-
include BTC
|
11
|
-
|
12
|
-
tx = Transaction.new
|
13
|
-
|
14
|
-
# 1. Add a raw input with previous transaction ID and output index.
|
15
|
-
tx.add_input(TransactionInput.new(
|
16
|
-
previous_id: "aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31",
|
17
|
-
previous_index: 0))
|
18
|
-
|
19
|
-
# 2. Add a raw output with a script
|
20
|
-
tx.add_output(TransactionOutput.new(
|
21
|
-
value: 100_000,
|
22
|
-
script: PublicKeyAddress.parse("1CBtcGivXmHQ8ZqdPgeMfcpQNJrqTrSAcG").script))
|
23
|
-
|
24
|
-
# 3. Get the private key from WIF
|
25
|
-
key = Key.new(wif: "L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy")
|
26
|
-
|
27
|
-
# 4. Sign the input (assuming it links to an output with address 18oxCAnbuKHDjP7KzLBDj8mLjggDBjE1Q9)
|
28
|
-
hashtype = BTC::SIGHASH_ALL
|
29
|
-
sighash = tx.signature_hash(input_index: 0,
|
30
|
-
output_script: PublicKeyAddress.parse("18oxCAnbuKHDjP7KzLBDj8mLjggDBjE1Q9").script,
|
31
|
-
hash_type: hashtype)
|
32
|
-
tx.inputs[0].signature_script = Script.new << (key.ecdsa_signature(sighash) + WireFormat.encode_uint8(hashtype)) << key.public_key
|
33
|
-
|
34
|
-
# Get transaction data and broadcast it
|
35
|
-
puts "Binary transaction:"
|
36
|
-
puts tx.data # => raw binary data
|
37
|
-
puts "Hex transaction:"
|
38
|
-
puts tx.to_hex # hex-encoded data
|
39
|
-
# => 0100000001313eb630b128102b60241ca895f1d0ffca2170d5a0990e094f2182c102ab94aa
|
40
|
-
# 000000006a473044022039148258144202301221a305adb38ce0a182ecb4055c6015cdd735
|
41
|
-
# 8372d7ad6d022008aa259c87177f0e4e887dd0947c57fd140eb8f8a826f14ef8389dbc26ef
|
42
|
-
# a7b20121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59f
|
43
|
-
# ffffffff01a0860100000000001976a9147ab89f9fae3f8043dcee5f7b5467a0f0a6e2f7e1
|
44
|
-
# 88ac00000000
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# Generating an address
|
2
|
-
# ---------------------
|
3
|
-
#
|
4
|
-
# This example demonstrates how to generate a key and get its address.
|
5
|
-
|
6
|
-
require_relative "../lib/btcruby.rb"
|
7
|
-
|
8
|
-
key = BTC::Key.random
|
9
|
-
|
10
|
-
puts key.to_wif # private key in WIF format
|
11
|
-
# => L4RqZhbn2VsVgy2wCWW8kUPpA4xEkH7WbfPtj1MdFug5MayHzLeT
|
12
|
-
|
13
|
-
puts key.address.to_s # public address
|
14
|
-
# => 1MFqAcAxNsAKj5e6yksZCCyfNukSdDGsEY
|
15
|
-
|
16
|
-
puts key.to_wif(network: BTC::Network.testnet)
|
17
|
-
# => cUnq2cbdTZZkrQWCavKG7ntsnJFeQjDCfhYMqRp8m2L5cL1yHDmc
|
18
|
-
|
19
|
-
puts key.address(network: BTC::Network.testnet).to_s
|
20
|
-
# => n1mnTfFwBtbaWC7ihKqw28BzEuM9YqxRyw
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# Using transaction builder
|
2
|
-
# -------------------------
|
3
|
-
#
|
4
|
-
# Transaction builder helps composing arbitrary transactions using just keys or unspent outputs.
|
5
|
-
# It takes care of computing a proper change amount, adding fees and signing inputs.
|
6
|
-
# It is also highly customizable, so you may use it for very complex transactions.
|
7
|
-
|
8
|
-
require_relative "../lib/btcruby.rb"
|
9
|
-
|
10
|
-
builder = BTC::TransactionBuilder.new
|
11
|
-
|
12
|
-
# 1. Provide a list of address to get unspent outputs from.
|
13
|
-
# If address is a WIF instance, it will be used to sign corresponding input
|
14
|
-
# If address is a public address (or P2SH), its input will remain unsigned.
|
15
|
-
builder.input_addresses = [ BTC::Key.new(wif: "L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy").to_wif_object ]
|
16
|
-
|
17
|
-
# 2. Use external API (e.g. Chain.com) to fetch unspent outputs for the input addresses.
|
18
|
-
# In this example we simply hard-code a single unspent output.
|
19
|
-
# Note: transaction ID and output index must be provided.
|
20
|
-
builder.unspent_outputs_provider_block = lambda do |addresses, outputs_amount, outputs_size, fee|
|
21
|
-
txout = BTC::TransactionOutput.new(
|
22
|
-
value: 50_000,
|
23
|
-
script: BTC::PublicKeyAddress.parse("17XBj6iFEsf8kzDMGQk5ghZipxX49VXuaV").script,
|
24
|
-
transaction_id: "115e8f72f39fad874cfab0deed11a80f24f967a84079fb56ddf53ea02e308986",
|
25
|
-
index: 0
|
26
|
-
)
|
27
|
-
[ txout ]
|
28
|
-
end
|
29
|
-
|
30
|
-
# 3. Specify payment address and amount
|
31
|
-
builder.outputs = [ BTC::TransactionOutput.new(
|
32
|
-
value: 10_000,
|
33
|
-
script: BTC::PublicKeyAddress.parse("17XBj6iFEsf8kzDMGQk5ghZipxX49VXuaV").script) ]
|
34
|
-
|
35
|
-
# 4. Specify the change address
|
36
|
-
builder.change_address = BTC::PublicKeyAddress.parse("1CBtcGivXmHQ8ZqdPgeMfcpQNJrqTrSAcG")
|
37
|
-
|
38
|
-
# 5. Build the transaction and broadcast it.
|
39
|
-
result = builder.build
|
40
|
-
tx = result.transaction
|
41
|
-
puts tx.to_hex
|
42
|
-
|
43
|
-
# => 01000000018689302ea03ef5dd56fb7940a867f9240fa811eddeb0fa4c87ad9ff3728f5e11
|
44
|
-
# 000000006b483045022100e280f71106a84a4a1b1a2035eae70266eb53630beab2b59cc8cf
|
45
|
-
# f40b1a5bdbb902201dcbae9bb12730fe5563dc37e3a33e064f2efa78ba0af5c0179187aece
|
46
|
-
# 180b6c0121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b5
|
47
|
-
# 9fffffffff0210270000000000001976a91447862fe165e6121af80d5dde1ecb478ed17056
|
48
|
-
# 5b88ac30750000000000001976a9147ab89f9fae3f8043dcee5f7b5467a0f0a6e2f7e188ac
|
49
|
-
# 00000000
|