counterparty_ruby 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +7 -5
- data/README.md +5 -0
- data/counterparty_ruby.gemspec +1 -1
- data/lib/blockr_io.rb +10 -0
- data/lib/counterparty/tx_decode.rb +119 -0
- data/lib/counterparty/tx_encode.rb +135 -0
- data/lib/counterparty/version.rb +1 -1
- data/lib/counterparty_ruby.rb +3 -0
- data/spec/blockr_io_spec.rb +14 -0
- data/spec/tx_decode_spec.rb +262 -0
- data/spec/tx_encode_spec.rb +179 -0
- metadata +42 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1f5207b55688ced904bffa8b0c7e131bdbefeb63
|
4
|
+
data.tar.gz: da952475875e8dfebf067fed4881496ebd60e029
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b03863b18593a84e2c2d80c47d9adbf86c41f0cbac07ccb3fb3e826f2b68b8fe33cc44cdbec170fa477bb4494e4375e960670314fa553b03b33e2dd0a6c33aa3
|
7
|
+
data.tar.gz: 4063562be01b04a5353cadbb3bbafbfa80555b7ff284810404d221ae100cf08884f46915ee6eeb41fa8583c8a7d5536787087e9fc2eafd368020dfc1433073f6
|
data/Gemfile.lock
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
counterparty_ruby (1.
|
4
|
+
counterparty_ruby (1.2.0)
|
5
5
|
bitcoin-ruby
|
6
6
|
ffi
|
7
7
|
rest-client
|
8
|
+
ruby-rc4
|
8
9
|
|
9
10
|
GEM
|
10
11
|
remote: https://rubygems.org/
|
11
12
|
specs:
|
12
|
-
bitcoin-ruby (0.0.
|
13
|
+
bitcoin-ruby (0.0.7)
|
13
14
|
diff-lcs (1.2.5)
|
14
|
-
domain_name (0.5.
|
15
|
+
domain_name (0.5.24)
|
15
16
|
unf (>= 0.0.5, < 1.0.0)
|
16
17
|
ffi (1.9.8)
|
17
18
|
http-cookie (1.0.2)
|
18
19
|
domain_name (~> 0.5)
|
19
20
|
json (1.8.1)
|
20
|
-
mime-types (2.
|
21
|
+
mime-types (2.6.1)
|
21
22
|
netrc (0.10.3)
|
22
23
|
rake (10.3.2)
|
23
24
|
rdoc (4.2.0)
|
@@ -41,9 +42,10 @@ GEM
|
|
41
42
|
rspec-mocks (3.1.3)
|
42
43
|
rspec-support (~> 3.1.0)
|
43
44
|
rspec-support (3.1.2)
|
45
|
+
ruby-rc4 (0.1.5)
|
44
46
|
unf (0.1.4)
|
45
47
|
unf_ext
|
46
|
-
unf_ext (0.0.
|
48
|
+
unf_ext (0.0.7.1)
|
47
49
|
|
48
50
|
PLATFORMS
|
49
51
|
ruby
|
data/README.md
CHANGED
@@ -26,6 +26,11 @@ setting everything up.
|
|
26
26
|
![Party On Wayne](http://data.whicdn.com/images/24796384/tumblr_m0ng6rBeWT1qhd0xso1_500_large.jpg)
|
27
27
|
|
28
28
|
## Changelog
|
29
|
+
_Version 1.2_
|
30
|
+
* Minor refactoring
|
31
|
+
* Added an extensive suite of tests for transaction encoding and decoding
|
32
|
+
* Implemented a counterparty transaction TxEncode/TxDecode class to decode counterparty transactions without a need for counterpartyd
|
33
|
+
|
29
34
|
_Version 1.1_
|
30
35
|
* Minor Updates to support changes in counterpartyd 1.1
|
31
36
|
* Removed support for relaying transactions through counterparty
|
data/counterparty_ruby.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.required_ruby_version = '>= 1.9'
|
17
17
|
gem.license = 'LGPL'
|
18
18
|
|
19
|
-
['rest-client', 'bitcoin-ruby', 'ffi'].each do |dependency|
|
19
|
+
['rest-client', 'bitcoin-ruby', 'ffi', 'ruby-rc4'].each do |dependency|
|
20
20
|
gem.add_runtime_dependency dependency
|
21
21
|
end
|
22
22
|
['rspec', 'rspec-its', 'rake', 'rdoc'].each do |dependency|
|
data/lib/blockr_io.rb
CHANGED
@@ -24,6 +24,16 @@ class BlockrIo
|
|
24
24
|
@is_testing
|
25
25
|
end
|
26
26
|
|
27
|
+
def listunspent(addr, include_unconfirmed = false)
|
28
|
+
query = [addr,(include_unconfirmed) ? '?unconfirmed=1' : nil ].join
|
29
|
+
json_get('address', 'unspent', query)['data']['unspent']
|
30
|
+
end
|
31
|
+
|
32
|
+
# Shows all the transactions that are unconfirmed for the provided address:
|
33
|
+
def listunconfirmed(addr)
|
34
|
+
json_get('address','unconfirmed',addr)['data']['unconfirmed']
|
35
|
+
end
|
36
|
+
|
27
37
|
private
|
28
38
|
|
29
39
|
def request(*path, &block)
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Inspriration heavily lifted from:
|
4
|
+
# - https://github.com/tokenly/counterparty-transaction-parser
|
5
|
+
module Counterparty
|
6
|
+
class TxDecode
|
7
|
+
class UndefinedBehavior < StandardError; end # If you find one of these, lmk!
|
8
|
+
class InvalidOpReturn < StandardError; end
|
9
|
+
class InvalidOutput < StandardError; end
|
10
|
+
class MultisigUnsupported < StandardError; end
|
11
|
+
|
12
|
+
DEFAULT_PREFIX = 'CNTRPRTY'
|
13
|
+
|
14
|
+
OP_RETURN_PARTS = /^OP_RETURN ([a-z0-9]+)$/
|
15
|
+
P2PKH_PARTS = /^OP_DUP OP_HASH160 ([a-z0-9]+) OP_EQUALVERIFY OP_CHECKSIG$/
|
16
|
+
OP_MULTISIG_PARTS = /^[12] ([a-z0-9 ]+) ([23]) OP_CHECKMULTISIG$/
|
17
|
+
|
18
|
+
attr_accessor :sender_addr, :receiver_addr, :decrypt_key, :data, :prefix
|
19
|
+
|
20
|
+
def initialize(tx, options = {})
|
21
|
+
@prefix = options[:prefix] || DEFAULT_PREFIX
|
22
|
+
@decrypt_key = options[:decrypt_key] || [tx.inputs[0].prev_out.reverse_hth].pack('H*')
|
23
|
+
|
24
|
+
parse! (tx.respond_to? :outputs) ?
|
25
|
+
tx.outputs.collect{|out| out.parsed_script.to_string } : tx
|
26
|
+
end
|
27
|
+
|
28
|
+
def decrypt(chunk)
|
29
|
+
RC4.new(decrypt_key).decrypt chunk
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def prefixed?(data, offset = 1)
|
35
|
+
data[offset...(prefix.length+offset)] == prefix
|
36
|
+
end
|
37
|
+
|
38
|
+
# This determines if the supplied operation is a non-data
|
39
|
+
def is_non_prefixed_p2pkh?(op)
|
40
|
+
P2PKH_PARTS.match(op) && !prefixed?(decrypt([$1].pack('H*')))
|
41
|
+
end
|
42
|
+
|
43
|
+
def hash160_from_p2pkh(op)
|
44
|
+
Bitcoin.hash160_to_address $1 if P2PKH_PARTS.match op
|
45
|
+
end
|
46
|
+
|
47
|
+
# Note that this isn't exactly the way counterparty parses the transactions.
|
48
|
+
# But , it reads cleaner, and worked on every transaction I could find.
|
49
|
+
# Mostly the difference is that the counterparty version is a loop that
|
50
|
+
# collects P2PKH's anywhere in the outputs, whereas this block takes a sender
|
51
|
+
# or receiver address from the top and bottom only
|
52
|
+
def parse!(outputs)
|
53
|
+
return if @data
|
54
|
+
|
55
|
+
# So typically, the first output is a P2PKH with the receiver address:
|
56
|
+
@receiver_addr = hash160_from_p2pkh outputs.shift if is_non_prefixed_p2pkh? outputs.first
|
57
|
+
|
58
|
+
# Parse the sender address:
|
59
|
+
@sender_addr = hash160_from_p2pkh outputs.pop if is_non_prefixed_p2pkh? outputs.last
|
60
|
+
|
61
|
+
@data = outputs.collect{|out|
|
62
|
+
# This weirdo line will send the regex matches to the operation handler
|
63
|
+
# that matches the line
|
64
|
+
send (case out
|
65
|
+
when OP_RETURN_PARTS then :data_from_opreturn
|
66
|
+
when P2PKH_PARTS then :data_from_opchecksig
|
67
|
+
when OP_MULTISIG_PARTS then :data_from_opcheckmultisig
|
68
|
+
else raise InvalidOutput
|
69
|
+
end), *$~.to_a[1..-1]
|
70
|
+
}.compact.join
|
71
|
+
end
|
72
|
+
|
73
|
+
def data_from_opreturn(data)
|
74
|
+
chunk = [data].pack('H*')
|
75
|
+
|
76
|
+
raise InvalidOpReturn if chunk.nil?
|
77
|
+
|
78
|
+
data = decrypt chunk
|
79
|
+
|
80
|
+
raise InvalidOpReturn unless prefixed?(data,0)
|
81
|
+
|
82
|
+
data[prefix.length..-1]
|
83
|
+
end
|
84
|
+
|
85
|
+
def data_from_opchecksig(pubkeyhash_text)
|
86
|
+
chunk = decrypt [pubkeyhash_text].pack('H*')
|
87
|
+
|
88
|
+
# This should get picked up by the sender and receiver pop/shift in parse!
|
89
|
+
# However, the counterparty lib would parse these obtuse addresses typically
|
90
|
+
# ATM - I can't find one in the wild
|
91
|
+
raise UndefinedBehavior unless prefixed? chunk
|
92
|
+
|
93
|
+
chunk_length = chunk[0].ord
|
94
|
+
chunk[(1+prefix.length)...chunk_length+1]
|
95
|
+
end
|
96
|
+
|
97
|
+
def data_from_opcheckmultisig(pubkeys_op, n_signatures_op)
|
98
|
+
pubkeys, n_signatures = pubkeys_op.split(' '), n_signatures_op.to_i
|
99
|
+
|
100
|
+
# There's no data in the last pubkey:
|
101
|
+
chunk = pubkeys[0...-1].collect{ |pubkey|
|
102
|
+
[pubkey].pack('H*')[1...-1] # Skip sign byte and nonce byte.
|
103
|
+
}.reduce(:+)
|
104
|
+
|
105
|
+
data = decrypt chunk
|
106
|
+
|
107
|
+
# Multisig transactions will break here. I haven't actually collected enough
|
108
|
+
# of these samples yet to really test, but it seems they are typically are
|
109
|
+
# at the top of the output stack:
|
110
|
+
raise MultisigUnsupported unless prefixed? data
|
111
|
+
|
112
|
+
# Padding byte in each output (instead of just in the last one) so that
|
113
|
+
# encoding methods may be mixed. Also, it’s just not very much data.
|
114
|
+
chunk_length = data[0].ord
|
115
|
+
|
116
|
+
data[1..chunk_length][prefix.length..-1]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
# Inspriration heavily lifted from:
|
4
|
+
# - https://github.com/CounterpartyXCP/counterparty-lib/blob/master/counterpartylib/lib/transaction.py
|
5
|
+
module Counterparty
|
6
|
+
class TxEncode
|
7
|
+
class MissingPubkey < StandardError; end
|
8
|
+
class MissingSenderAddr < StandardError; end
|
9
|
+
class InvalidPubkey < StandardError; end
|
10
|
+
class InvalidPubkeyGenerated < StandardError; end
|
11
|
+
class DataTooLarge < StandardError; end
|
12
|
+
|
13
|
+
PREFIX = 'CNTRPRTY'
|
14
|
+
|
15
|
+
P2PKH = 'OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG'
|
16
|
+
MULTISIG = '1 %s %s OP_CHECKMULTISIG'
|
17
|
+
OPRETURN = 'OP_RETURN %s'
|
18
|
+
|
19
|
+
# 33 is the size of a pubkey, there are two pubkeys in a multisig, 1 byte
|
20
|
+
# is lost for the data length byte, and two bytes are lost on each key for
|
21
|
+
# the data_to_pubkey inefficiency
|
22
|
+
BYTES_IN_MULTISIG = (33 * 2) - 1 - 2 - 2
|
23
|
+
BYTES_IN_PUBKEYHASH = 20 - 1
|
24
|
+
BYTES_IN_OPRETURN = 40
|
25
|
+
|
26
|
+
attr_accessor :sender_addr, :sender_pubkey, :receiver_addr, :encrypt_key,
|
27
|
+
:source_data, :prefix
|
28
|
+
|
29
|
+
def initialize(encrypt_key, source_data, options = {})
|
30
|
+
@source_data, @encrypt_key = source_data, encrypt_key
|
31
|
+
|
32
|
+
if options[:sender_pubkey]
|
33
|
+
@sender_pubkey = options[:sender_pubkey]
|
34
|
+
@sender_addr = Bitcoin.pubkey_to_address(sender_pubkey)
|
35
|
+
elsif options.has_key? :sender_addr
|
36
|
+
@sender_addr = options[:sender_addr]
|
37
|
+
else
|
38
|
+
raise MissingSenderAddr
|
39
|
+
end
|
40
|
+
|
41
|
+
@receiver_addr = options[:receiver_addr] if options.has_key? :receiver_addr
|
42
|
+
|
43
|
+
@prefix = options[:prefix] || PREFIX
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_opmultisig
|
47
|
+
raise MissingPubkey unless sender_pubkey
|
48
|
+
|
49
|
+
data_length = BYTES_IN_MULTISIG-prefix.length
|
50
|
+
p2pkh_wrap collect_chunks(source_data,data_length){|chunk|
|
51
|
+
padding = 0.chr * (data_length-chunk.length)
|
52
|
+
|
53
|
+
data = encrypt [(chunk.length+prefix.length).chr,prefix, chunk, padding].join
|
54
|
+
|
55
|
+
data_keys = [(0...31), (31...62)].collect{|r| data_to_pubkey data[r] }
|
56
|
+
|
57
|
+
MULTISIG % [(data_keys + [sender_pubkey]).join(' '), 3]
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_pubkeyhash
|
62
|
+
p2pkh_wrap collect_chunks(source_data, BYTES_IN_PUBKEYHASH-prefix.length){ |chunk|
|
63
|
+
data_length = prefix.length + chunk.length
|
64
|
+
|
65
|
+
padding = 0.chr * (BYTES_IN_PUBKEYHASH - data_length)
|
66
|
+
|
67
|
+
enc_chunk = encrypt [(data_length).chr, prefix, chunk, padding].join
|
68
|
+
|
69
|
+
P2PKH % enc_chunk.unpack('H*').first
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_opreturn
|
74
|
+
# I'm fairly certain that using more than one OP_RETURN per transaction is
|
75
|
+
# unstandard behavior right now
|
76
|
+
raise DataTooLarge if (source_data.length + prefix.length) > BYTES_IN_OPRETURN
|
77
|
+
|
78
|
+
data = encrypt [prefix,source_data].join
|
79
|
+
|
80
|
+
p2pkh_wrap( OPRETURN % data.unpack('H*').first )
|
81
|
+
end
|
82
|
+
|
83
|
+
def encrypt(chunk)
|
84
|
+
RC4.new(encrypt_key).encrypt chunk
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def p2pkh_wrap(operation)
|
90
|
+
[ (receiver_addr) ? P2PKH % Bitcoin.hash160_from_address(receiver_addr) : nil,
|
91
|
+
operation,
|
92
|
+
P2PKH % Bitcoin.hash160_from_address(sender_addr) ].flatten.compact
|
93
|
+
end
|
94
|
+
|
95
|
+
# Take a too short data pubkey and make it look like a real pubkey.
|
96
|
+
# Take an obfuscated chunk of data that is two bytes too short to be a pubkey and
|
97
|
+
# add a sign byte to its beginning and a nonce byte to its end. Choose these
|
98
|
+
# bytes so that the resulting sequence of bytes is a fully valid pubkey (i.e. on
|
99
|
+
# the ECDSA curve). Find the correct bytes by guessing randomly until the check
|
100
|
+
# passes. (In parsing, these two bytes are ignored.)
|
101
|
+
#
|
102
|
+
# NOTE: This function is named "make_fully_valid" in the official code.
|
103
|
+
def data_to_pubkey(bytes)
|
104
|
+
raise InvalidPubkey unless bytes.length == 31
|
105
|
+
|
106
|
+
random_bytes = Digest::SHA256.digest bytes
|
107
|
+
|
108
|
+
# Deterministically generated, for unit tests.
|
109
|
+
sign = (random_bytes[0].ord & 1) + 2
|
110
|
+
nonce = initial_nonce = random_bytes[1].ord
|
111
|
+
|
112
|
+
begin
|
113
|
+
nonce += 1
|
114
|
+
next if nonce == initial_nonce
|
115
|
+
|
116
|
+
ret = (sign.chr + bytes + (nonce % 256).chr).unpack('H*').first
|
117
|
+
|
118
|
+
# Note that 256 is the exclusive limit:
|
119
|
+
end until Bitcoin.valid_pubkey? ret
|
120
|
+
|
121
|
+
# I don't actually think this is ever possible. Note that we return 66 bytes
|
122
|
+
# as this is string of hex, and not the bytes themselves:
|
123
|
+
raise InvalidPubkeyGenerated unless ret.length == 66
|
124
|
+
|
125
|
+
ret
|
126
|
+
end
|
127
|
+
|
128
|
+
# This is a little helper method that lets us split our binary data into
|
129
|
+
# chunks for further processing
|
130
|
+
def collect_chunks(data,chunk_length, &block)
|
131
|
+
(source_data.length.to_f / chunk_length).ceil.times.collect{|i|
|
132
|
+
block.call source_data.slice(i*chunk_length, chunk_length) }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/counterparty/version.rb
CHANGED
data/lib/counterparty_ruby.rb
CHANGED
@@ -2,9 +2,12 @@ require 'json'
|
|
2
2
|
require 'rest_client'
|
3
3
|
require 'open-uri'
|
4
4
|
require 'bitcoin'
|
5
|
+
require 'rc4'
|
5
6
|
|
6
7
|
require 'blockr_io'
|
7
8
|
require 'counterparty/raw_tx'
|
9
|
+
require 'counterparty/tx_decode'
|
10
|
+
require 'counterparty/tx_encode'
|
8
11
|
require 'counterparty/version'
|
9
12
|
require 'counterparty/resource'
|
10
13
|
require 'counterparty/resources'
|
data/spec/blockr_io_spec.rb
CHANGED
@@ -61,8 +61,22 @@ describe BlockrIo do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
describe "#listunspent" do
|
65
|
+
it "should list unspent transactions" do
|
66
|
+
unspents = blockr_main.listunspent('1CounterpartyXXXXXXXXXXXXXXXUWLpVr')
|
67
|
+
|
68
|
+
expect(unspents.length).to eq(2620)
|
69
|
+
expect(unspents.first.tap{|u| u.delete('confirmations') }).to eq( {
|
70
|
+
"tx"=>"bcd6fd6997d26ae12caef102f5e9631ee2ed1e38eaa16547a51d908f4c5ddac8",
|
71
|
+
"amount"=>"0.00005430", "n"=>0,
|
72
|
+
"script"=>"76a914818895f3dc2c178629d3d2d8fa3ec4a3f817982188ac"} )
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
64
77
|
describe "#sendrawtransaction" do
|
65
78
|
# I think the way to test this is simply to do so in the resource_create
|
66
79
|
end
|
80
|
+
|
67
81
|
end
|
68
82
|
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require_relative 'spec_helper'
|
3
|
+
|
4
|
+
# deweller provided some nice unit tests for enconding/decoding transactions.
|
5
|
+
# These examples were lifted from there.
|
6
|
+
# raw_tx = BlockrIo.new.getrawtransaction ''
|
7
|
+
describe Counterparty::TxDecode do
|
8
|
+
# This converts the tokenly-unit test hash into what bitcoin-ruby expects:
|
9
|
+
def tokenly_json_to_hash(json)
|
10
|
+
hash = JSON.parse json
|
11
|
+
|
12
|
+
{ 'ver' => hash['version'], 'lock_time' => hash['locktime'],
|
13
|
+
'in' => hash['vin'].collect{ |ain|
|
14
|
+
{ 'prev_out' => {'hash' => ain['txid'], 'n' => ain['n']},
|
15
|
+
'scriptSig' => ain['scriptSig']['asm'], 'sequence' => ain['sequence']
|
16
|
+
}
|
17
|
+
},
|
18
|
+
'out' => hash['vout'].collect{ |aout|
|
19
|
+
{'value' => aout['value'], 'n' => aout['n'],
|
20
|
+
'scriptPubKey' => aout['scriptPubKey']['asm'] } } }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".parse" do
|
24
|
+
it "Tokenly's getSampleCounterpartyTransactionProtocol2()" do
|
25
|
+
json = '{"txid":"e0082d1fc37172ccf0f5ebfc3cc54291e463384712f44f32ba4996c02045966f","version":1,"locktime":0,"vin":[{"txid":"8fd9f689f158a426867215dbdee58e9eab6c818097d4bf2bcf0bd1458f3c55ab","vout":2,"scriptSig":{"asm":"3045022100a178c9accd7972cfe30a03c98ff5f684bdf0b144eb415f4a4b7fcff596283f720220267f68a6413093b97a42ed5c2f2811193c1bbdd07d668e3076f99751044c347a01 02f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e6","hex":"483045022100a178c9accd7972cfe30a03c98ff5f684bdf0b144eb415f4a4b7fcff596283f720220267f68a6413093b97a42ed5c2f2811193c1bbdd07d668e3076f99751044c347a012102f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e6"},"sequence":4294967295,"n":0,"addr":"1AuTJDwH6xNqxRLEjPB7m86dgmerYVQ5G1","valueSat":95270,"value":0.0009527,"doubleSpentTxID":null}],"vout":[{"value":"0.00005430","n":0,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 1407ec32be440f32fc70f4eea810acd98f32aa32 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a9141407ec32be440f32fc70f4eea810acd98f32aa3288ac","reqSigs":1,"type":"pubkeyhash","addresses":["12pv1K6LTLPFYXcCwsaU7VWYRSX7BuiF28"]}},{"value":"0.00002500","n":1,"scriptPubKey":{"asm":"1 0276d539826e5ec10fed9ef597d5bfdac067d287fb7f06799c449971b9ddf9fec6 02af7efeb1f7cf0d5077ae7f7a59e2b643c5cd01fb55221bf76221d8c8ead92bf0 02f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e6 3 OP_CHECKMULTISIG","hex":"51210276d539826e5ec10fed9ef597d5bfdac067d287fb7f06799c449971b9ddf9fec62102af7efeb1f7cf0d5077ae7f7a59e2b643c5cd01fb55221bf76221d8c8ead92bf02102f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e653ae","reqSigs":1,"type":"multisig","addresses":["17MPn1QXt1SLqKWy3NPmJQ7iT5dJKRhCU7","12oEzNKh5TQpKDP1vfeTGnSjoxkboo1m5u","1AuTJDwH6xNqxRLEjPB7m86dgmerYVQ5G1"]}},{"value":"0.00086340","n":2,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 6ca4b6b20eac497e9ca94489c545a3372bdd2fa7 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a9146ca4b6b20eac497e9ca94489c545a3372bdd2fa788ac","reqSigs":1,"type":"pubkeyhash","addresses":["1AuTJDwH6xNqxRLEjPB7m86dgmerYVQ5G1"]}}],"valueOut":0.0009427,"size":340,"valueIn":0.0009527,"fees":0.00001}'
|
26
|
+
|
27
|
+
tx = Bitcoin::P::Tx.from_hash( tokenly_json_to_hash(json) )
|
28
|
+
record = Counterparty::TxDecode.new tx
|
29
|
+
|
30
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x17Hv\xE8\x00".force_encoding('ASCII-8BIT'))
|
31
|
+
expect(record.receiver_addr).to eq('12pv1K6LTLPFYXcCwsaU7VWYRSX7BuiF28')
|
32
|
+
expect(record.sender_addr).to eq('1AuTJDwH6xNqxRLEjPB7m86dgmerYVQ5G1')
|
33
|
+
end
|
34
|
+
|
35
|
+
it "Tokenly's getSampleCounterpartyTransaction3()" do
|
36
|
+
json = '{"txid":"24c9f9dd130591959b8f2e2e6d0133de028138bf73dfe14cc3de0fbb151812bd","version":1,"locktime":0,"vin":[{"txid":"e7f9319de85661c33130e80b7df16733164892eeb2e1fb044e5ac5de7a3269b7","vout":0,"scriptSig":{"asm":"304402205267657bb7ea5542b8fd32502e78dc3903e5781de8b8a5a119abbd382691a98e02204c47b7aa5940c030def956a4e91be16a692c09c7194a6fdec3054457c99e70c701 0257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690","hex":"47304402205267657bb7ea5542b8fd32502e78dc3903e5781de8b8a5a119abbd382691a98e02204c47b7aa5940c030def956a4e91be16a692c09c7194a6fdec3054457c99e70c701210257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690"},"sequence":4294967295,"n":0,"addr":"1291Z6hofAAvH8E886cN9M5uKB1VvwBnup","valueSat":5430,"value":0.0000543,"doubleSpentTxID":null},{"txid":"d800ef4c33542c90bcfe4cd0c2fc2c0d120877ec933ca869177a77eb8b42077e","vout":1,"scriptSig":{"asm":"3045022100e43310957b541c51e00c3076393bf93c23dd72306a012f0ebe1024218269045d022029b5218047adf59186d53dbff7a249f82003e923a782cdfd75f8871b89c819b801 0257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690","hex":"483045022100e43310957b541c51e00c3076393bf93c23dd72306a012f0ebe1024218269045d022029b5218047adf59186d53dbff7a249f82003e923a782cdfd75f8871b89c819b801210257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690"},"sequence":4294967295,"n":1,"addr":"1291Z6hofAAvH8E886cN9M5uKB1VvwBnup","valueSat":801320,"value":0.0080132,"doubleSpentTxID":null}],"vout":[{"value":"0.00005430","n":0,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 9c2401388e6d2752a496261e9130cd54ddb2b262 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a9149c2401388e6d2752a496261e9130cd54ddb2b26288ac","reqSigs":1,"type":"pubkeyhash","addresses":["1FEbYaghvr7V53B9csjQTefUtBBQTaDFvN"]}},{"value":"0.00002500","n":1,"scriptPubKey":{"asm":"1 035240874259b8f93dffc6ffa29b09d0d06dfb072d9646ae777480a2c521bfdbb1 0264f1dd503423e8305e19fc77b4e26dc8ec8a8f500b1bec580112af8c64e74b1b 0257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690 3 OP_CHECKMULTISIG","hex":"5121035240874259b8f93dffc6ffa29b09d0d06dfb072d9646ae777480a2c521bfdbb1210264f1dd503423e8305e19fc77b4e26dc8ec8a8f500b1bec580112af8c64e74b1b210257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c69053ae","reqSigs":1,"type":"multisig","addresses":["1J7TTrHcWQgs37Es8PFKcaoJmUvGRGsEzY","126HYzAnxybKoHpkmrMBSSu3KnqzUgEHGc","1291Z6hofAAvH8E886cN9M5uKB1VvwBnup"]}},{"value":"0.00793820","n":2,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 0c7bea5ae61ccbc157156ffc9466a54b07bfe951 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a9140c7bea5ae61ccbc157156ffc9466a54b07bfe95188ac","reqSigs":1,"type":"pubkeyhash","addresses":["1291Z6hofAAvH8E886cN9M5uKB1VvwBnup"]}}],"valueOut":0.0080175,"size":487,"valueIn":0.0080675,"fees":0.00005}'
|
37
|
+
|
38
|
+
tx = Bitcoin::P::Tx.from_hash( tokenly_json_to_hash(json) )
|
39
|
+
record = Counterparty::TxDecode.new tx
|
40
|
+
|
41
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x00\v\xEB\xC2\x00".force_encoding('ASCII-8BIT'))
|
42
|
+
expect(record.receiver_addr).to eq('1FEbYaghvr7V53B9csjQTefUtBBQTaDFvN')
|
43
|
+
expect(record.sender_addr).to eq('1291Z6hofAAvH8E886cN9M5uKB1VvwBnup')
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
it "Tokenly's getSampleCounterpartyTransaction4()" do
|
48
|
+
json = '{"txid":"2d1fea72ea4be25793d8a2e254c6dc4aacfac8978ce0cc4729fe1418649c8f1e","version":1,"locktime":0,"vin":[{"txid":"a6edb86171fc7736389f20bc63542255dbbfa2dcd173fc079414adab7f548071","vout":0,"scriptSig":{"asm":"3044022038397429f0a49e80690eb143e63d83c097288b2c1ea90167688997e8a75a3c8402204e48260b4440001d402b40a33183dc5d54d5ced64670b0e5b72373392c8481d501 034bf23d14fa8aa9e8ebfee6e0bf986fa36ad61434068b89b7a8801506ed5060bb","hex":"473044022038397429f0a49e80690eb143e63d83c097288b2c1ea90167688997e8a75a3c8402204e48260b4440001d402b40a33183dc5d54d5ced64670b0e5b72373392c8481d50121034bf23d14fa8aa9e8ebfee6e0bf986fa36ad61434068b89b7a8801506ed5060bb"},"sequence":4294967295,"n":0,"addr":"1MFHQCPGtcSfNPXAS6NryWja3TbUN9239Y","valueSat":5430,"value":0.0000543,"doubleSpentTxID":null},{"txid":"31aa31fb22cd24d54b68ef7390ed39db09f2e4cbae1c227b2f78087f3edf4077","vout":1,"scriptSig":{"asm":"30440220189f79d7c86884d69f35cb7d8b96916bc3001c522a2025471675a6835fc45b7d02203345a31b0abb79035722a9ed5381fd34380f4e9cc418a5ea522034e50ea1f2e901 034bf23d14fa8aa9e8ebfee6e0bf986fa36ad61434068b89b7a8801506ed5060bb","hex":"4730440220189f79d7c86884d69f35cb7d8b96916bc3001c522a2025471675a6835fc45b7d02203345a31b0abb79035722a9ed5381fd34380f4e9cc418a5ea522034e50ea1f2e90121034bf23d14fa8aa9e8ebfee6e0bf986fa36ad61434068b89b7a8801506ed5060bb"},"sequence":4294967295,"n":1,"addr":"1MFHQCPGtcSfNPXAS6NryWja3TbUN9239Y","valueSat":1717640,"value":0.0171764,"doubleSpentTxID":null}],"vout":[{"value":"0.00005430","n":0,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 fd84ff1f2cc1b0299165e2804fccd6fb0bd48d0b OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914fd84ff1f2cc1b0299165e2804fccd6fb0bd48d0b88ac","reqSigs":1,"type":"pubkeyhash","addresses":["1Q7VHJDEzVj7YZBVseQWgYvVj3DWDCLwDE"]}},{"value":"0.00000000","n":1,"scriptPubKey":{"asm":"OP_RETURN 2c54fff6d3e165e008f5ec45a06951e6b6fb4a162fcfec34aa1f0dd8","hex":"6a1c2c54fff6d3e165e008f5ec45a06951e6b6fb4a162fcfec34aa1f0dd8","type":"nulldata"}},{"value":"0.01712640","n":2,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 de1607744008a3edeabae06365a9aa2b131d5dc2 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914de1607744008a3edeabae06365a9aa2b131d5dc288ac","reqSigs":1,"type":"pubkeyhash","addresses":["1MFHQCPGtcSfNPXAS6NryWja3TbUN9239Y"]}}],"blockhash":"00000000000000000d7fbe3a59b9d37380fb46a79289e2011396721c433a7883","confirmations":1,"time":1428589045,"blocktime":1428589045,"valueOut":0.0171807,"size":411,"valueIn":0.0172307,"fees":0.00005}'
|
49
|
+
|
50
|
+
tx = Bitcoin::P::Tx.from_hash( tokenly_json_to_hash(json) )
|
51
|
+
record = Counterparty::TxDecode.new tx
|
52
|
+
|
53
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x00\x05\xF5\xE1\x00".force_encoding('ASCII-8BIT'))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "Tokenly's getSampleCounterpartyTransaction5()" do
|
57
|
+
json = '{"txid":"48e07bdad04f869850ccdb11b5e6a9e89ee8023111eb4f2e293d3e8ef75befee","version":1,"locktime":0,"vin":[{"txid":"cf8fa29cf63938a787e732c85071695668b9e00bfedff807dfbdc85a6ad6a696","vout":0,"scriptSig":{"asm":"304502210089af043911012c558bd11392d4346da725cd35822c1c6c0140293fed3344176d02207e6ad3945cb6580e654ac579a3ffdc01b93e54c4babc55bde6aa2b97ddf3f0af01 02b0610c458d67d76e348c6bb2f29f66d272e2c66bd23747ac401fefa45d2fc7a0","hex":"48304502210089af043911012c558bd11392d4346da725cd35822c1c6c0140293fed3344176d02207e6ad3945cb6580e654ac579a3ffdc01b93e54c4babc55bde6aa2b97ddf3f0af012102b0610c458d67d76e348c6bb2f29f66d272e2c66bd23747ac401fefa45d2fc7a0"},"sequence":4294967295,"n":0,"addr":"12iVwKP7jCPnuYy7jbAbyXnZ3FxvgLwvGK","valueSat":5430,"value":0.0000543,"doubleSpentTxID":null},{"txid":"d6e1e95bae2a4715dce049f464525af1f118876b7e79c311e1fa4c2bf77f4df4","vout":2,"scriptSig":{"asm":"30440220459ef45b40a80a9dc1cb2c33d1f5ddd8d464c4a607dbe2df83049d69b35c7b960220134b69e807eb2bebc3339bfb60a7de5b86c801f64d176fc704a3ce9132e8509301 02b0610c458d67d76e348c6bb2f29f66d272e2c66bd23747ac401fefa45d2fc7a0","hex":"4730440220459ef45b40a80a9dc1cb2c33d1f5ddd8d464c4a607dbe2df83049d69b35c7b960220134b69e807eb2bebc3339bfb60a7de5b86c801f64d176fc704a3ce9132e85093012102b0610c458d67d76e348c6bb2f29f66d272e2c66bd23747ac401fefa45d2fc7a0"},"sequence":4294967295,"n":1,"addr":"12iVwKP7jCPnuYy7jbAbyXnZ3FxvgLwvGK","valueSat":1760000,"value":0.0176,"doubleSpentTxID":null}],"vout":[{"value":"0.00005430","n":0,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 cab7d87116e620e10a69e666ec6494d4607631e7 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a914cab7d87116e620e10a69e666ec6494d4607631e788ac","reqSigs":1,"type":"pubkeyhash","addresses":["1KUsjZKrkd7LYRV7pbnNJtofsq1HAiz6MF"]}},{"value":"0.00000000","n":1,"scriptPubKey":{"asm":"OP_RETURN fb706d6b2839cfd52a4b50cb135f18cf9e0b280ca45b2da5694229f0","hex":"6a1cfb706d6b2839cfd52a4b50cb135f18cf9e0b280ca45b2da5694229f0","type":"nulldata"}},{"value":"0.01755000","n":2,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 12d155cefea286e9d3cda6cb64cd8d26a5b95780 OP_EQUALVERIFY OP_CHECKSIG","hex":"76a91412d155cefea286e9d3cda6cb64cd8d26a5b9578088ac","reqSigs":1,"type":"pubkeyhash","addresses":["12iVwKP7jCPnuYy7jbAbyXnZ3FxvgLwvGK"]}}],"valueOut":0.0176043,"size":412,"valueIn":0.0176543,"fees":0.00005}'
|
58
|
+
|
59
|
+
tx = Bitcoin::P::Tx.from_hash( tokenly_json_to_hash(json) )
|
60
|
+
record = Counterparty::TxDecode.new tx
|
61
|
+
|
62
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x01*\x05\xF2\x00".force_encoding('ASCII-8BIT'))
|
63
|
+
expect(record.receiver_addr).to eq('1KUsjZKrkd7LYRV7pbnNJtofsq1HAiz6MF')
|
64
|
+
expect(record.sender_addr).to eq('12iVwKP7jCPnuYy7jbAbyXnZ3FxvgLwvGK')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "decodes a random counterparty transaction" do
|
68
|
+
# This was from a random Counterparty Broadcast. Txid:
|
69
|
+
# eae1fd843f267d756c765b3e84ff33cd3f7dcde4df671c53b2e3465ba9f1b94e
|
70
|
+
|
71
|
+
raw_tx = '0100000001c77af36618fa11f91152608a6ed50'+
|
72
|
+
'eab0fed0c9ace1a1f60444e8abb15d5cdd6010000006b4830450220243fa1706a7'+
|
73
|
+
'708ffa5313a04935fd543f5fd04d43f3f8d6c46e94502dfabcb08022100a682848'+
|
74
|
+
'c79356ab47e17b3f10ed91e45c72ad0fc866c2e4a4bb25826ef9ac00f01210216b'+
|
75
|
+
'6c3047c80b4e2fcbed0df1b265d73dbef174291fcb4cdc427cef12ea3cf3cfffff'+
|
76
|
+
'fff03781e00000000000069512103d468e197eaad3c41aac3aca739bb6a6a9a96f'+
|
77
|
+
'7c8446ae8055d3889b7a3d5219f21021875e020f9fac3f2654d173b110b0354db4'+
|
78
|
+
'ff931b5aa069bb090a15521164a73210216b6c3047c80b4e2fcbed0df1b265d73d'+
|
79
|
+
'bef174291fcb4cdc427cef12ea3cf3c53ae781e00000000000069512103f968e19'+
|
80
|
+
'7eaad3c41aaa0cfc5559c59a8412907c8446ae8055d3889b7a3fd63092102543aa'+
|
81
|
+
'36baab982bc451b5269584d5a799a0bbd63f0f955bb84fdcc244020238a210216b'+
|
82
|
+
'6c3047c80b4e2fcbed0df1b265d73dbef174291fcb4cdc427cef12ea3cf3c53ae3'+
|
83
|
+
'3009718000000001976a914b14a2f25ceaa17b72a089813eae8f33f9dddeb0c88a'+
|
84
|
+
'c00000000'
|
85
|
+
|
86
|
+
|
87
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
88
|
+
record = Counterparty::TxDecode.new tx
|
89
|
+
|
90
|
+
expect(record.data).to eq("\x00\x00\x00\x1EUT\xA9\xA2\xBF\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(BLOCKSCAN VERIFY-ADDRESS 4mmqa6iccbrrgky".force_encoding('ASCII-8BIT'))
|
91
|
+
expect(record.sender_addr).to eq('1HARUMuoSXftAwY6jxMUutc9uKSCK9zxzF')
|
92
|
+
expect(record.receiver_addr).to be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it "decodes a pubkeyhash encoding" do
|
96
|
+
# This was from Txid:
|
97
|
+
# '76133a842ced8d76047e070924bca66652b19581803079f200d35fd824499940'
|
98
|
+
raw_tx = '01000000011b4e667cf0b715fa95be6baa6b505'+
|
99
|
+
'78fd9c3fa15fb0a5554aeb5f3991e672c64010000006a47304402204dea7f4824a'+
|
100
|
+
'c40fc501fab3e341c2e47670a81b38820854b6f5540c673945a8a0220110446d7a'+
|
101
|
+
'4e76df07041ef76f137485f0d0fd9114d612e784e2721954129c48701210321bab'+
|
102
|
+
'6d17f75ebbbdd71793fa9c1136b537e5679ea2fc153fa1cb0884d038834fffffff'+
|
103
|
+
'f0436150000000000001976a914748e483222863a836a421df1a9395bbd835bdfd'+
|
104
|
+
'a88ac36150000000000001976a91461e09442c872dabb980a7a86a04323a62512e'+
|
105
|
+
'c5d88ac36150000000000001976a91463e09442c872dabb98467a86a0432653c40'+
|
106
|
+
'c96c088ac20867700000000001976a914ce27246a0a6ca54dfa1f780ccd5cb3d0c'+
|
107
|
+
'73a75b288ac00000000'
|
108
|
+
|
109
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
110
|
+
record = Counterparty::TxDecode.new tx
|
111
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x1Ez\x9DL\x00\x00\x00\x00\x05\xF5\xE1\x00".force_encoding('ASCII-8BIT'))
|
112
|
+
expect(record.receiver_addr).to eq('1BdHqBSfUqv77XtBSeofH6XwHHczZxKRUF')
|
113
|
+
expect(record.sender_addr).to eq('1Ko36AjTKYh6EzToLU737Bs2pxCsGReApK')
|
114
|
+
end
|
115
|
+
|
116
|
+
it "decodes these weird two output OP_RETURNs" do
|
117
|
+
# The reason this is a weird transaction is
|
118
|
+
# because the size of the inputs happens to equal dust_size + tx fee
|
119
|
+
#
|
120
|
+
# This was from Txid:
|
121
|
+
# '05f89f3538e762c534fa9c65200c115b9796386ce2eb8f88f3d7b430873ec302'
|
122
|
+
raw_tx = '010000000341ba60588bdf72c63ae3641767f59'+
|
123
|
+
'5be991e8c70bf970b658d48c2a3446d367a000000006b483045022100c8f219137'+
|
124
|
+
'6cc2c0235d8cd66e429fbd7bb0cbe410e35359d6a1a27b903345f1d0220696f72e'+
|
125
|
+
'af67f3bfe96fc7504fe1b9d5455bdde45dba127a1e082152c056706bc012102724'+
|
126
|
+
'0dfe6f1b45e009812b9bf0b1dce959f3313e28140185800c9fec814f00351fffff'+
|
127
|
+
'fff713f469f416cd52270f756373d6da00b6829b88240d7aa9f74464f0e77df836'+
|
128
|
+
'a000000006b483045022100a8da4b96afe2a70c69fa9aacf186e2ba0ed03782bd7'+
|
129
|
+
'b4fe70e3e75a4ed62380e02206964db4f0d19a9ed4753ecbd8685fdb6e45e23611'+
|
130
|
+
'7ec4eeaca968acb781d9b110121027240dfe6f1b45e009812b9bf0b1dce959f331'+
|
131
|
+
'3e28140185800c9fec814f00351ffffffffcdd532ffa6e5742ca99bd5f713777d3'+
|
132
|
+
'b6569152a813e3b351ccb9da82abe456d000000006b48304502210093c57cd43cc'+
|
133
|
+
'ca9a9c7743341c23bba532dc9025f8f4fea7c02d56a4197e2737802207e4a8dec6'+
|
134
|
+
'5efe31fef6e9297698207b5d09f8729974a90e70ff85b1ee6029d670121027240d'+
|
135
|
+
'fe6f1b45e009812b9bf0b1dce959f3313e28140185800c9fec814f00351fffffff'+
|
136
|
+
'f0256400000000000001976a9148c2e9372962ce45c5c2f33479499314a71e6ea3'+
|
137
|
+
'd88ac00000000000000001e6a1c00d0dd53993819edb255fc6e348bfcb2092d896'+
|
138
|
+
'9d012da6183f8ec6100000000'
|
139
|
+
|
140
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
141
|
+
record = Counterparty::TxDecode.new tx
|
142
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x05\xF5\xE1\x00".force_encoding('ASCII-8BIT'))
|
143
|
+
expect(record.receiver_addr).to eq('1DnDQ1ef1eCuFcexZn1wqXFdtbFTQqE9LH')
|
144
|
+
expect(record.sender_addr).to be_nil
|
145
|
+
end
|
146
|
+
|
147
|
+
it "decodes a four output pubkeyhash" do
|
148
|
+
# This was from Txid:
|
149
|
+
# '76133a842ced8d76047e070924bca66652b19581803079f200d35fd824499940'
|
150
|
+
raw_tx = '01000000011b4e667cf0b715fa95be6baa6b505'+
|
151
|
+
'78fd9c3fa15fb0a5554aeb5f3991e672c64010000006a47304402204dea7f4824a'+
|
152
|
+
'c40fc501fab3e341c2e47670a81b38820854b6f5540c673945a8a0220110446d7a'+
|
153
|
+
'4e76df07041ef76f137485f0d0fd9114d612e784e2721954129c48701210321bab'+
|
154
|
+
'6d17f75ebbbdd71793fa9c1136b537e5679ea2fc153fa1cb0884d038834fffffff'+
|
155
|
+
'f0436150000000000001976a914748e483222863a836a421df1a9395bbd835bdfd'+
|
156
|
+
'a88ac36150000000000001976a91461e09442c872dabb980a7a86a04323a62512e'+
|
157
|
+
'c5d88ac36150000000000001976a91463e09442c872dabb98467a86a0432653c40'+
|
158
|
+
'c96c088ac20867700000000001976a914ce27246a0a6ca54dfa1f780ccd5cb3d0c'+
|
159
|
+
'73a75b288ac00000000'
|
160
|
+
|
161
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
162
|
+
record = Counterparty::TxDecode.new tx
|
163
|
+
|
164
|
+
expect(record.data).to eq("\x00\x00\x00\x00\x00\x00\x00\x00\x1Ez\x9DL\x00\x00\x00\x00\x05\xF5\xE1\x00".force_encoding('ASCII-8BIT'))
|
165
|
+
expect(record.receiver_addr).to eq('1BdHqBSfUqv77XtBSeofH6XwHHczZxKRUF')
|
166
|
+
expect(record.sender_addr).to eq('1Ko36AjTKYh6EzToLU737Bs2pxCsGReApK')
|
167
|
+
end
|
168
|
+
|
169
|
+
it "decodes the mother of all multisig broadcasts" do
|
170
|
+
# This was from Txid:
|
171
|
+
# '14200afba2c8f91664afc37143763e5987a20647db3443c999137cc41b4db6e4'
|
172
|
+
# This transaction was enormous, so I'm just going to pull it from the web:
|
173
|
+
raw_tx = BlockrIo.new.getrawtransaction '14200afba2c8f91664afc37143763e5987a20647db3443c999137cc41b4db6e4'
|
174
|
+
|
175
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
176
|
+
record = Counterparty::TxDecode.new tx
|
177
|
+
|
178
|
+
expect(record.data).to eq("\x00\x00\x00\x1EUj\x18\xE0\xBF\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Commerce on the Internet has come to rely almost exclusively on financial institutions serving as trusted third parties to process electronic payments. While the system works well enough for most transactions, it still suffers from the inherent weaknesses of the trust based model. Completely non-reversible transactions are not really possible, since financial institutions cannot avoid mediating disputes. The cost of mediation increases transaction costs, limiting the minimum practical transaction size and cutting off the possibility for small casual transactions, and there is a broader cost in the loss of ability to make non-reversible payments for nonreversible services. With the possibility of reversal, the need for trust spreads. Merchants must be wary of their customers, hassling them for more information than they would otherwise need. A certain percentage of fraud is accepted as unavoidable. These costs and payment uncertainties can be avoided in person by using physical currency, but no mechanism exists to make payments over a communications channel without a trusted party. What is needed is an electronic payment system based on cryptographic proof instead of trust, allowing any two willing parties to transact directly with each other without the need for a trusted third party. Transactions that are computationally impractical to reverse would protect sellers from fraud, and routine escrow mechanisms could easily be implemented to protect buyers. In this paper, we propose a solution to the double-spending problem using a peer-to-peer distributed timestamp server to generate computational proof of the chronological order of transactions. The system is secure as long as honest nodes collectively control more CPU power than any cooperating group of attacker nodes.".force_encoding('ASCII-8BIT'))
|
179
|
+
expect(record.sender_addr).to eq('186sRhi5Ux1eKGzx5vRdq1ueGGB5NKLKRr')
|
180
|
+
expect(record.receiver_addr).to be_nil
|
181
|
+
end
|
182
|
+
|
183
|
+
it "doesn't support multisig transactions ATM" do
|
184
|
+
# Txid:
|
185
|
+
# d4153cb6c3756d5198af15a018f50731dcdacae86d5448c7404b7e42adf59942
|
186
|
+
|
187
|
+
raw_tx = '010000000145a4f089931f677dd5c97c7c5de6e2e748c431726d0a9dc8b200df4250'+
|
188
|
+
'596768020000006b483045022100fd881b69b1572587c224e7bf79bc7aba96447946cecb1fb'+
|
189
|
+
'66f7c4a7ac140881c022030f91bb9a9c119c8ccf9fdf7d86d123a5c3e791fecc3578433db39'+
|
190
|
+
'b54fed674c01210202baab55d662c40f5846da3ac914fef8acc4c2932dac0120808c3fcc583'+
|
191
|
+
'ad0efffffffff03781e000000000000c95241047664bc75c1eb2df0082e6753fa01fe3ed690'+
|
192
|
+
'012236d9629d9e754dc63b540634c5db95700fa337c4e2374519d357ebc4fa2a69b02f30aa9'+
|
193
|
+
'2988afdaaad2a2e314104cb88f386eccbccb0b847b69e6ef3570ad5ce2397cd6bd74cd448d1'+
|
194
|
+
'a5de31a5a3e7deadb446bcb25df8ecf45b3aad234e16183b71c2621829572e268c18ccb72f4'+
|
195
|
+
'104fb41fed5c73b3fa08f8be7e31982f4fb490d0d5017a65c2ebf0a0bbb930ceff7dba3581c'+
|
196
|
+
'941a71035f5a06254364d9deb6de40c1626e10205f840ab11315904c53ae000000000000000'+
|
197
|
+
'01e6a1c593b2c1d8269aa039023b56b6487bf8dbedc7b880f42bddbe7388989de7f0b000000'+
|
198
|
+
'00001976a9149583a3a598b987d5fa27eae2dc27f004b11277b988ac00000000'
|
199
|
+
|
200
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
201
|
+
expect{ Counterparty::TxDecode.new tx }.to raise_error(::Counterparty::TxDecode::MultisigUnsupported)
|
202
|
+
end
|
203
|
+
|
204
|
+
it "Doesn't parse this weird double output send to self" do
|
205
|
+
# Txid: http://www.blockscan.com/txInfo/11675374
|
206
|
+
# b062d52f7749cf46cbe01e8dd16fe2b7edd6483269c8a0ac5b0b3f8ea6370e5f
|
207
|
+
|
208
|
+
raw_tx = '01000000015869b4a6e10d9540621b168e9cde9fa45fd79540725a3512c6'+
|
209
|
+
'be63a8ab81d154020000006b483045022100f92d69473147027150680b138b70e1f'+
|
210
|
+
'89fef78c8e276f7cd251ebb226fd4c4bb0220673e07a6323c0bc7e927939a062ec2'+
|
211
|
+
'c557b585b45cc2336bbcb0131d15fe835b012102a51147c9e3a554ed35e20cc5ca0'+
|
212
|
+
'fef20e47ae976cfe06a594e135e416bb05e32ffffffff0436150000000000001976'+
|
213
|
+
'a9144de50dc01362d6ad9b4365a56167dae8c029bba188ac3615000000000000197'+
|
214
|
+
'6a9149c834113474128c7c59eec778d57cbcca48839be88ac00000000000000001e'+
|
215
|
+
'6a1c4a789161a23e6f1be8c311a7aa330f31a9ca450a1cec95caca0df2c89fc97c0'+
|
216
|
+
'0000000001976a9144de50dc01362d6ad9b4365a56167dae8c029bba188ac00000000'
|
217
|
+
|
218
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
219
|
+
expect{ Counterparty::TxDecode.new tx }.to raise_error(
|
220
|
+
::Counterparty::TxDecode::UndefinedBehavior)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "Data before addresses" do
|
224
|
+
# Txid: http://www.blockscan.com/txInfo/11675370
|
225
|
+
# 54d181aba863bec612355a724095d75fa49fde9c8e161b6240950de1a6b46958
|
226
|
+
|
227
|
+
raw_tx = '01000000017b66db9fdbdddc72fe24bfc9a85842d8bd68f75300756b7b7b'+
|
228
|
+
'bff250e2874071020000006a47304402207207e0204153c828ef3357252a52d522a'+
|
229
|
+
'07f43ba2024582312f02507c4b57ca1022037f2182ee6f664d235879119c6ff10d5'+
|
230
|
+
'3e2dfa6bce0126bcb68af78ce2c4dd32012102a51147c9e3a554ed35e20cc5ca0fe'+
|
231
|
+
'f20e47ae976cfe06a594e135e416bb05e32ffffffff0300000000000000001e6a1c'+
|
232
|
+
'd5a46d783d4d425b6e0c4fe1bcc1bc3fb8827e67e81199ff98d0d2f636150000000'+
|
233
|
+
'000001976a9149c834113474128c7c59eec778d57cbcca48839be88ac1b1b7d0000'+
|
234
|
+
'0000001976a9144de50dc01362d6ad9b4365a56167dae8c029bba188ac00000000'
|
235
|
+
|
236
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
237
|
+
expect{ Counterparty::TxDecode.new tx }.to raise_error(
|
238
|
+
::Counterparty::TxDecode::UndefinedBehavior)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "Doesn't parse this weird double-output spend" do
|
242
|
+
# Txid: http://www.blockscan.com/txInfo/11674475
|
243
|
+
# 99beec983f9b700629cb3283b5444e837b73790d2e0eec60f00fdb443340d446
|
244
|
+
|
245
|
+
raw_tx = '0100000001f2e2738960c4f488f0913ebbbb787e3f4db6e953a099275a56'+
|
246
|
+
'e75be340c58424020000006b483045022100f241dfcc797e46978bc2cfd54976dac'+
|
247
|
+
'32edb03c5022367bb50bb9bdec45ebaab02206039b0a664cfa3d7190405a1fbdb63'+
|
248
|
+
'497bfb066dcd4f70e8a574024823c01cc6012102a51147c9e3a554ed35e20cc5ca0'+
|
249
|
+
'fef20e47ae976cfe06a594e135e416bb05e32ffffffff0436150000000000001976'+
|
250
|
+
'a9149c834113474128c7c59eec778d57cbcca48839be88ac3615000000000000197'+
|
251
|
+
'6a914bce6192508e34eba664cfe21dd495c59d5501c2088ac00000000000000001e'+
|
252
|
+
'6a1ce85876dd554d039aaee671e845972981b6a0e283de1a7ea8c59df734330c7e0'+
|
253
|
+
'0000000001976a9144de50dc01362d6ad9b4365a56167dae8c029bba188ac00000000'
|
254
|
+
|
255
|
+
tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
|
256
|
+
expect{ Counterparty::TxDecode.new tx }.to raise_error(
|
257
|
+
::Counterparty::TxDecode::UndefinedBehavior)
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_relative 'spec_helper'
|
3
|
+
|
4
|
+
describe Counterparty::TxEncode do
|
5
|
+
describe ".encode" do
|
6
|
+
it "Tokenly's getSampleCounterpartyTransactionProtocol2()" do
|
7
|
+
encoder = Counterparty::TxEncode.new(
|
8
|
+
# Key:
|
9
|
+
"\x8F\xD9\xF6\x89\xF1X\xA4&\x86r\x15\xDB\xDE\xE5\x8E\x9E\xABl\x81"+
|
10
|
+
"\x80\x97\xD4\xBF+\xCF\v\xD1E\x8F<U\xAB",
|
11
|
+
# Data:
|
12
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x17Hv\xE8\x00",
|
13
|
+
:receiver_addr => "12pv1K6LTLPFYXcCwsaU7VWYRSX7BuiF28",
|
14
|
+
:sender_pubkey => '02f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e6')
|
15
|
+
|
16
|
+
expect(encoder.to_opmultisig).to eq([
|
17
|
+
"OP_DUP OP_HASH160 1407ec32be440f32fc70f4eea810acd98f32aa32 OP_EQUALVERIFY OP_CHECKSIG",
|
18
|
+
"1 0276d539826e5ec10fed9ef597d5bfdac067d287fb7f06799c449971b9ddf9fec6 02af7efeb1f7cf0d5077ae7f7a59e2b643c5cd01fb55221bf76221d8c8ead92bf0 02f4aef682535628a7e0492b2b5db1aa312348c3095e0258e26b275b25b10290e6 3 OP_CHECKMULTISIG",
|
19
|
+
"OP_DUP OP_HASH160 6ca4b6b20eac497e9ca94489c545a3372bdd2fa7 OP_EQUALVERIFY OP_CHECKSIG"
|
20
|
+
] )
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Tokenly's getSampleCounterpartyTransaction3()" do
|
24
|
+
encoder = Counterparty::TxEncode.new(
|
25
|
+
# Key:
|
26
|
+
"\xE7\xF91\x9D\xE8Va\xC310\xE8\v}\xF1g3\x16H\x92\xEE\xB2\xE1\xFB"+
|
27
|
+
"\x04NZ\xC5\xDEz2i\xB7",
|
28
|
+
# Data:
|
29
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x00\v\xEB\xC2\x00",
|
30
|
+
:receiver_addr => "1FEbYaghvr7V53B9csjQTefUtBBQTaDFvN",
|
31
|
+
:sender_pubkey => "0257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690")
|
32
|
+
|
33
|
+
expect(encoder.to_opmultisig).to eq([
|
34
|
+
"OP_DUP OP_HASH160 9c2401388e6d2752a496261e9130cd54ddb2b262 OP_EQUALVERIFY OP_CHECKSIG",
|
35
|
+
"1 035240874259b8f93dffc6ffa29b09d0d06dfb072d9646ae777480a2c521bfdbb1 0264f1dd503423e8305e19fc77b4e26dc8ec8a8f500b1bec580112af8c64e74b1b 0257b0d96d1fe64fbb95b2087e68592ee016c50f102d8dcf776ed166473f27c690 3 OP_CHECKMULTISIG",
|
36
|
+
"OP_DUP OP_HASH160 0c7bea5ae61ccbc157156ffc9466a54b07bfe951 OP_EQUALVERIFY OP_CHECKSIG"
|
37
|
+
|
38
|
+
] )
|
39
|
+
end
|
40
|
+
|
41
|
+
it "Tokenly's getSampleCounterpartyTransaction4()" do
|
42
|
+
encoder = Counterparty::TxEncode.new(
|
43
|
+
# Key:
|
44
|
+
"\xA6\xED\xB8aq\xFCw68\x9F \xBCcT\"U\xDB\xBF\xA2\xDC\xD1s\xFC\a\x94"+
|
45
|
+
"\x14\xAD\xAB\x7FT\x80q",
|
46
|
+
# Data:
|
47
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x00"+
|
48
|
+
"\x05\xF5\xE1\x00",
|
49
|
+
:receiver_addr => "1Q7VHJDEzVj7YZBVseQWgYvVj3DWDCLwDE",
|
50
|
+
:sender_addr => '1MFHQCPGtcSfNPXAS6NryWja3TbUN9239Y')
|
51
|
+
|
52
|
+
expect(encoder.to_opreturn).to eq([
|
53
|
+
"OP_DUP OP_HASH160 fd84ff1f2cc1b0299165e2804fccd6fb0bd48d0b OP_EQUALVERIFY OP_CHECKSIG",
|
54
|
+
"OP_RETURN 2c54fff6d3e165e008f5ec45a06951e6b6fb4a162fcfec34aa1f0dd8",
|
55
|
+
"OP_DUP OP_HASH160 de1607744008a3edeabae06365a9aa2b131d5dc2 OP_EQUALVERIFY OP_CHECKSIG"
|
56
|
+
] )
|
57
|
+
end
|
58
|
+
|
59
|
+
it "Tokenly's getSampleCounterpartyTransaction5()" do
|
60
|
+
encoder = Counterparty::TxEncode.new(
|
61
|
+
# Key:
|
62
|
+
"\xCF\x8F\xA2\x9C\xF698\xA7\x87\xE72\xC8PqiVh\xB9\xE0\v\xFE\xDF\xF8"+
|
63
|
+
"\a\xDF\xBD\xC8Zj\xD6\xA6\x96",
|
64
|
+
# Data:
|
65
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xFA\xDF\x00\x00\x00\x01*"+
|
66
|
+
"\x05\xF2\x00",
|
67
|
+
:receiver_addr => "1KUsjZKrkd7LYRV7pbnNJtofsq1HAiz6MF",
|
68
|
+
:sender_addr => '12iVwKP7jCPnuYy7jbAbyXnZ3FxvgLwvGK')
|
69
|
+
|
70
|
+
expect(encoder.to_opreturn).to eq([
|
71
|
+
"OP_DUP OP_HASH160 cab7d87116e620e10a69e666ec6494d4607631e7 OP_EQUALVERIFY OP_CHECKSIG",
|
72
|
+
"OP_RETURN fb706d6b2839cfd52a4b50cb135f18cf9e0b280ca45b2da5694229f0",
|
73
|
+
"OP_DUP OP_HASH160 12d155cefea286e9d3cda6cb64cd8d26a5b95780 OP_EQUALVERIFY OP_CHECKSIG"
|
74
|
+
] )
|
75
|
+
end
|
76
|
+
|
77
|
+
it "encodes a four output pubkeyhash" do
|
78
|
+
# This was from Txid:
|
79
|
+
# '76133a842ced8d76047e070924bca66652b19581803079f200d35fd824499940'
|
80
|
+
|
81
|
+
encoder = Counterparty::TxEncode.new(
|
82
|
+
# Key:
|
83
|
+
"d,g\x1E\x99\xF3\xB5\xAETU\n\xFB\x15\xFA\xC3\xD9\x8FWPk\xAAk\xBE"+
|
84
|
+
"\x95\xFA\x15\xB7\xF0|fN\e",
|
85
|
+
# Data:
|
86
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x1Ez\x9DL\x00\x00\x00\x00\x05"+
|
87
|
+
"\xF5\xE1\x00".force_encoding('UTF-8'),
|
88
|
+
:receiver_addr => "1BdHqBSfUqv77XtBSeofH6XwHHczZxKRUF",
|
89
|
+
:sender_addr => '1Ko36AjTKYh6EzToLU737Bs2pxCsGReApK')
|
90
|
+
|
91
|
+
expect(encoder.to_pubkeyhash).to eq([
|
92
|
+
'OP_DUP OP_HASH160 748e483222863a836a421df1a9395bbd835bdfda OP_EQUALVERIFY OP_CHECKSIG',
|
93
|
+
'OP_DUP OP_HASH160 61e09442c872dabb980a7a86a04323a62512ec5d OP_EQUALVERIFY OP_CHECKSIG',
|
94
|
+
'OP_DUP OP_HASH160 63e09442c872dabb98467a86a0432653c40c96c0 OP_EQUALVERIFY OP_CHECKSIG',
|
95
|
+
'OP_DUP OP_HASH160 ce27246a0a6ca54dfa1f780ccd5cb3d0c73a75b2 OP_EQUALVERIFY OP_CHECKSIG',
|
96
|
+
] )
|
97
|
+
end
|
98
|
+
|
99
|
+
it "Encodes the gigantic multsig satoshi broadcast" do
|
100
|
+
# This was from Txid:
|
101
|
+
# '14200afba2c8f91664afc37143763e5987a20647db3443c999137cc41b4db6e4'
|
102
|
+
|
103
|
+
encoder = Counterparty::TxEncode.new(
|
104
|
+
# Key:
|
105
|
+
"\x13\xA2\x19LGG\xC7g\x85\xA7N\xFEQ\xB8xyG\x16E\xDD\xC1&\x8D\xE9"+
|
106
|
+
"\xCA\xA6%\xF3\xA9\xA3\x05E",
|
107
|
+
# Data:
|
108
|
+
"\x00\x00\x00\x1EUj\x18\xE0\xBF\xF0\x00\x00\x00\x00\x00\x00\x00\x00"+
|
109
|
+
"\x00\x00Commerce on the Internet has come to rely almost exclusively"+
|
110
|
+
" on financial institutions serving as trusted third parties to "+
|
111
|
+
"process electronic payments. While the system works well enough for "+
|
112
|
+
"most transactions, it still suffers from the inherent weaknesses of "+
|
113
|
+
"the trust based model. Completely non-reversible transactions are "+
|
114
|
+
"not really possible, since financial institutions cannot avoid "+
|
115
|
+
"mediating disputes. The cost of mediation increases transaction "+
|
116
|
+
"costs, limiting the minimum practical transaction size and cutting "+
|
117
|
+
"off the possibility for small casual transactions, and there is a "+
|
118
|
+
"broader cost in the loss of ability to make non-reversible payments "+
|
119
|
+
"for nonreversible services. With the possibility of reversal, the "+
|
120
|
+
"need for trust spreads. Merchants must be wary of their customers, "+
|
121
|
+
"hassling them for more information than they would otherwise need. "+
|
122
|
+
"A certain percentage of fraud is accepted as unavoidable. These "+
|
123
|
+
"costs and payment uncertainties can be avoided in person by using "+
|
124
|
+
"physical currency, but no mechanism exists to make payments over a "+
|
125
|
+
"communications channel without a trusted party. What is needed is "+
|
126
|
+
"an electronic payment system based on cryptographic proof instead "+
|
127
|
+
"of trust, allowing any two willing parties to transact directly "+
|
128
|
+
"with each other without the need for a trusted third party. "+
|
129
|
+
"Transactions that are computationally impractical to reverse would "+
|
130
|
+
"protect sellers from fraud, and routine escrow mechanisms could "+
|
131
|
+
"easily be implemented to protect buyers. In this paper, we propose "+
|
132
|
+
"a solution to the double-spending problem using a peer-to-peer "+
|
133
|
+
"distributed timestamp server to generate computational proof of the "+
|
134
|
+
"chronological order of transactions. The system is secure as long "+
|
135
|
+
"as honest nodes collectively control more CPU power than any "+
|
136
|
+
"cooperating group of attacker nodes.".force_encoding('UTF-8'),
|
137
|
+
:sender_pubkey => '02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32')
|
138
|
+
|
139
|
+
expect(encoder.to_opmultisig).to eq([
|
140
|
+
'1 027d222586a44cc5d365673cb613c1bb8df9cf6ab74cd825b1e0b2e579b1fd423d 0370a16f70a8a8a0a9afc5c0f3b9aae5d02b9bcf9f3351eb6cba0df8490e54ed2d 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
141
|
+
'1 027d222586a44cc5d3654748d92de6b4f96050fbdb21b756c5c0d79d1addcb5e31 0374ba6f6eb2edefa8e183ddf5bde4cfd73e929d983856bf6daf0bac430e57fb85 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
142
|
+
'1 037d222586a44cc5d365474fd37fe2b8fb7e50fbc46cac57c493c6801d91ca45f6 0274be6e22bbacf2b2a880c7bba8e58cce2d91de942556eb61b71bbb5e1356e617 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
143
|
+
'1 037d222586a44cc5d3650e5f967df5a8f87c1eeec462f872d989de8059c5d648b6 033dbf7371bfa8ede6b68ac6f0afaadbdb33929d94384abe63b35ebe451319e588 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
144
|
+
'1 027d222586a44cc5d365084fc22de0a3f47703fbd438b14adf939ec510c59e5e12 0269a5666eebbef5a0a780c6e8fcecded132dec9993305a26ab31baa4f0f4da807 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
145
|
+
'1 027d222586a44cc5d3651059d766fab4e66a15e99723be05c588d7c50dc3cb5e2f 0269ec6863b8a8e4e6ac8ad0feb0a48cfd3093cd9d3351ae68a25eb6450f14fab6 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
146
|
+
'1 027d222586a44cc5d365024ad37fe7b8f77515bac33eb94bc281d19110ded05ed3 023dad7867eba3efb2e197d1fab0e6d59e2f91ce823f47a761f75eab430f5aed27 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
147
|
+
'1 037d222586a44cc5d365475adf63f5bff67011f69725b656c589c6900dd8d14359 036eec6963a5a3efb2e184c2f4b5ee8cd33a9ad490224ca563fb1ab159114cfc69 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
148
|
+
'1 027d222586a44cc5d365024f982dc0b9f03913f5c438f84ad7c0df801dd8df59cd 0374a36422a2a3e3b4a484c7feafaad8cc3e90ce903551a26bb55ebb45124dfb30 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
149
|
+
'1 037d222586a44cc5d3654b1cda64f9b8e1701efd9738b040918ddb8b10dccb40cd 033dbc7863a8b9e9a5a08994efaeebc2cd3e9dc998394beb77b204bd0a0057ecec 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
150
|
+
'1 037d222586a44cc5d365475fc379e0b8fb7e50f5d12af851d985929516c2cd44b2 037fa5666bbfb4a0a0ae9794e8b1ebc0d27f9ddc822344a724af0cb9441258eb0d 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
151
|
+
'1 037d222586a44cc5d3651355d963e7fdb5781efe9738b040c385928c0a91df0dc3 037fbe6563afa8f2e6a28ac7effce3c29e2b96d8d13a4ab877fb11be0a005be11c 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
152
|
+
'1 037d222586a44cc5d3650b55c274b4a5fa391dfbdc29f84bde8e9f971cc7db5f20 026ea5686eaeedf0a7b888d1f5a8f98cd8308c9d9f394bb961ad1baa59085be4a1 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
153
|
+
'1 027d222586a44cc5d365021cc568e6a7fc7a15e9996c8f4cc588929111d49e5d3e 0372bf796ba9a4ecafb59c94f4baaadedb299bcf823749e724af16bd0a0f5cedaf 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
154
|
+
'1 027d222586a44cc5d365031cd062e6f1e16b05e9c36cab55c385d3810a9f9e603b 0378be696aaaa3f4b5e188c1e8a8aacedb7f89dc832f05a462fb0ab04f084ba822 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
155
|
+
'1 037d222586a44cc5d3650449c579fbbcf06b03b69724b956c28cdb8b1e91ca456c 0278a12a64a4bfa0abae97d1bbb5e4cad12d93dc853f4aa524af16b944414de0ed 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
156
|
+
'1 027d222586a44cc5d3650245967afba4f97d50f5c324bd57c689c18059dfdb4812 0279e22a43ebaee5b4b584ddf5fcfac9cc3c9bd3853742ae24b418f84c1358fd9a 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
157
|
+
'1 037d222586a44cc5d365031cdf7eb4b0f67a15eac329bc05d093929017d0c84266 0374a86b60a7a8aee6958dd1e8b9aacfd12c8aced1374baf24ab1fa1470457fcc6 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
158
|
+
'1 037d222586a44cc5d3654749d86ef1a3e17819f4c325bd569183d38b59d3db0dbb 037cba656bafa8e4e6a88b94ebb9f8dfd131dedf887650b86db519f85a0940fb0e 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
159
|
+
'1 027d222586a44cc5d3650e5fd761b4b2e06b02ffd92fa1099182c79159dfd10d1a 0270a9696aaaa3e9b5acc5d1e3b5f9d8cd7f8ad2d13b44a061fb0eb9530c5ce606 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
160
|
+
'1 027d222586a44cc5d365134f9662e2b4e73911bad423b548c48edb8618c5d74244 0273bf2a61a3aceea8a48994ecb5fec4d12a8a9d907651b971a80abd4e4149e9d4 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
161
|
+
'1 037d222586a44cc5d3651548cf23b486fd7804bade3ff84bd485d6801d91d75e46 023dad6422aea1e5a5b597dbf5b5e98cce3e87d0943851eb77a20dac4f0c19eab3 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
162
|
+
'1 037d222586a44cc5d365064fd369b4befb3913e8ce3cac4ad692d39511d8dd0d73 036dbe656dadede9a8b291d1fab8aac3d87f8acf842551e724ba12b4451650e621 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
163
|
+
'1 037d222586a44cc5d365001cd763edf1e16e1fbac025b449d88ed5c509d0cc5903 0274a97922bfa2a0b2b384dae8bde9d89e3b97cf943551a77dfb09b15e0919edcc 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
164
|
+
'1 037d222586a44cc5d365065fde2dfba5fd7c02bac025ac4dde95c6c50dd9db0db3 0273a96f66ebabefb4e18494efaeffdfca3a9a9d853e4cb960fb0eb9581540a605 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
165
|
+
'1 037d222586a44cc5d3654768c46cfaa2f47a04f3d822ab05c588d39159d0cc48a5 023daf656fbbb8f4a7b58cdbf5bde6c0c77f97d0812444a870b21db946414de79b 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
166
|
+
'1 037d222586a44cc5d365474ed37bf1a3e67c50edd839b4419190c08a0dd4dd591a 033dbf6f6ea7a8f2b5e183c6f4b1aacacc3e8bd9dd7644a560fb0cb75f1550e63b 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
167
|
+
'1 037d222586a44cc5d365021cd37ef7a3fa6e50f7d22fb044df89c1880a91dd4230 0268a06e22aeacf3afad9c94f9b9aac5d32f92d89c334bbf61bf5eac454149fa71 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
168
|
+
'1 027d222586a44cc5d3650848d36ee0f1f76c09ffc53ff605f88e929111d8cd0d21 036dad7a67b9e1a0b1a4c5c4e9b3fac3cd3adedcd1254aa771af17b744414de797 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
169
|
+
'1 027d222586a44cc5d3654748de68b4b5fa6c12f6d261ab55d48ed68c17d69e5d8c 026fa3686eaea0a0b3b28cdafcfceb8cce3a9bcfdc224ae674be1baa0a0550fbc3 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
170
|
+
'1 037d222586a44cc5d365134edf6fe1a5f07d50eede21bd56c581df9559c2db5f85 026ba97822bfa2a0a1a48bd1e9bdfec99e3c91d0812351aa70b211b64b0d19f864 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
171
|
+
'1 037d222586a44cc5d3651553d96bb4bef33904f2d26cbb4dc38fdc8a15ded944c9 037ead6622a4bfe4a3b3c5dbfdfcfededf318ddc92224ca46aa850f87e095ca8e6 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
172
|
+
'1 027d222586a44cc5d3651445c579f1bcb57003bac429bb50c38592840a91d242ae 0373ab2a63b8ede8a9af80c7effce4c3da3a8d9d923949a761b80ab15c0455f1a7 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
173
|
+
'1 037d222586a44cc5d365475fd963e0a3fa7550f7d83ebd05f2b0e7c509dec9487c 026fec7e6aaaa3a0a7af9c94f8b3e5dcdb2d9fc9983842eb63a911ad5a4156ee70 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
174
|
+
'1 0258222586a44cc5d365475dc279f5b2fe7c02bad923bc40c2ceb2e579b1be2df1 031dcc0a02cbcd80c6c1e5b49bdc8aacbe5ffebdf15625cb04db7ed82a6139888b 02a51147c9e3a554ed35e20cc5ca0fef20e47ae976cfe06a594e135e416bb05e32 3 OP_CHECKMULTISIG',
|
175
|
+
'OP_DUP OP_HASH160 4de50dc01362d6ad9b4365a56167dae8c029bba1 OP_EQUALVERIFY OP_CHECKSIG'
|
176
|
+
])
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
metadata
CHANGED
@@ -1,126 +1,125 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: counterparty_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Chris DeRose
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2015-
|
11
|
+
date: 2015-08-01 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rest-client
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: bitcoin-ruby
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: ffi
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ruby-rc4
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
60
67
|
- !ruby/object:Gem::Version
|
61
68
|
version: '0'
|
62
69
|
- !ruby/object:Gem::Dependency
|
63
70
|
name: rspec
|
64
71
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
72
|
requirements:
|
67
|
-
- -
|
73
|
+
- - ">="
|
68
74
|
- !ruby/object:Gem::Version
|
69
75
|
version: '0'
|
70
76
|
type: :development
|
71
77
|
prerelease: false
|
72
78
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
79
|
requirements:
|
75
|
-
- -
|
80
|
+
- - ">="
|
76
81
|
- !ruby/object:Gem::Version
|
77
82
|
version: '0'
|
78
83
|
- !ruby/object:Gem::Dependency
|
79
84
|
name: rspec-its
|
80
85
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
86
|
requirements:
|
83
|
-
- -
|
87
|
+
- - ">="
|
84
88
|
- !ruby/object:Gem::Version
|
85
89
|
version: '0'
|
86
90
|
type: :development
|
87
91
|
prerelease: false
|
88
92
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
93
|
requirements:
|
91
|
-
- -
|
94
|
+
- - ">="
|
92
95
|
- !ruby/object:Gem::Version
|
93
96
|
version: '0'
|
94
97
|
- !ruby/object:Gem::Dependency
|
95
98
|
name: rake
|
96
99
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
100
|
requirements:
|
99
|
-
- -
|
101
|
+
- - ">="
|
100
102
|
- !ruby/object:Gem::Version
|
101
103
|
version: '0'
|
102
104
|
type: :development
|
103
105
|
prerelease: false
|
104
106
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
107
|
requirements:
|
107
|
-
- -
|
108
|
+
- - ">="
|
108
109
|
- !ruby/object:Gem::Version
|
109
110
|
version: '0'
|
110
111
|
- !ruby/object:Gem::Dependency
|
111
112
|
name: rdoc
|
112
113
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
121
|
requirements:
|
123
|
-
- -
|
122
|
+
- - ">="
|
124
123
|
- !ruby/object:Gem::Version
|
125
124
|
version: '0'
|
126
125
|
description: This gem is designed to abstract communications with the counterpartyd
|
@@ -131,7 +130,7 @@ executables: []
|
|
131
130
|
extensions: []
|
132
131
|
extra_rdoc_files: []
|
133
132
|
files:
|
134
|
-
- .gitignore
|
133
|
+
- ".gitignore"
|
135
134
|
- Gemfile
|
136
135
|
- Gemfile.lock
|
137
136
|
- README.md
|
@@ -142,6 +141,8 @@ files:
|
|
142
141
|
- lib/counterparty/raw_tx.rb
|
143
142
|
- lib/counterparty/resource.rb
|
144
143
|
- lib/counterparty/resources.rb
|
144
|
+
- lib/counterparty/tx_decode.rb
|
145
|
+
- lib/counterparty/tx_encode.rb
|
145
146
|
- lib/counterparty/version.rb
|
146
147
|
- lib/counterparty_ruby.rb
|
147
148
|
- spec/blockr_io_spec.rb
|
@@ -152,30 +153,31 @@ files:
|
|
152
153
|
- spec/resource_create_spec.rb
|
153
154
|
- spec/resource_read_spec.rb
|
154
155
|
- spec/spec_helper.rb
|
156
|
+
- spec/tx_decode_spec.rb
|
157
|
+
- spec/tx_encode_spec.rb
|
155
158
|
homepage: https://github.com/brighton36/counterparty_ruby
|
156
159
|
licenses:
|
157
160
|
- LGPL
|
161
|
+
metadata: {}
|
158
162
|
post_install_message:
|
159
163
|
rdoc_options: []
|
160
164
|
require_paths:
|
161
165
|
- lib
|
162
166
|
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
-
none: false
|
164
167
|
requirements:
|
165
|
-
- -
|
168
|
+
- - ">="
|
166
169
|
- !ruby/object:Gem::Version
|
167
170
|
version: '1.9'
|
168
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
-
none: false
|
170
172
|
requirements:
|
171
|
-
- -
|
173
|
+
- - ">="
|
172
174
|
- !ruby/object:Gem::Version
|
173
175
|
version: '0'
|
174
176
|
requirements: []
|
175
177
|
rubyforge_project:
|
176
|
-
rubygems_version:
|
178
|
+
rubygems_version: 2.4.6
|
177
179
|
signing_key:
|
178
|
-
specification_version:
|
180
|
+
specification_version: 4
|
179
181
|
summary: An ActiveRecord-esque abstraction of the Counterparty API
|
180
182
|
test_files:
|
181
183
|
- spec/blockr_io_spec.rb
|
@@ -186,3 +188,5 @@ test_files:
|
|
186
188
|
- spec/resource_create_spec.rb
|
187
189
|
- spec/resource_read_spec.rb
|
188
190
|
- spec/spec_helper.rb
|
191
|
+
- spec/tx_decode_spec.rb
|
192
|
+
- spec/tx_encode_spec.rb
|