counterparty_ruby 0.9.0

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.
@@ -0,0 +1,179 @@
1
+ module Counterparty
2
+ # A base class for the purpose of extending by api result hashes
3
+ class CounterResource
4
+ # This is mostly used by the eq operation and indicates the
5
+ # attributes that this resource has
6
+ attr_accessor :result_attributes # :nodoc:
7
+
8
+ # encoding (string): The encoding method to use
9
+ attr_accessor :encoding
10
+
11
+ # pubkey (string): The pubkey hex string. Required if multisig transaction
12
+ # encoding is specified for a key external to counterpartyd's local wallet.
13
+ attr_accessor :pubkey
14
+
15
+ # allow_unconfirmed_inputs (boolean): Set to true to allow this transaction
16
+ # to utilize unconfirmed UTXOs as inputs.
17
+ attr_accessor :allow_unconfirmed_inputs
18
+
19
+ # fee (integer): If you'd like to specify a custom miners' fee, specify it
20
+ # here (in satoshi). Leave as default for counterpartyd to automatically
21
+ # choose.
22
+ attr_accessor :fee
23
+
24
+ # fee_per_kb (integer): The fee per kilobyte of transaction data constant
25
+ # that counterpartyd uses when deciding on the dynamic fee to use
26
+ # (in satoshi). Leave as default unless you know what you're doing.
27
+ attr_accessor :fee_per_kb
28
+
29
+ def initialize(attrs={})
30
+ @result_attributes = attrs.keys.sort.collect(&:to_sym)
31
+ attrs.each{|k,v| instance_variable_set '@%s' % k, v}
32
+ end
33
+
34
+ # Just a simple compare. No need to get crazy
35
+ def ==(b) # :nodoc:
36
+ ( b.respond_to?(:result_attributes) &&
37
+ result_attributes == b.result_attributes &&
38
+ @result_attributes.all?{ |k| send(k) == b.send(k) } )
39
+ end
40
+
41
+ # This method returns the unsigned raw create transaction string. hex
42
+ # encoded (i.e. the same format that bitcoind returns with its raw
43
+ # transaction API calls).
44
+ def to_raw_tx
45
+ connection.request self.class.to_create_request, to_params
46
+ end
47
+
48
+ # Given the provided private key, this method returns a signed transaction
49
+ # suitable for broadcasting on the network.
50
+ #
51
+ # NOTE: This method communicates your private key to the counterpartyd
52
+ # server, which might not be what you want!
53
+ def to_signed_tx(private_key)
54
+ sign_tx to_raw_tx, private_key
55
+ end
56
+
57
+ # Commit this object to the blockchain. If a private key is passed, the
58
+ # transaction is signed using this key via a create_ call and a subsequent
59
+ # sign_tx call.
60
+ # NOTE: This method communicates your private key to the counterpartyd
61
+ # server, which might not be what you want!
62
+ def save!(private_key = nil)
63
+ (private_key) ?
64
+ connection.broadcast_tx( to_signed_tx(private_key) ) :
65
+ connection.request(self.class.to_do_request, to_params)
66
+ end
67
+
68
+ private
69
+
70
+ # Currently this is communicating the request to the backend. This method
71
+ # is a stub for when we decide in the future to Use the bitcoin-client gem
72
+ # to perform signatures
73
+ def sign_tx(raw_tx, pkey_wif)
74
+ key = ::Bitcoin.open_key pkey_wif
75
+ raw_tx_hash = RawTx.new(raw_tx).to_hash
76
+
77
+ prev_hash = raw_tx_hash['vin'][0]['txid']
78
+ prior_tx_json = open("http://test.webbtc.com/tx/#{prev_hash}.json").read
79
+ puts prior_tx_json.inspect
80
+ prev_tx = Bitcoin::P::Tx.from_json(prior_tx_json.to_s)
81
+
82
+
83
+ puts "HERE"
84
+ signed_tx = Bitcoin::Protocol::Tx.new
85
+ signed_tx.ver = raw_tx_hash['ver']
86
+ signed_tx.lock = raw_tx_hash['lock_time']
87
+
88
+ tx_in= TxInBuilder.new
89
+ tx_in.prev_out prev_tx
90
+ tx_in.prev_out_index 0
91
+ tx_in.signature_key key
92
+
93
+ signed_tx.add_in tx_in.tx
94
+
95
+ # Here's how we put them in the raw
96
+ # @block.tx << tx
97
+
98
+
99
+ # We need to compare against
100
+ # Primarily: http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html
101
+ # With Some of this: https://bitcoin.org/en/developer-reference#signrawtransaction
102
+ =begin
103
+ def sign(tx, i, priv, hashcode=SIGHASH_ALL):
104
+ i = int(i)
105
+ if not re.match('^[0-9a-fA-F]*$', tx):
106
+ return binascii.unhexlify(sign(binascii.hexlify(tx), i, priv))
107
+ if len(priv) <= 33:
108
+ priv = binascii.hexlify(priv)
109
+ pub = privkey_to_pubkey(priv)
110
+ address = pubkey_to_address(pub)
111
+ signing_tx = signature_form(tx, i, mk_pubkey_script(address), hashcode)
112
+ sig = ecdsa_tx_sign(signing_tx, priv, hashcode)
113
+ txobj = deserialize(tx)
114
+ txobj["ins"][i]["script"] = serialize_script([sig, pub])
115
+ return serialize(txobj)
116
+ =end
117
+
118
+
119
+ scriptSig = Bitcoin.sign_data(key,
120
+ raw_tx_hash["in"][0]["scriptSig"] ).unpack('h*').first
121
+ # TODO: We may have to iterate over each input
122
+ raw_tx_hash["in"][0]["scriptSig"] = scriptSig
123
+
124
+ ret = Bitcoin::Protocol::Tx.from_hash(raw_tx_hash).to_payload.unpack('h*').first
125
+
126
+ ret
127
+ end
128
+
129
+ def connection
130
+ self.class.connection
131
+ end
132
+
133
+ # This serializes self into a hash suitable for transmission via json
134
+ def to_params
135
+ Hash[* @result_attributes.collect{|k|
136
+ v = self.send(k)
137
+ (v) ? [k,self.send(k)] : nil
138
+ }.compact.flatten]
139
+ end
140
+
141
+ class << self
142
+ # The base connection object for this class
143
+ attr_writer :connection
144
+
145
+ # Returns the counterparty-api version of this objects class name
146
+ def api_name
147
+ to_s.split('::').last.gsub(/[^\A]([A-Z])/, '_\\1').downcase
148
+ end
149
+
150
+ # Returns the currently assigned connection object, or if one hasn't
151
+ # been set, the default specified in the Counterparty module
152
+ def connection
153
+ @connection || Counterparty.connection
154
+ end
155
+
156
+ # Returns the method name of a do_* request for this resource
157
+ def to_do_request
158
+ 'do_%s' % api_name
159
+ end
160
+
161
+ # Returns the method name of a create_* request for this resource
162
+ def to_create_request
163
+ 'create_%s' % api_name
164
+ end
165
+
166
+ # Returns the method name of a get_* request for this resource
167
+ def to_get_request
168
+ 'get_%ss' % api_name
169
+ end
170
+
171
+ # Queries the counterpartyd connection to find matching instances of this
172
+ # resource, given the filters provided in the params
173
+ def find(params)
174
+ connection.request(to_get_request, params).collect{|r| new r}
175
+ end
176
+ end
177
+ end
178
+ end
179
+