dropzone_ruby 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Drop Zone - An Anonymous Peer-To-Peer Local Contraband Marketplace.pdf +0 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +69 -0
  6. data/README.md +62 -0
  7. data/bin/dropzone +487 -0
  8. data/dropzone-screenshot.jpg +0 -0
  9. data/dropzone_ruby.gemspec +31 -0
  10. data/lib/blockrio_ext.rb +52 -0
  11. data/lib/dropzone/buyer.rb +21 -0
  12. data/lib/dropzone/command.rb +488 -0
  13. data/lib/dropzone/communication.rb +43 -0
  14. data/lib/dropzone/connection.rb +312 -0
  15. data/lib/dropzone/invoice.rb +23 -0
  16. data/lib/dropzone/item.rb +160 -0
  17. data/lib/dropzone/listing.rb +64 -0
  18. data/lib/dropzone/message_base.rb +178 -0
  19. data/lib/dropzone/payment.rb +36 -0
  20. data/lib/dropzone/profile.rb +86 -0
  21. data/lib/dropzone/record_base.rb +34 -0
  22. data/lib/dropzone/seller.rb +21 -0
  23. data/lib/dropzone/session.rb +161 -0
  24. data/lib/dropzone/state_accumulator.rb +39 -0
  25. data/lib/dropzone/version.rb +4 -0
  26. data/lib/dropzone_ruby.rb +14 -0
  27. data/lib/veto_checks.rb +74 -0
  28. data/spec/bitcoin_spec.rb +115 -0
  29. data/spec/buyer_profile_spec.rb +279 -0
  30. data/spec/buyer_spec.rb +109 -0
  31. data/spec/command_spec.rb +353 -0
  32. data/spec/config.yml +5 -0
  33. data/spec/invoice_spec.rb +129 -0
  34. data/spec/item_spec.rb +294 -0
  35. data/spec/lib/fake_connection.rb +97 -0
  36. data/spec/listing_spec.rb +150 -0
  37. data/spec/payment_spec.rb +152 -0
  38. data/spec/seller_profile_spec.rb +290 -0
  39. data/spec/seller_spec.rb +120 -0
  40. data/spec/session_spec.rb +303 -0
  41. data/spec/sham/buyer.rb +5 -0
  42. data/spec/sham/invoice.rb +5 -0
  43. data/spec/sham/item.rb +8 -0
  44. data/spec/sham/payment.rb +13 -0
  45. data/spec/sham/seller.rb +7 -0
  46. data/spec/spec_helper.rb +49 -0
  47. metadata +267 -0
@@ -0,0 +1,109 @@
1
+ #encoding: utf-8
2
+ require_relative 'spec_helper'
3
+ require_relative 'sham/buyer'
4
+
5
+ describe Dropzone::Buyer do
6
+ include_context 'globals'
7
+
8
+ describe "defaults" do
9
+ it "has accessors" do
10
+ buyer = Dropzone::Buyer.sham!(:build)
11
+
12
+ expect(buyer.description).to eq("abc")
13
+ expect(buyer.alias).to eq("Satoshi")
14
+ expect(buyer.transfer_pkey).to be_nil
15
+ expect(buyer.receiver_addr).to eq(test_pubkey)
16
+ expect(buyer.sender_addr).to eq(nil)
17
+ end
18
+ end
19
+
20
+ describe "serialization" do
21
+ it "serializes to_transaction" do
22
+ expect(Dropzone::Buyer.sham!.to_transaction).to eq({
23
+ tip: 20000,
24
+ receiver_addr: test_pubkey,
25
+ data: "BYUPDT\u0001d\u0003abc\u0001a\aSatoshi".force_encoding('ASCII-8BIT') })
26
+ end
27
+ end
28
+
29
+ describe "database" do
30
+ after{ clear_blockchain! }
31
+
32
+ it ".save() and .find()" do
33
+ buyer = Dropzone::Buyer.sham!(:build).save!(test_privkey)
34
+ expect(buyer).to be_kind_of(String)
35
+
36
+ buyer = Dropzone::Buyer.find buyer
37
+ expect(buyer.description).to eq("abc")
38
+ expect(buyer.alias).to eq("Satoshi")
39
+ expect(buyer.transfer_pkey).to be_nil
40
+ expect(buyer.receiver_addr).to eq(test_pubkey)
41
+ expect(buyer.sender_addr).to eq(test_pubkey)
42
+ end
43
+ end
44
+
45
+ describe "validations" do
46
+ it "validates default build" do
47
+ expect(Dropzone::Buyer.sham!(:build).valid?).to eq(true)
48
+ end
49
+
50
+ it "validates minimal buyer" do
51
+ buyer = Dropzone::Buyer.new receiver_addr: test_pubkey
52
+
53
+ expect(buyer.valid?).to eq(true)
54
+ end
55
+
56
+ it "validates output address must be present" do
57
+ buyer = Dropzone::Buyer.sham! receiver_addr: nil
58
+
59
+ expect(buyer.valid?).to eq(false)
60
+ expect(buyer.errors.count).to eq(1)
61
+ expect(buyer.errors.on(:receiver_addr)).to eq(['is not present'])
62
+ end
63
+
64
+ it "description must be string" do
65
+ buyer = Dropzone::Buyer.sham! description: 1
66
+
67
+ expect(buyer.valid?).to eq(false)
68
+ expect(buyer.errors.count).to eq(1)
69
+ expect(buyer.errors.on(:description)).to eq(['is not a string'])
70
+ end
71
+
72
+ it "alias must be string" do
73
+ buyer = Dropzone::Buyer.sham! alias: 1
74
+
75
+ expect(buyer.valid?).to eq(false)
76
+ expect(buyer.errors.count).to eq(1)
77
+ expect(buyer.errors.on(:alias)).to eq(['is not a string'])
78
+ end
79
+
80
+ it "transfer_pkey must be pkey" do
81
+ buyer = Dropzone::Buyer.sham! transfer_pkey: 'bad-key'
82
+
83
+ expect(buyer.valid?).to eq(false)
84
+ expect(buyer.errors.count).to eq(2)
85
+ expect(buyer.errors.on(:transfer_pkey)).to eq(['does not match receiver_addr',
86
+ 'is not a public key' ])
87
+ end
88
+
89
+ it "transfer_pkey must be receiver_addr" do
90
+ buyer = Dropzone::Buyer.sham! transfer_pkey: TESTER2_PUBLIC_KEY
91
+
92
+ expect(buyer.valid?).to eq(false)
93
+ expect(buyer.errors.count).to eq(1)
94
+ expect(buyer.errors.on(:transfer_pkey)).to eq(['does not match receiver_addr'])
95
+ end
96
+
97
+ it "declaration must be addressed to self" do
98
+ id = Dropzone::Buyer.sham!(receiver_addr: TESTER2_PUBLIC_KEY).save! test_privkey
99
+
100
+ buyer = Dropzone::Buyer.find id
101
+
102
+ expect(buyer.valid?).to eq(false)
103
+ expect(buyer.errors.count).to eq(1)
104
+ expect(buyer.errors.on(:receiver_addr)).to eq(['does not match sender_addr'])
105
+ end
106
+ end
107
+
108
+
109
+ end
@@ -0,0 +1,353 @@
1
+ #encoding: utf-8
2
+ require_relative 'spec_helper'
3
+ require_relative '../lib/dropzone/command'
4
+
5
+ class Hash
6
+ alias :__hash__ :to_h
7
+ end
8
+
9
+ describe DropZoneCommand do
10
+ include_context 'globals'
11
+
12
+ before(:all) do
13
+ clear_blockchain!
14
+
15
+ # This allows us to preserve the transaction ids regardless of what tests
16
+ # ran before us.
17
+ db = FakeBitcoinConnection::DB.execute(
18
+ "UPDATE SQLITE_SEQUENCE SET SEQ=0 WHERE NAME='transactions';" )
19
+ end
20
+
21
+ def to_out(string)
22
+ string.strip.gsub(/^[ ]+/,'')+"\n"
23
+ end
24
+
25
+ it "creates buyers" do
26
+ expect{ DropZoneCommand.new(true).profile_buyer_create(
27
+ [test_privkey],
28
+ alias: "Miracle Max",
29
+ description: "First Buyer on DropZone"
30
+ )}.to output(to_out(<<-eos)).to_stdout
31
+ +-------------------------------------------+
32
+ | Buyer: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
33
+ +-------------------------------------------+
34
+ | alias : Miracle Max |
35
+ | description: First Buyer on DropZone |
36
+ +-------------------------------------------+
37
+ | Tx: 1 |
38
+ +-------------------------------------------+
39
+ eos
40
+
41
+ expect{ DropZoneCommand.new(true).profile_buyer_show(
42
+ [test_pubkey], {}
43
+ )}.to output(to_out(<<-eos)).to_stdout
44
+ +-------------------------------------------+
45
+ | Buyer: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
46
+ +-------------------------------------------+
47
+ | alias : Miracle Max |
48
+ | description: First Buyer on DropZone |
49
+ +-------------------------------------------+
50
+ eos
51
+ end
52
+
53
+ it "creates sellers" do
54
+ expect{ DropZoneCommand.new(true).profile_seller_create(
55
+ [TESTER2_PRIVATE_KEY],
56
+ alias: "Miracle Max",
57
+ description: "First Seller on DropZone",
58
+ communications_pkey: TESTER2_PUBLIC_KEY
59
+ )}.to output(to_out(<<-eos)).to_stdout
60
+ +---------------------------------------------------------+
61
+ | Seller: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
62
+ +---------------------------------------------------------+
63
+ | alias : Miracle Max |
64
+ | description : First Seller on DropZone |
65
+ | communications_pkey: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
66
+ +---------------------------------------------------------+
67
+ | Tx: 2 |
68
+ +---------------------------------------------------------+
69
+ eos
70
+
71
+ expect{ DropZoneCommand.new(true).profile_seller_show(
72
+ [TESTER2_PUBLIC_KEY], {}
73
+ )}.to output(to_out(<<-eos)).to_stdout
74
+ +---------------------------------------------------------+
75
+ | Seller: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
76
+ +---------------------------------------------------------+
77
+ | alias : Miracle Max |
78
+ | description : First Seller on DropZone |
79
+ | communications_pkey: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
80
+ +---------------------------------------------------------+
81
+ eos
82
+ end
83
+
84
+ it "creates listings" do
85
+ expect{ DropZoneCommand.new(true).listing_create(
86
+ [TESTER2_PRIVATE_KEY],
87
+ latitude: "51.500782", longitude: "-0.124669", radius: 1000,
88
+ price_currency: 'USD', price_in_units: 100,
89
+ description: "Test Description"
90
+ )}.to output(to_out(<<-eos)).to_stdout
91
+ +---------------------------------------------+
92
+ | Listing: mfZ1415XX782179875331XX1XXXXXgtzWu |
93
+ +---------------------------------------------+
94
+ | latitude : 51.500782 |
95
+ | longitude : -0.124669 |
96
+ | radius : 1000 |
97
+ | price_currency: USD |
98
+ | price_in_units: 100 |
99
+ | description : Test Description |
100
+ +---------------------------------------------+
101
+ | Tx: 3 |
102
+ +---------------------------------------------+
103
+ eos
104
+
105
+ expect{ DropZoneCommand.new(true).listing_show(
106
+ ['3'], {} )}.to output(to_out(<<-eos)).to_stdout
107
+ +----------------------------------------------------+
108
+ | Listing: 3 |
109
+ +----------------------------------------------------+
110
+ | latitude : 51.500782 |
111
+ | longitude : -0.124669 |
112
+ | radius : 1000 |
113
+ | price_currency: USD |
114
+ | price_in_units: 100 |
115
+ | description : Test Description |
116
+ | addr : mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
117
+ +----------------------------------------------------+
118
+ eos
119
+ end
120
+
121
+ it "updates listings" do
122
+ expect{ DropZoneCommand.new(true).listing_update(
123
+ [TESTER2_PRIVATE_KEY, '3'],
124
+ description: "Second Description"
125
+ )}.to output(to_out(<<-eos)).to_stdout
126
+ +---------------------------------------------+
127
+ | Listing: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
128
+ +---------------------------------------------+
129
+ | description: Second Description |
130
+ +---------------------------------------------+
131
+ | Tx: 4 |
132
+ +---------------------------------------------+
133
+ eos
134
+
135
+ expect{ DropZoneCommand.new(true).listing_show(
136
+ ['3'], {} )}.to output(to_out(<<-eos)).to_stdout
137
+ +----------------------------------------------------+
138
+ | Listing: 3 |
139
+ +----------------------------------------------------+
140
+ | latitude : 51.500782 |
141
+ | longitude : -0.124669 |
142
+ | radius : 1000 |
143
+ | price_currency: USD |
144
+ | price_in_units: 100 |
145
+ | description : Second Description |
146
+ | addr : mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
147
+ +----------------------------------------------------+
148
+ eos
149
+ end
150
+
151
+ it "creates invoices" do
152
+ expect{ DropZoneCommand.new(true).invoice_create(
153
+ [TESTER2_PRIVATE_KEY, test_pubkey],
154
+ amount_due: 50_000_000, expiration_in: 6
155
+ )}.to output(to_out(<<-eos)).to_stdout
156
+ +---------------------------------------------+
157
+ | Invoice: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
158
+ +---------------------------------------------+
159
+ | amount_due : 50000000 |
160
+ | expiration_in: 6 |
161
+ +---------------------------------------------+
162
+ | Tx: 5 |
163
+ +---------------------------------------------+
164
+ eos
165
+
166
+ expect{ DropZoneCommand.new(true).invoice_show(
167
+ ['5'], {} )}.to output(to_out(<<-eos)).to_stdout
168
+ +---------------------------------------------------+
169
+ | Invoice: 5 |
170
+ +---------------------------------------------------+
171
+ | amount_due : 50000000 |
172
+ | expiration_in: 6 |
173
+ | sender_addr : mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
174
+ | receiver_addr: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
175
+ +---------------------------------------------------+
176
+ eos
177
+ end
178
+
179
+ it "creates reviews" do
180
+ expect{ DropZoneCommand.new(true).review_create(
181
+ [test_privkey, '5'],
182
+ description: 'Fair exchange',
183
+ delivery_quality: 8,
184
+ product_quality: 8,
185
+ communications_quality: 4
186
+ )}.to output(to_out(<<-eos)).to_stdout
187
+ +--------------------------------------------+
188
+ | Review: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
189
+ +--------------------------------------------+
190
+ | description : Fair exchange |
191
+ | delivery_quality : 8 |
192
+ | product_quality : 8 |
193
+ | communications_quality: 4 |
194
+ | invoice_txid : 5 |
195
+ +--------------------------------------------+
196
+ | Tx: 6 |
197
+ +--------------------------------------------+
198
+ eos
199
+
200
+ expect{ DropZoneCommand.new(true).review_show(
201
+ ['6'], {} )}.to output(to_out(<<-eos)).to_stdout
202
+ +------------------------------------------------------------+
203
+ | Review: 6 |
204
+ +------------------------------------------------------------+
205
+ | description : Fair exchange |
206
+ | delivery_quality : 8 |
207
+ | product_quality : 8 |
208
+ | communications_quality: 4 |
209
+ | invoice_txid : 5 |
210
+ | sender_addr : mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
211
+ | receiver_addr : mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
212
+ +------------------------------------------------------------+
213
+ eos
214
+ end
215
+
216
+ it "converses" do
217
+ expect{ DropZoneCommand.new(true).communication_new(
218
+ [test_privkey, TESTER2_PUBLIC_KEY], {}
219
+ )}.to output(to_out(<<-eos)).to_stdout
220
+ +---------------------------------------------------+
221
+ | Session: 7 |
222
+ +---------------------------------------------------+
223
+ | sender_addr : mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
224
+ | receiver_addr: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
225
+ +---------------------------------------------------+
226
+ eos
227
+
228
+ expect{ DropZoneCommand.new(true).communication_list(
229
+ [test_privkey], {}
230
+ )}.to output(to_out(<<-eos)).to_stdout
231
+ +---------------------------------------------------+
232
+ | Session: 7 |
233
+ +---------------------------------------------------+
234
+ | sender_addr : mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
235
+ | receiver_addr: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
236
+ +---------------------------------------------------+
237
+ eos
238
+
239
+ expect{ DropZoneCommand.new(true).communication_list(
240
+ [TESTER2_PRIVATE_KEY], {}
241
+ )}.to output(to_out(<<-eos)).to_stdout
242
+ +---------------------------------------------------+
243
+ | Session: 7 |
244
+ +---------------------------------------------------+
245
+ | sender_addr : mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
246
+ | receiver_addr: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
247
+ +---------------------------------------------------+
248
+ eos
249
+
250
+ expect{ DropZoneCommand.new(true).communication_say(
251
+ [TESTER2_PRIVATE_KEY, '7', 'Greetings Initiator'], {}
252
+ )}.to output(to_out(<<-eos)).to_stdout
253
+ +-------------------------------------------------+
254
+ | Communication: 9 |
255
+ +-------------------------------------------------+
256
+ | Session : 7 |
257
+ | sender_addr: mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp |
258
+ | message : Greetings Initiator |
259
+ +-------------------------------------------------+
260
+ eos
261
+
262
+ expect{ DropZoneCommand.new(true).communication_say(
263
+ [test_privkey, '7', 'Conversation Initiated'], {}
264
+ )}.to output(to_out(<<-eos)).to_stdout
265
+ +-------------------------------------------------+
266
+ | Communication: 10 |
267
+ +-------------------------------------------------+
268
+ | Session : 7 |
269
+ | sender_addr: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
270
+ | message : Conversation Initiated |
271
+ +-------------------------------------------------+
272
+ eos
273
+
274
+ expect{ DropZoneCommand.new(true).communication_show(
275
+ [test_privkey, '7'], {}
276
+ )}.to output(to_out(<<-eos)).to_stdout
277
+ +------------------------------------------------------------+
278
+ | Communication: 7 |
279
+ +------------------------------------------------------------+
280
+ | mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw: Conversation Initiated |
281
+ | mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp: Greetings Initiator |
282
+ +------------------------------------------------------------+
283
+ eos
284
+
285
+ expect{ DropZoneCommand.new(true).communication_show(
286
+ [TESTER2_PRIVATE_KEY, '7'], {}
287
+ )}.to output(to_out(<<-eos)).to_stdout
288
+ +------------------------------------------------------------+
289
+ | Communication: 7 |
290
+ +------------------------------------------------------------+
291
+ | mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw: Conversation Initiated |
292
+ | mqVRfjepJTxxoDgDt892tCybhmjfKCFNyp: Greetings Initiator |
293
+ +------------------------------------------------------------+
294
+ eos
295
+ end
296
+
297
+ it "wraps exceedingly long table values" do
298
+ abstract = (<<-eos).tr("\n", " ")
299
+ Abstract. Drop Zone is a solution to the problem of restricted sales in censored markets.
300
+ The proposal is for the design of a protocol and reference client that encodes the location
301
+ and a brief description of a good onto The Blockchain. Those wishing to purchase the
302
+ good can search for items within a user-requested radius. Sellers list a good as available
303
+ within a geographic region, subject to some degree of precision, for the purpose of
304
+ obfuscating their precise location. Goods are announced next to an expiration, a hashtag,
305
+ and if space permits, a description. Once a buyer finds a good in a defined relative
306
+ proximity, a secure communication channel is opened between the parties on the Bitcoin
307
+ test network ("testnet"). Once negotiations are complete, the buyer sends payment to the
308
+ seller via the address listed on the Bitcoin mainnet. This spend action establishes
309
+ reputation for the buyer, and potentially for the seller. Once paid, the seller is to furnish
310
+ the exact GPS coordinates of the good to the buyer (alongside a small note such as
311
+ "Check in the crevice of the tree"). When the buyer successfully picks up the item at the
312
+ specified location, the buyer then issues a receipt with a note by spending flake to the
313
+ address of the original post. In this way, sellers receive a reputation score. The solution
314
+ is akin to that of Craigslist.org or Uber, but is distributed and as such provides nearly
315
+ risk-free terms to contraband sellers, and drastically reduced risk to contraband buyers.
316
+ eos
317
+
318
+ expect{ DropZoneCommand.new(true).communication_say(
319
+ [test_privkey, '7', abstract], {}
320
+ )}.to output(to_out(<<-eos)).to_stdout
321
+ +----------------------------------------------------------------------------------+
322
+ | Communication: 11 |
323
+ +----------------------------------------------------------------------------------+
324
+ | Session : 7 |
325
+ | sender_addr: mi37WkBomHJpUghCn7Vgh3ah33h6L9Nkqw |
326
+ | message : Abstract. Drop Zone is a solution to the problem of restricted |
327
+ | : sales in censored markets. The proposal is for the design of a |
328
+ | : protocol and reference client that encodes the location and a |
329
+ | : brief description of a good onto The Blockchain. Those wishing to |
330
+ | : purchase the good can search for items within a user-requested |
331
+ | : radius. Sellers list a good as available within a geographic |
332
+ | : region, subject to some degree of precision, for the purpose of |
333
+ | : obfuscating their precise location. Goods are announced next to an |
334
+ | : expiration, a hashtag, and if space permits, a description. Once a |
335
+ | : buyer finds a good in a defined relative proximity, a secure |
336
+ | : communication channel is opened between the parties on the Bitcoin |
337
+ | : test network ("testnet"). Once negotiations are complete, the |
338
+ | : buyer sends payment to the seller via the address listed on the |
339
+ | : Bitcoin mainnet. This spend action establishes reputation for the |
340
+ | : buyer, and potentially for the seller. Once paid, the seller is to |
341
+ | : furnish the exact GPS coordinates of the good to the buyer |
342
+ | : (alongside a small note such as "Check in the crevice of the |
343
+ | : tree"). When the buyer successfully picks up the item at the |
344
+ | : specified location, the buyer then issues a receipt with a note by |
345
+ | : spending flake to the address of the original post. In this way, |
346
+ | : sellers receive a reputation score. The solution is akin to that |
347
+ | : of Craigslist.org or Uber, but is distributed and as such provides |
348
+ | : nearly risk-free terms to contraband sellers, and drastically |
349
+ | : reduced risk to contraband buyers. |
350
+ +----------------------------------------------------------------------------------+
351
+ eos
352
+ end
353
+ end