ciri 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +14 -0
  3. data/.rspec +2 -1
  4. data/.travis.yml +11 -4
  5. data/Gemfile.lock +3 -0
  6. data/README.md +44 -34
  7. data/Rakefile +47 -4
  8. data/ciri.gemspec +13 -12
  9. data/docker/Base +34 -0
  10. data/lib/ciri/actor.rb +223 -0
  11. data/lib/ciri/chain.rb +293 -0
  12. data/lib/ciri/chain/block.rb +47 -0
  13. data/lib/ciri/chain/header.rb +62 -0
  14. data/lib/ciri/chain/transaction.rb +145 -0
  15. data/lib/ciri/crypto.rb +58 -5
  16. data/lib/ciri/db/backend/memory.rb +68 -0
  17. data/lib/ciri/db/backend/rocks.rb +104 -0
  18. data/lib/ciri/db/backend/rocks_db.rb +278 -0
  19. data/lib/ciri/devp2p/peer.rb +10 -2
  20. data/lib/ciri/devp2p/protocol.rb +11 -3
  21. data/lib/ciri/devp2p/protocol_io.rb +6 -3
  22. data/lib/ciri/devp2p/rlpx.rb +1 -0
  23. data/lib/ciri/devp2p/rlpx/encryption_handshake.rb +1 -1
  24. data/lib/ciri/devp2p/rlpx/frame_io.rb +1 -1
  25. data/lib/ciri/devp2p/rlpx/message.rb +4 -4
  26. data/lib/ciri/devp2p/server.rb +14 -13
  27. data/lib/ciri/eth.rb +33 -0
  28. data/lib/ciri/eth/peer.rb +64 -0
  29. data/lib/ciri/eth/protocol_manage.rb +122 -0
  30. data/lib/ciri/eth/protocol_messages.rb +158 -0
  31. data/lib/ciri/eth/synchronizer.rb +188 -0
  32. data/lib/ciri/ethash.rb +123 -0
  33. data/lib/ciri/evm.rb +140 -0
  34. data/lib/ciri/evm/account.rb +50 -0
  35. data/lib/ciri/evm/block_info.rb +31 -0
  36. data/lib/ciri/evm/forks/frontier.rb +183 -0
  37. data/lib/ciri/evm/instruction.rb +92 -0
  38. data/lib/ciri/evm/machine_state.rb +81 -0
  39. data/lib/ciri/evm/op.rb +536 -0
  40. data/lib/ciri/evm/serialize.rb +60 -0
  41. data/lib/ciri/evm/sub_state.rb +64 -0
  42. data/lib/ciri/evm/vm.rb +379 -0
  43. data/lib/ciri/forks.rb +38 -0
  44. data/lib/ciri/forks/frontier.rb +43 -0
  45. data/lib/ciri/key.rb +7 -1
  46. data/lib/ciri/pow.rb +95 -0
  47. data/lib/ciri/rlp.rb +3 -53
  48. data/lib/ciri/rlp/decode.rb +100 -40
  49. data/lib/ciri/rlp/encode.rb +95 -34
  50. data/lib/ciri/rlp/serializable.rb +61 -91
  51. data/lib/ciri/types/address.rb +70 -0
  52. data/lib/ciri/types/errors.rb +36 -0
  53. data/lib/ciri/utils.rb +45 -13
  54. data/lib/ciri/utils/lib_c.rb +46 -0
  55. data/lib/ciri/utils/logger.rb +99 -0
  56. data/lib/ciri/utils/number.rb +67 -0
  57. data/lib/ciri/version.rb +1 -1
  58. metadata +67 -7
  59. data/lib/ciri/devp2p/actor.rb +0 -224
@@ -31,26 +31,78 @@ module Ciri
31
31
  module Crypto
32
32
  extend self
33
33
 
34
- class ECIESDecryptionError < StandardError
34
+ ECIES_CIPHER_NAME = 'aes-128-ctr'
35
+ SECP256K1N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
36
+
37
+ class Error < StandardError
38
+ end
39
+ class ECIESDecryptionError < Error
40
+ end
41
+ class ECDSASignatureError < Error
35
42
  end
36
43
 
37
- ECIES_CIPHER_NAME = 'aes-128-ctr'
44
+ class Signature
45
+ attr_reader :r, :s, :v
46
+
47
+ def initialize(signature: nil, vrs: nil)
48
+ if !!signature == !!vrs
49
+ raise ArgumentError.new("should pass signature_bytes or vrs, but can't provide both together")
50
+ end
51
+
52
+ if signature
53
+ unless signature.size == 65
54
+ raise ECDSASignatureError.new("signature size should be 65, got: #{signature.size}")
55
+ end
56
+
57
+ @r = Utils.big_endian_decode(signature[0...32])
58
+ @s = Utils.big_endian_decode(signature[32...64])
59
+ @v = Utils.big_endian_decode(signature[64])
60
+ else
61
+ @v, @r, @s = vrs
62
+
63
+ unless self.signature.size == 65
64
+ raise ECDSASignatureError.new("vrs is incorrect")
65
+ end
66
+ end
67
+ end
68
+
69
+ def signature
70
+ @signature ||= Utils.big_endian_encode_to_size(@r, "\x00".b, size: 32) +
71
+ Utils.big_endian_encode_to_size(@s, "\x00".b, size: 32) +
72
+ Utils.big_endian_encode(@v, "\x00".b)
73
+ end
74
+
75
+ alias to_s signature
76
+
77
+ def valid?
78
+ v <= 1 &&
79
+ r < SECP256K1N && r >= 1 &&
80
+ s < SECP256K1N && s >= 1
81
+ end
82
+
83
+ def low_s?
84
+ s < (SECP256K1N / 2)
85
+ end
86
+ end
38
87
 
39
88
  def ecdsa_signature(key, data)
40
89
  secp256k1_key = ensure_secp256k1_key(privkey: key)
41
90
  signature, recid = secp256k1_key.ecdsa_recoverable_serialize(secp256k1_key.ecdsa_sign_recoverable(data, raw: true))
42
- signature + Ciri::Utils.big_endian_encode(recid, "\x00")
91
+ Signature.new(signature: signature + Ciri::Utils.big_endian_encode(recid, "\x00".b))
43
92
  end
44
93
 
45
94
  def ecdsa_recover(msg, signature, return_raw_key: true)
95
+ signature = Signature.new(signature: signature) unless signature.is_a?(Signature)
46
96
  pk = Secp256k1::PrivateKey.new(flags: Secp256k1::ALL_FLAGS)
47
- sig, recid = signature[0..-2], Ciri::Utils.big_endian_decode(signature[-1])
97
+ sig, recid = signature.signature[0..-2], signature.v
48
98
 
49
- recsig = pk.ecdsa_recoverable_deserialize(sig, recid)
99
+ recsig = pk.ecdsa_recoverable_deserialize(sig, recid % 4)
50
100
  pubkey = pk.ecdsa_recover(msg, recsig, raw: true)
51
101
 
52
102
  key = Secp256k1::PublicKey.new(pubkey: pubkey)
53
103
  return_raw_key ? key.serialize(compressed: false) : key
104
+ rescue Secp256k1::AssertError => e
105
+ raise ECDSASignatureError.new(e)
54
106
  end
55
107
 
56
108
  def ecies_encrypt(message, raw_pubkey, shared_mac_data = '')
@@ -114,6 +166,7 @@ module Ciri
114
166
  end
115
167
 
116
168
  private
169
+
117
170
  def ecies_kdf(key_material, key_len)
118
171
  s1 = ''.b
119
172
  key = ''.b
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+
24
+ require_relative 'rocks_db'
25
+ require 'forwardable'
26
+
27
+ module Ciri
28
+ module DB
29
+ module Backend
30
+
31
+ # implement kvstore
32
+ class Memory
33
+
34
+ class InvalidError < StandardError
35
+ end
36
+
37
+ extend Forwardable
38
+
39
+ def initialize
40
+ @db = {}
41
+ end
42
+
43
+ def_delegators :@db, :[], :[]=
44
+
45
+ def get(key)
46
+ @db[key]
47
+ end
48
+
49
+ def put(key, value)
50
+ @db[key] = value
51
+ end
52
+
53
+ def each(&blk)
54
+ keys.each(&blk)
55
+ end
56
+
57
+ def close
58
+ @db = nil
59
+ end
60
+
61
+ def closed?
62
+ @db.nil?
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+
24
+ require_relative 'rocks_db'
25
+ require 'forwardable'
26
+
27
+ module Ciri
28
+ module DB
29
+ module Backend
30
+
31
+ # implement kvstore
32
+ class Rocks
33
+
34
+ class InvalidError < StandardError
35
+ end
36
+
37
+ extend Forwardable
38
+
39
+ def initialize(path)
40
+ @db = RocksDB::DB.new(path)
41
+ end
42
+
43
+ def_delegators :db, :get, :put, :[], :[]=
44
+
45
+ def each(&blk)
46
+ inter_each(only_key: false, &blk)
47
+ end
48
+
49
+ def keys(key: nil)
50
+ inter_each(key: key, only_key: true)
51
+ end
52
+
53
+ def scan(key, &blk)
54
+ inter_each(key: key, only_key: false, &blk)
55
+ end
56
+
57
+ def batch
58
+ batch = RocksDB::Batch.new
59
+ yield batch
60
+ db.write(batch)
61
+ self
62
+ end
63
+
64
+ def close
65
+ return if closed?
66
+ db.close
67
+ @db = nil
68
+ end
69
+
70
+ def closed?
71
+ @db.nil?
72
+ end
73
+
74
+ private
75
+
76
+ def db
77
+ @db || raise(InvalidError.new 'db is not open')
78
+ end
79
+
80
+ def inter_each(key: nil, only_key: true, &blk)
81
+ i = db.new_iterator
82
+ key ? i.seek(key) : i.seek_to_first
83
+
84
+ enum = Enumerator.new do |iter|
85
+ while i.valid
86
+ iter << (only_key ? i.key : [i.key, i.value])
87
+ i.next
88
+ end
89
+ ensure
90
+ i.close
91
+ end
92
+
93
+ if blk.nil?
94
+ enum
95
+ else
96
+ enum.each(&blk)
97
+ self
98
+ end
99
+ end
100
+
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,278 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+
24
+ require 'ffi'
25
+
26
+ module Ciri
27
+ module DB
28
+ module Backend
29
+ module RocksDB
30
+
31
+ class Error < StandardError
32
+ end
33
+
34
+ module RocksDBLib
35
+ extend FFI::Library
36
+ ffi_lib 'rocksdb'
37
+
38
+ attach_function :rocksdb_options_create, [], :pointer
39
+ attach_function :rocksdb_options_set_create_if_missing, [:pointer, :int], :void
40
+ attach_function :rocksdb_open, [:pointer, :string, :pointer], :pointer
41
+ attach_function :rocksdb_close, [:pointer], :void
42
+ attach_function :rocksdb_writeoptions_create, [], :pointer
43
+ attach_function :rocksdb_readoptions_create, [], :pointer
44
+ attach_function :rocksdb_writeoptions_destroy, [:pointer], :void
45
+ attach_function :rocksdb_readoptions_destroy, [:pointer], :void
46
+ attach_function :rocksdb_options_destroy, [:pointer], :void
47
+ attach_function :rocksdb_put, [:pointer, :pointer, :pointer, :int, :pointer, :int, :pointer], :void
48
+ attach_function :rocksdb_get, [:pointer, :pointer, :pointer, :int, :pointer, :pointer], :pointer
49
+ attach_function :rocksdb_delete, [:pointer, :pointer, :pointer, :int, :pointer], :void
50
+ attach_function :rocksdb_write, [:pointer, :pointer, :pointer, :pointer], :void
51
+ # iterator
52
+ attach_function :rocksdb_create_iterator, [:pointer, :pointer], :pointer
53
+ attach_function :rocksdb_iter_destroy, [:pointer], :void
54
+ attach_function :rocksdb_iter_valid, [:pointer], :uchar
55
+ attach_function :rocksdb_iter_seek_to_first, [:pointer], :void
56
+ attach_function :rocksdb_iter_seek_to_last, [:pointer], :void
57
+ attach_function :rocksdb_iter_seek, [:pointer, :string, :int], :void
58
+ attach_function :rocksdb_iter_seek_for_prev, [:pointer, :string, :int], :void
59
+ attach_function :rocksdb_iter_next, [:pointer], :void
60
+ attach_function :rocksdb_iter_prev, [:pointer], :void
61
+ attach_function :rocksdb_iter_key, [:pointer, :pointer], :string
62
+ attach_function :rocksdb_iter_value, [:pointer, :pointer], :string
63
+ # batch
64
+ attach_function :rocksdb_writebatch_create, [], :pointer
65
+ attach_function :rocksdb_writebatch_destroy, [:pointer], :void
66
+ attach_function :rocksdb_writebatch_put, [:pointer, :pointer, :int, :pointer, :int], :void
67
+ attach_function :rocksdb_writebatch_delete, [:pointer, :string, :int], :void
68
+ attach_function :rocksdb_writebatch_count, [:pointer], :int
69
+
70
+ class << self
71
+ def open_database(path, options)
72
+ err_ptr = FFI::MemoryPointer.new :string
73
+ db = rocksdb_open(options, path, err_ptr)
74
+ raise_error_from_point(Error, err_ptr)
75
+ db
76
+ end
77
+
78
+ def close_database(db)
79
+ rocksdb_close(db)
80
+ nil
81
+ end
82
+
83
+ def put(db, write_options, key, value)
84
+ err_ptr = FFI::MemoryPointer.new :pointer
85
+ # use pointer to aboid ffi null string issue
86
+ key_ptr = FFI::MemoryPointer.from_string(key)
87
+ value_ptr = FFI::MemoryPointer.from_string(value)
88
+ rocksdb_put(db, write_options, key_ptr, key.size, value_ptr, value.size + 1, err_ptr)
89
+ raise_error_from_point(Error, err_ptr)
90
+ nil
91
+ end
92
+
93
+ def get(db, read_options, key)
94
+ err_ptr = FFI::MemoryPointer.new :pointer
95
+ value_len = FFI::MemoryPointer.new :int
96
+ value_ptr = RocksDBLib.rocksdb_get(db, read_options, key, key.size, value_len, err_ptr)
97
+ raise_error_from_point(Error, err_ptr)
98
+ len = value_len.read_int - 1
99
+ key_exists = len > 0 && !value_ptr.null?
100
+ key_exists ? value_ptr.read_string(len) : nil
101
+ end
102
+
103
+ def delete(db, write_options, key)
104
+ key_ptr = FFI::MemoryPointer.from_string(key)
105
+ err_ptr = FFI::MemoryPointer.new :pointer
106
+ RocksDBLib.rocksdb_delete(db, write_options, key_ptr, key.size, err_ptr)
107
+ raise_error_from_point(Error, err_ptr)
108
+ nil
109
+ end
110
+
111
+ def write(db, write_options, batch)
112
+ err_ptr = FFI::MemoryPointer.new :pointer
113
+ RocksDBLib.rocksdb_write(db, write_options, batch, err_ptr)
114
+ raise_error_from_point(Error, err_ptr)
115
+ nil
116
+ end
117
+
118
+ def writebatch_put(batch, key, value)
119
+ key_ptr = FFI::MemoryPointer.from_string(key)
120
+ value_ptr = FFI::MemoryPointer.from_string(value)
121
+ rocksdb_writebatch_put(batch, key_ptr, key.size, value_ptr, value.size + 1)
122
+ nil
123
+ end
124
+
125
+ def writebatch_delete(batch, key)
126
+ rocksdb_writebatch_delete(batch, key, key.size)
127
+ nil
128
+ end
129
+
130
+ private
131
+
132
+ def raise_error_from_point(error_klass, err_ptr)
133
+ err = err_ptr.get_pointer(0)
134
+ raise error_klass.new(err.read_string_to_null) unless err.null?
135
+ end
136
+ end
137
+ end
138
+
139
+ class Batch
140
+ def initialize
141
+ @batch = RocksDBLib.rocksdb_writebatch_create
142
+ ObjectSpace.define_finalizer(self, self.class.finalizer(@batch))
143
+ end
144
+
145
+ def put(key, value)
146
+ RocksDBLib.writebatch_put(@batch, key, value)
147
+ end
148
+
149
+ def delete(key)
150
+ RocksDBLib.writebatch_delete(@batch, key)
151
+ end
152
+
153
+ def raw_batch
154
+ @batch
155
+ end
156
+
157
+ class << self
158
+ def finalizer(batch)
159
+ proc {
160
+ RocksDBLib.rocksdb_writebatch_destroy(batch)
161
+ }
162
+ end
163
+ end
164
+ end
165
+
166
+ class Iterator
167
+ def initialize(db, readoptions)
168
+ @iter = RocksDBLib.rocksdb_create_iterator(db, readoptions)
169
+ end
170
+
171
+ def valid
172
+ RocksDBLib.rocksdb_iter_valid(@iter) == 1
173
+ end
174
+
175
+ def seek_to_first
176
+ RocksDBLib.rocksdb_iter_seek_to_first(@iter)
177
+ nil
178
+ end
179
+
180
+ def seek_to_last
181
+ RocksDBLib.rocksdb_iter_seek_to_last(@iter)
182
+ nil
183
+ end
184
+
185
+ def seek(key)
186
+ RocksDBLib.rocksdb_iter_seek(@iter, key, key.size)
187
+ nil
188
+ end
189
+
190
+ def seek_for_prev(key)
191
+ RocksDBLib.rocksdb_iter_seek_for_prev(@iter, key, key.size)
192
+ nil
193
+ end
194
+
195
+ def next
196
+ RocksDBLib.rocksdb_iter_next(@iter)
197
+ nil
198
+ end
199
+
200
+ def prev
201
+ RocksDBLib.rocksdb_iter_prev(@iter)
202
+ nil
203
+ end
204
+
205
+ def key
206
+ len_ptr = FFI::MemoryPointer.new :int
207
+ key = RocksDBLib.rocksdb_iter_key(@iter, len_ptr)
208
+ len = len_ptr.read_int
209
+ key[0...len]
210
+ end
211
+
212
+ def value
213
+ len_ptr = FFI::MemoryPointer.new :int
214
+ value = RocksDBLib.rocksdb_iter_value(@iter, len_ptr)
215
+ len = len_ptr.read_int
216
+ value[0...len]
217
+ end
218
+
219
+ def close
220
+ RocksDBLib.rocksdb_iter_destroy(@iter)
221
+ end
222
+ end
223
+
224
+ class DB
225
+ def initialize(path)
226
+ options = RocksDBLib.rocksdb_options_create
227
+ RocksDBLib.rocksdb_options_set_create_if_missing(options, 1)
228
+ @db = RocksDBLib.open_database(path, options)
229
+ @writeoptions = RocksDBLib.rocksdb_writeoptions_create
230
+ @readoptions = RocksDBLib.rocksdb_readoptions_create
231
+ ObjectSpace.define_finalizer(self, self.class.finalizer(@db, options, @writeoptions, @readoptions))
232
+ end
233
+
234
+ def get(key)
235
+ RocksDBLib.get(@db, @readoptions, key)
236
+ end
237
+
238
+ alias [] get
239
+
240
+ def put(key, value)
241
+ RocksDBLib.put(@db, @writeoptions, key, value)
242
+ end
243
+
244
+ alias []= put
245
+
246
+ def new_iterator
247
+ Iterator.new(@db, @readoptions)
248
+ end
249
+
250
+ def close
251
+ RocksDBLib.close_database(@db) if @db
252
+ @db = nil
253
+ end
254
+
255
+ def closed?
256
+ @db.nil?
257
+ end
258
+
259
+ def write(batch)
260
+ RocksDBLib.write(@db, @writeoptions, batch.raw_batch)
261
+ end
262
+
263
+ class << self
264
+ def finalizer(db, options, write_options, read_options)
265
+ proc {
266
+ # RocksDBLib.close_database(db)
267
+ RocksDBLib.rocksdb_options_destroy(options)
268
+ RocksDBLib.rocksdb_writeoptions_destroy(write_options)
269
+ RocksDBLib.rocksdb_readoptions_destroy(read_options)
270
+ }
271
+ end
272
+ end
273
+ end
274
+
275
+ end
276
+ end
277
+ end
278
+ end