exonum-client-ruby 0.0.1

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,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