exonum-client-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2234809e9ae540d2ae606a94240b4c2f7643a03473617058824e115dd5d60b21
4
+ data.tar.gz: f731faae600d904377c8a504f6ae7efe9537bae7cce5c47f1ce3bea78838d0ef
5
+ SHA512:
6
+ metadata.gz: 503e23958b618d4262619dd97d68e157bf30536ef50ac3ee884c04449186a3d57eacca34bf258267604485644d6471986cfbbaadc097c3b4f22b2fa4373f3954
7
+ data.tar.gz: 96ed0b2cca0afc8f645796638dcbb19760576e95de4f2d674bc85b5374305fbda3d93b26a97a9138140a62a7efc1f51a1318bafa9314e44811742a8f0ab4ecc8
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ db/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in insque.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 gropher
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Exonum Client Ruby
2
+
3
+ Light client for Exonum blockchain framework. [Exonum homepage](https://exonum.com)
4
+
5
+ ## Current state
6
+
7
+ Pre alpha
8
+
9
+ ## Usage
10
+
11
+ Signing a message:
12
+
13
+ # Ed25519 private key in hex
14
+ secret = '867103771411a6d8e14dd2b037bb5b57ab0add4debdc39147f9d2eae342a388d29823166d18e2471a19b16d261fe329f1228048846c1acea2f370e6a89c7a4d9'
15
+ # Message params template
16
+ fields = [
17
+ { name: 'pub_key', type: Exonum::PublicKeyT.new },
18
+ { name: 'amount', type: Exonum::UInt64T.new },
19
+ { name: 'seed', type: Exonum::UInt64T.new }
20
+ ]
21
+
22
+ # Message params values
23
+ data = {
24
+ 'pub_key' => "29823166d18e2471a19b16d261fe329f1228048846c1acea2f370e6a89c7a4d9",
25
+ 'amount' => 10,
26
+ 'seed' => 4645085842425400387
27
+ }
28
+
29
+ # protocol_version: 0, message_id: 1, service_id: 128
30
+ message = Exonum::MessageT.new 0, 1, 128, Exonum::StructT.new(fields)
31
+
32
+ # get ed25519 signature in hex
33
+ # 46386a5ef9ad0ac5d1e2fe509e3e3bfa27f4f0d376628169df76b5c02f77f8699ed966031a42bbc1a94002c4ec666f4e7d143a481e19eee306a2dfd8280c3d0e
34
+ message.sign(secret, data)
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/exonum/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Yuri Gomozov"]
6
+ gem.email = ["grophen@gmail.com"]
7
+ gem.description = "Light client for Exonum blockchain framework. https://exonum.com"
8
+ gem.summary = "Exonum light clent written in Ruby"
9
+ gem.homepage = "https://github.com/IPINVEST/exonum-client-ruby"
10
+ gem.licenses = ['MIT']
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "exonum-client-ruby"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Exonum::VERSION
18
+
19
+ gem.add_dependency('ed25519', '> 0')
20
+ gem.add_dependency('sparse_array', '> 0')
21
+ gem.add_dependency('activesupport', '> 3')
22
+ gem.add_development_dependency('rspec', '> 3')
23
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_support/all'
2
+ require 'sparse_array'
3
+ require 'ed25519'
4
+ require 'securerandom'
5
+ require 'exonum/util/sparse_array'
6
+ require 'exonum/util/seed'
7
+ require 'exonum/types/primitive'
8
+ require 'exonum/types/struct'
9
+ require 'exonum/types/array'
10
+ require 'exonum/types/message'
11
+
12
+
13
+ module Exonum
14
+ end
@@ -0,0 +1,51 @@
1
+ module Exonum
2
+ class ArrayT
3
+ attr_accessor :value_type
4
+
5
+ def initialize value_type
6
+ raise 'String arrays are not supported yet' if value_type.is_a?(StringT)
7
+ self.value_type = value_type
8
+ end
9
+
10
+ def size
11
+ 8
12
+ end
13
+
14
+ def fixed?
15
+ false
16
+ end
17
+
18
+ def serialize data, buffer, from=0, shift=0
19
+ raise "Expecting array" unless data.is_a?(Array)
20
+ UInt32T.new.serialize buffer.length, buffer, from
21
+ UInt32T.new.serialize data.length, buffer, from + 4
22
+ if value_type.is_a?(StringT)
23
+ start = buffer.length
24
+ (start..(data.length*8-1)).each do |i|
25
+ buffer[i] = 0
26
+ end
27
+ (0..(data.length-1)).each do |i|
28
+ index = start + i*8
29
+ finish = buffer.length
30
+ UInt32T.new.serialize finish - shift, buffer, index
31
+ value_type.serialize data[i], buffer, finish
32
+ UInt32T.new.serialize buffer.length - finish, buffer, index + 4
33
+ end
34
+ elsif value_type.is_a?(ArrayT)
35
+ start = buffer.length
36
+ (start..(data.length*8-1)).each do |i|
37
+ buffer[i] = 0
38
+ end
39
+ (0..(data.length-1)).each do |i|
40
+ index = start + i*8
41
+ value_type.serialize data[i], buffer, shift
42
+ end
43
+ else
44
+ data.each do |item|
45
+ bufferLength = buffer.length
46
+ value_type.serialize item, buffer, bufferLength, bufferLength + value_type.size
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,49 @@
1
+ module Exonum
2
+ class MessageT
3
+ attr_accessor :protocol_version
4
+ attr_accessor :message_id
5
+ attr_accessor :service_id
6
+ attr_accessor :head
7
+ attr_accessor :body
8
+ attr_accessor :signature
9
+
10
+ def initialize protocol_version, message_id, service_id, body
11
+ self.protocol_version = protocol_version
12
+ self.message_id = message_id
13
+ self.service_id = service_id
14
+ self.head = StructT.new([
15
+ { name: 'network_id', type: UInt8T.new },
16
+ { name: 'protocol_version', type: UInt8T.new },
17
+ { name: 'message_id', type: UInt16T.new },
18
+ { name: 'service_id', type: UInt16T.new },
19
+ { name: 'payload', type: UInt32T.new }
20
+ ])
21
+ self.body = body
22
+ end
23
+
24
+ def serialize data, cutSignature
25
+ buffer = SparseArray.new
26
+ head_data = {
27
+ network_id: 0,
28
+ protocol_version: self.protocol_version,
29
+ message_id: self.message_id,
30
+ service_id: self.service_id,
31
+ payload: 0 # placeholder, real value will be inserted later
32
+ }
33
+ head.serialize head_data, buffer, 0
34
+ body.serialize data, buffer, head.size, 0, true
35
+ UInt32T.new.serialize buffer.length + SignatureT.new.size, buffer, 6
36
+ unless cutSignature
37
+ SignatureT.new.serialize signature, buffer, buffer.length
38
+ end
39
+ buffer.serialize
40
+ end
41
+
42
+ def sign secret, data
43
+ raise "Expecting 64 bytes key in hex" unless secret.is_a?(String) and secret.length == 128
44
+ key = Ed25519::SigningKey.new [secret[0..63]].pack 'H*'
45
+ buffer = serialize(data, true).pack('c*')
46
+ key.sign(buffer).unpack('H*').first
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,280 @@
1
+ module Exonum
2
+ MIN_INT8 = -128
3
+ MAX_INT8 = 127
4
+ MIN_INT16 = -32768
5
+ MAX_INT16 = 32767
6
+ MIN_INT32 = -2147483648
7
+ MAX_INT32 = 2147483647
8
+ MIN_INT64 = -9223372036854775808
9
+ MAX_INT64 = 9223372036854775807
10
+ MAX_UINT8 = 255
11
+ MAX_UINT16 = 65535
12
+ MAX_UINT32 = 4294967295
13
+ MAX_UINT64 = 18446744073709551615
14
+
15
+ class Int8T
16
+ def size
17
+ 1
18
+ end
19
+
20
+ def fixed?
21
+ true
22
+ end
23
+
24
+ def serialize value, buffer, from, shift=0
25
+ raise 'Incorrect integer value' if value < MIN_INT8 or value > MAX_INT8
26
+ [value].pack('c').bytes.each do |byte|
27
+ buffer[from] = byte
28
+ from += 1
29
+ end
30
+ end
31
+ end
32
+
33
+ class UInt8T
34
+ def size
35
+ 1
36
+ end
37
+
38
+ def fixed?
39
+ true
40
+ end
41
+
42
+ def serialize value, buffer, from, shift=0
43
+ raise 'Incorrect integer value' if value < 0 or value > MAX_UINT8
44
+ [value].pack('C').bytes.each do |byte|
45
+ buffer[from] = byte
46
+ from += 1
47
+ end
48
+ end
49
+ end
50
+
51
+ class Int16T
52
+ def size
53
+ 2
54
+ end
55
+
56
+ def fixed?
57
+ true
58
+ end
59
+
60
+ def serialize value, buffer, from, shift=0
61
+ raise 'Incorrect integer value' if value < MIN_INT16 or value > MAX_INT16
62
+ [value].pack('s<').bytes.each do |byte|
63
+ buffer[from] = byte
64
+ from += 1
65
+ end
66
+ end
67
+ end
68
+
69
+ class UInt16T
70
+ def size
71
+ 2
72
+ end
73
+
74
+ def fixed?
75
+ true
76
+ end
77
+
78
+ def serialize value, buffer, from, shift=0
79
+ raise 'Incorrect integer value' if value < 0 or value > MAX_UINT16
80
+ [value].pack('S<').bytes.each do |byte|
81
+ buffer[from] = byte
82
+ from += 1
83
+ end
84
+ end
85
+ end
86
+
87
+ class Int32T
88
+ def size
89
+ 4
90
+ end
91
+
92
+ def fixed?
93
+ true
94
+ end
95
+
96
+ def serialize value, buffer, from, shift=0
97
+ raise 'Incorrect integer value' if value < MIN_INT32 or value > MAX_INT32
98
+ [value].pack('l<').bytes.each do |byte|
99
+ buffer[from] = byte
100
+ from += 1
101
+ end
102
+ end
103
+ end
104
+
105
+ class UInt32T
106
+ def size
107
+ 4
108
+ end
109
+
110
+ def fixed?
111
+ true
112
+ end
113
+
114
+ def serialize value, buffer, from, shift=0
115
+ raise 'Incorrect integer value' if value < 0 or value > MAX_UINT32
116
+ [value].pack('L<').bytes.each do |byte|
117
+ buffer[from] = byte
118
+ from += 1
119
+ end
120
+ end
121
+ end
122
+
123
+ class Int64T
124
+ def size
125
+ 8
126
+ end
127
+
128
+ def fixed?
129
+ true
130
+ end
131
+
132
+ def serialize value, buffer, from, shift=0
133
+ [value].pack('q<').bytes.each do |byte|
134
+ buffer[from] = byte
135
+ from += 1
136
+ end
137
+ end
138
+ end
139
+
140
+ class UInt64T
141
+ def size
142
+ 8
143
+ end
144
+
145
+ def fixed?
146
+ true
147
+ end
148
+
149
+ def serialize value, buffer, from, shift=0
150
+ [value].pack('Q<').bytes.each do |byte|
151
+ buffer[from] = byte
152
+ from += 1
153
+ end
154
+ end
155
+ end
156
+
157
+ class Float32T
158
+ def size
159
+ 4
160
+ end
161
+
162
+ def fixed?
163
+ true
164
+ end
165
+
166
+ def serialize value, buffer, from, shift=0
167
+ [value].pack('e').bytes.each do |byte|
168
+ buffer[from] = byte
169
+ from += 1
170
+ end
171
+ end
172
+ end
173
+
174
+ class Float64T
175
+ def size
176
+ 8
177
+ end
178
+
179
+ def fixed?
180
+ true
181
+ end
182
+
183
+ def serialize value, buffer, from, shift=0
184
+ [value].pack('E').bytes.each do |byte|
185
+ buffer[from] = byte
186
+ from += 1
187
+ end
188
+ end
189
+ end
190
+
191
+ class BoolT
192
+ def size
193
+ 1
194
+ end
195
+
196
+ def fixed?
197
+ true
198
+ end
199
+
200
+ def serialize value, buffer, from, shift=0
201
+ buffer[from] = value ? 1 : 0
202
+ end
203
+ end
204
+
205
+ class PublicKeyT
206
+ def size
207
+ 32
208
+ end
209
+
210
+ def fixed?
211
+ true
212
+ end
213
+
214
+ def serialize value, buffer, from, shift=0
215
+ raise "Expecting #{size} bytes in hex" unless value.is_a?(String) and value.length == size*2
216
+ [value].pack('H*').bytes.each do |byte|
217
+ buffer[from] = byte
218
+ from += 1
219
+ end
220
+ end
221
+ end
222
+
223
+ class HashT
224
+ def size
225
+ 32
226
+ end
227
+
228
+ def fixed?
229
+ true
230
+ end
231
+
232
+ def serialize value, buffer, from, shift=0
233
+ raise "Expecting #{size} bytes in hex" unless value.is_a?(String) and value.length == size*2
234
+ [value].pack('H*').bytes.each do |byte|
235
+ buffer[from] = byte
236
+ from += 1
237
+ end
238
+ end
239
+ end
240
+
241
+ class SignatureT
242
+ def size
243
+ 64
244
+ end
245
+
246
+ def fixed?
247
+ true
248
+ end
249
+
250
+ def serialize value, buffer, from, shift=0
251
+ raise "Expecting #{size} bytes in hex" unless value.is_a?(String) and value.length == size*2
252
+ [value].pack('H*').bytes.each do |byte|
253
+ buffer[from] = byte
254
+ from += 1
255
+ end
256
+ end
257
+ end
258
+
259
+ class StringT
260
+ def size
261
+ 8
262
+ end
263
+
264
+ def fixed?
265
+ false
266
+ end
267
+
268
+ def serialize value, buffer, from, shift=0
269
+ raise "Expecting string" unless value.is_a?(String)
270
+ bufferLengthOld = buffer.length
271
+ bufferLengthNew = bufferLengthOld
272
+ UInt32T.new.serialize(bufferLengthOld - shift, buffer, from) # index where string content starts in buffer
273
+ value.bytes.each do |byte|
274
+ buffer[bufferLengthNew] = byte
275
+ bufferLengthNew += 1
276
+ end
277
+ UInt32T.new.serialize(bufferLengthNew - bufferLengthOld, buffer, from + 4) # string length
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,59 @@
1
+ module Exonum
2
+ class StructT
3
+ attr_accessor :fields
4
+
5
+ def initialize fields
6
+ raise 'Expecting array parameter' unless fields.is_a?(Array)
7
+ fields.each do |field|
8
+ raise 'Name property is missing' unless field[:name].present?
9
+ raise 'Type property is missing' unless field[:type].present?
10
+ end
11
+ self.fields = fields
12
+ end
13
+
14
+ def size
15
+ fields.map do |field|
16
+ if field[:type].fixed?
17
+ field[:type].size
18
+ else
19
+ 8
20
+ end
21
+ end.reduce(&:+)
22
+ end
23
+
24
+ def fixed?
25
+ fields.map {|f| f[:type].fixed? }.reduce(&:&)
26
+ end
27
+
28
+ def serialize data, buffer, from=0, shift=0, isTransactionBody=false
29
+ (0..(size-1)).each do |i|
30
+ buffer[from+i] = 0
31
+ end
32
+ localShift = 0
33
+ fields.each do |field|
34
+ value = data.with_indifferent_access[field[:name]]
35
+ raise "Field #{field[:name]} is not defined" unless value.present?
36
+ localFrom = from + localShift
37
+ nestedShift = isTransactionBody ? 0 : shift
38
+ if field[:type].is_a?(StructT)
39
+ if field[:type].fixed?
40
+ field[:type].serialize value, buffer, localFrom, nestedShift
41
+ localShift += field[:type].size
42
+ else
43
+ bufferLengthOld = buffer.length
44
+ UInt32T.new.serialize(bufferLengthOld - nestedShift, buffer, localFrom) # index where string content starts in buffer
45
+ field[:type].serialize value, buffer, bufferLengthOld, nestedShift
46
+ bufferLengthNew = buffer.length
47
+ UInt32T.new.serialize(bufferLengthNew - bufferLengthOld, buffer, localFrom + 4) # string length
48
+ localShift += 8
49
+ end
50
+ else
51
+ field[:type].serialize value, buffer, localFrom, nestedShift
52
+ localShift += field[:type].size
53
+ #puts "\n\n#{field[:type].class.name}, #{value}, #{localFrom}, #{nestedShift}"
54
+ #puts buffer.serialize.inspect
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,5 @@
1
+ module Exonum
2
+ def self.generate_seed
3
+ SecureRandom.random_bytes(16).unpack('Q<').first
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ class SparseArray
2
+ def length
3
+ if keys.any?
4
+ keys.max + 1
5
+ else
6
+ 0
7
+ end
8
+ end
9
+
10
+ def serialize
11
+ if keys.any?
12
+ (0..(length-1)).map {|i| fetch i, 0 }
13
+ else
14
+ []
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,4 @@
1
+ module Exonum
2
+ VERSION = "0.0.1"
3
+ end
4
+
@@ -0,0 +1,41 @@
1
+ require 'exonum'
2
+
3
+ RSpec.describe 'serialization' do
4
+ it "can serialize simple structure" do
5
+ fields = [{name: 'pubkey', type: Exonum::PublicKeyT.new}, { name: 'owner', type: Exonum::StringT.new}, { name: 'balance', type: Exonum::UInt64T.new}]
6
+ data = { 'pubkey' => '99ace6c721db293b0ed5b487e6d6111f22a8c55d2a1b7606b6fa6e6c29671aa1', 'owner' => 'Andrew', 'balance' => 1234 }
7
+ buffer = SparseArray.new
8
+ s = Exonum::StructT.new fields
9
+ s.serialize data, buffer
10
+ expect(buffer.serialize.pack('c*').unpack('H*').first).to eq("99ace6c721db293b0ed5b487e6d6111f22a8c55d2a1b7606b6fa6e6c29671aa13000000006000000d204000000000000416e64726577")
11
+ end
12
+
13
+ it "can serialize array" do
14
+ a=Exonum::ArrayT.new Exonum::Int16T.new
15
+ buffer = SparseArray.new
16
+ a.serialize [1,2,3], buffer
17
+ expect(buffer.serialize.pack('c*').unpack('H*').first).to eq("0000000003000000010002000300")
18
+ end
19
+
20
+ it "can sign a message" do
21
+ secret = "867103771411a6d8e14dd2b037bb5b57ab0add4debdc39147f9d2eae342a388d29823166d18e2471a19b16d261fe329f1228048846c1acea2f370e6a89c7a4d9"
22
+ signature = "46386a5ef9ad0ac5d1e2fe509e3e3bfa27f4f0d376628169df76b5c02f77f8699ed966031a42bbc1a94002c4ec666f4e7d143a481e19eee306a2dfd8280c3d0e"
23
+
24
+ fields = [
25
+ { name: 'pub_key', type: Exonum::PublicKeyT.new },
26
+ { name: 'amount', type: Exonum::UInt64T.new },
27
+ { name: 'seed', type: Exonum::UInt64T.new }
28
+ ]
29
+ data = {
30
+ 'pub_key' => "29823166d18e2471a19b16d261fe329f1228048846c1acea2f370e6a89c7a4d9",
31
+ 'amount' => 10,
32
+ 'seed' => 4645085842425400387
33
+ }
34
+ message = Exonum::MessageT.new 0, 1, 128, Exonum::StructT.new(fields)
35
+ expect(message.sign(secret, data)).to eq(signature)
36
+ end
37
+
38
+ it "can generate seed" do
39
+ expect(Exonum.generate_seed.is_a? Integer).to be true
40
+ end
41
+ end
@@ -0,0 +1,100 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ # rspec-expectations config goes here. You can use an alternate
18
+ # assertion/expectation library such as wrong or the stdlib/minitest
19
+ # assertions if you prefer.
20
+ config.expect_with :rspec do |expectations|
21
+ # This option will default to `true` in RSpec 4. It makes the `description`
22
+ # and `failure_message` of custom matchers include text for helper methods
23
+ # defined using `chain`, e.g.:
24
+ # be_bigger_than(2).and_smaller_than(4).description
25
+ # # => "be bigger than 2 and smaller than 4"
26
+ # ...rather than:
27
+ # # => "be bigger than 2"
28
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
29
+ end
30
+
31
+ # rspec-mocks config goes here. You can use an alternate test double
32
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
33
+ config.mock_with :rspec do |mocks|
34
+ # Prevents you from mocking or stubbing a method that does not exist on
35
+ # a real object. This is generally recommended, and will default to
36
+ # `true` in RSpec 4.
37
+ mocks.verify_partial_doubles = true
38
+ end
39
+
40
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41
+ # have no way to turn it off -- the option exists only for backwards
42
+ # compatibility in RSpec 3). It causes shared context metadata to be
43
+ # inherited by the metadata hash of host groups and examples, rather than
44
+ # triggering implicit auto-inclusion in groups with matching metadata.
45
+ config.shared_context_metadata_behavior = :apply_to_host_groups
46
+
47
+ # The settings below are suggested to provide a good initial experience
48
+ # with RSpec, but feel free to customize to your heart's content.
49
+ =begin
50
+ # This allows you to limit a spec run to individual examples or groups
51
+ # you care about by tagging them with `:focus` metadata. When nothing
52
+ # is tagged with `:focus`, all examples get run. RSpec also provides
53
+ # aliases for `it`, `describe`, and `context` that include `:focus`
54
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
55
+ config.filter_run_when_matching :focus
56
+
57
+ # Allows RSpec to persist some state between runs in order to support
58
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
59
+ # you configure your source control system to ignore this file.
60
+ config.example_status_persistence_file_path = "spec/examples.txt"
61
+
62
+ # Limits the available syntax to the non-monkey patched syntax that is
63
+ # recommended. For more details, see:
64
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
65
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
66
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
67
+ config.disable_monkey_patching!
68
+
69
+ # This setting enables warnings. It's recommended, but in some cases may
70
+ # be too noisy due to issues in dependencies.
71
+ config.warnings = true
72
+
73
+ # Many RSpec users commonly either run the entire suite or an individual
74
+ # file, and it's useful to allow more verbose output when running an
75
+ # individual spec file.
76
+ if config.files_to_run.one?
77
+ # Use the documentation formatter for detailed output,
78
+ # unless a formatter has already been configured
79
+ # (e.g. via a command-line flag).
80
+ config.default_formatter = "doc"
81
+ end
82
+
83
+ # Print the 10 slowest examples and example groups at the
84
+ # end of the spec run, to help surface which specs are running
85
+ # particularly slow.
86
+ config.profile_examples = 10
87
+
88
+ # Run specs in random order to surface order dependencies. If you find an
89
+ # order dependency and want to debug it, you can fix the order by providing
90
+ # the seed, which is printed after each run.
91
+ # --seed 1234
92
+ config.order = :random
93
+
94
+ # Seed global randomization in this process using the `--seed` CLI option.
95
+ # Setting this allows you to use `--seed` to deterministically reproduce
96
+ # test failures related to randomization by passing the same `--seed` value
97
+ # as the one that triggered the failure.
98
+ Kernel.srand config.seed
99
+ =end
100
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: exonum-client-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuri Gomozov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-06-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ed25519
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sparse_array
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">"
67
+ - !ruby/object:Gem::Version
68
+ version: '3'
69
+ description: Light client for Exonum blockchain framework. https://exonum.com
70
+ email:
71
+ - grophen@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - exonum-client-ruby.gemspec
81
+ - lib/exonum.rb
82
+ - lib/exonum/types/array.rb
83
+ - lib/exonum/types/message.rb
84
+ - lib/exonum/types/primitive.rb
85
+ - lib/exonum/types/struct.rb
86
+ - lib/exonum/util/seed.rb
87
+ - lib/exonum/util/sparse_array.rb
88
+ - lib/exonum/version.rb
89
+ - spec/serialization_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: https://github.com/IPINVEST/exonum-client-ruby
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.7.6
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Exonum light clent written in Ruby
115
+ test_files:
116
+ - spec/serialization_spec.rb
117
+ - spec/spec_helper.rb