xrbp 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/nodestore1.rb +13 -8
- data/examples/nodestore2.rb +7 -2
- data/examples/sandbox.rb +13 -0
- data/lib/xrbp/nodestore/backends/decompressor.rb +197 -0
- data/lib/xrbp/nodestore/backends/nudb.rb +78 -1
- data/lib/xrbp/nodestore/backends/rocksdb.rb +1 -0
- data/lib/xrbp/nodestore/db.rb +3 -0
- data/lib/xrbp/nodestore/format.rb +8 -0
- data/lib/xrbp/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a8b3814b38bdb314bd9c69b5d9f3363b4f0a090f6d41a5849516cc1638d5abe
|
4
|
+
data.tar.gz: fc1ba94351b215389efaacb5013bfa9498a269cf12d7fde3e6958a5fb3f6273a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8e9e87bc83b3bd361bef7d1deffd87c7637285e15fca3bb5b25f87b34091ebb792137178b06c71d8ac1566a75aadf5ed74fe85d1fc414c5070edecfddce78d4
|
7
|
+
data.tar.gz: 8e8cbea5804ff5f852584be3a699caee69169ad3563bb2a0696e8a3ea9492faa89ae937138bb64c7b65804adc72f49f24538659b85a018b2444b038c4b0b0558
|
data/examples/nodestore1.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
$: << File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'xrbp'
|
3
|
-
require 'xrbp/nodestore/backends/rocksdb'
|
4
3
|
|
5
|
-
|
4
|
+
# for rocksdb:
|
5
|
+
#require 'xrbp/nodestore/backends/rocksdb'
|
6
|
+
#db = XRBP::NodeStore::Backends::RocksDB.new "/home/mmorsi/rippledb/rocksdb/rippledb.beb0"
|
6
7
|
|
7
|
-
#
|
8
|
-
|
9
|
-
|
8
|
+
# for nudb:
|
9
|
+
require 'xrbp/nodestore/backends/nudb'
|
10
|
+
db = XRBP::NodeStore::Backends::NuDB.new "/var/lib/rippled/nudb/"
|
11
|
+
|
12
|
+
ledger = "1B927880277CCF943CB4F6BF57A9BCE48F9583A3DD8EEE9A068D63FB6CD99714"
|
13
|
+
ledger = [ledger].pack("H*")
|
14
|
+
puts db.ledger(ledger)
|
10
15
|
|
11
16
|
#account = "0001bf7468341666f1f47a95e0f4d88e68b5fc7d20d77437cb22954fbbfe6127"
|
12
|
-
account = "02c46b3a4130d0a329c47f0da61b829aa5d1ae53c5817e475bcd794e5107be44"
|
13
|
-
account = [account].pack("H*")
|
14
|
-
puts db.account(account)
|
17
|
+
#account = "02c46b3a4130d0a329c47f0da61b829aa5d1ae53c5817e475bcd794e5107be44"
|
18
|
+
#account = [account].pack("H*")
|
19
|
+
#puts db.account(account)
|
data/examples/nodestore2.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
$: << File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'xrbp'
|
3
|
-
require 'xrbp/nodestore/backends/rocksdb'
|
4
3
|
|
5
|
-
|
4
|
+
# for rocksdb:
|
5
|
+
#require 'xrbp/nodestore/backends/rocksdb'
|
6
|
+
#db = XRBP::NodeStore::Backends::RocksDB.new "/home/mmorsi/rippledb/rocksdb/rippledb.beb0"
|
7
|
+
|
8
|
+
# for nudb:
|
9
|
+
require 'xrbp/nodestore/backends/nudb'
|
10
|
+
db = XRBP::NodeStore::Backends::NuDB.new "/var/lib/rippled/nudb/"
|
6
11
|
|
7
12
|
db.on :unknown do |hash, node|
|
8
13
|
puts "Unknown #{hash}: #{node}"
|
data/examples/sandbox.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$: << File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'xrbp'
|
3
|
+
require 'xrbp/nodestore/backends/nudb'
|
4
|
+
|
5
|
+
db = XRBP::NodeStore::Backends::NuDB.new "/var/lib/rippled/nudb/"
|
6
|
+
store = db.instance_variable_get(:@store)
|
7
|
+
|
8
|
+
key = [173, 159, 139, 114, 152, 207, 218, 221, 216, 149, 123, 11, 7, 224, 137, 139, 4, 190, 176, 89, 215, 228, 145, 13, 7, 45, 165, 249, 162, 83, 43, 241].pack("C*")
|
9
|
+
val = store.fetch(key).first
|
10
|
+
puts val.unpack("C*").join " "
|
11
|
+
decompressed = db.send(:decompress, val)
|
12
|
+
puts decompressed.unpack("C*").join " "
|
13
|
+
type, obj = db.send(:infer_type, decompressed)
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# requires lz4-ruby gem
|
2
|
+
require 'lz4-ruby'
|
3
|
+
|
4
|
+
module XRBP
|
5
|
+
module NodeStore
|
6
|
+
module Backends
|
7
|
+
# Ported from:
|
8
|
+
# https://github.com/ripple/rippled/blob/develop/src/ripple/nodestore/impl/codec.h
|
9
|
+
module Decompressor
|
10
|
+
protected
|
11
|
+
def decompress(data)
|
12
|
+
type, remaining = read_varint(data)
|
13
|
+
case(type)
|
14
|
+
when 0
|
15
|
+
remaining # uncompressed
|
16
|
+
when 1
|
17
|
+
decompress_lz4 remaining
|
18
|
+
when 2
|
19
|
+
decompress_compressed_v1_inner remaining
|
20
|
+
when 3
|
21
|
+
decompress_full_v1_inner remaining
|
22
|
+
when 5
|
23
|
+
decompress_compressed_v2_inner remaining
|
24
|
+
when 6
|
25
|
+
decompress_full_v2_inner remaining
|
26
|
+
|
27
|
+
else
|
28
|
+
raise "nodeobject codec: bad type=#{type}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
# https://github.com/ripple/rippled/blob/develop/src/ripple/nodestore/impl/varint.h
|
34
|
+
def read_varint(data)
|
35
|
+
bytes = data.bytes
|
36
|
+
|
37
|
+
t = 0
|
38
|
+
n = 0
|
39
|
+
while(bytes[n] & 0x80) != 0
|
40
|
+
n += 1
|
41
|
+
if n >= bytes.size
|
42
|
+
return t, data
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if (n += 1) >= bytes.size
|
47
|
+
return t, data
|
48
|
+
end
|
49
|
+
|
50
|
+
if n == 1 && bytes[0] == 0
|
51
|
+
return t, data[1..-1]
|
52
|
+
end
|
53
|
+
|
54
|
+
used = n
|
55
|
+
while(n -= 1) >= 0
|
56
|
+
d = bytes[n]
|
57
|
+
t0 = t
|
58
|
+
t *= 127
|
59
|
+
t += d & 0x7F
|
60
|
+
if t <= t0 # overflow
|
61
|
+
return t, data
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
return t, data[used..-1]
|
66
|
+
end
|
67
|
+
|
68
|
+
###
|
69
|
+
|
70
|
+
def decompress_lz4(data)
|
71
|
+
size, remaining = read_varint(data)
|
72
|
+
o = LZ4::Raw::decompress(remaining, size)[0]
|
73
|
+
o
|
74
|
+
end
|
75
|
+
|
76
|
+
###
|
77
|
+
|
78
|
+
def decompress_compressed_v1_inner(data)
|
79
|
+
raise if data.size < 34
|
80
|
+
|
81
|
+
out = [0, 0, 0, 0,
|
82
|
+
0, 0, 0, 0,
|
83
|
+
Format::NODE_OBJ_TYPES[:unknown]] +
|
84
|
+
[Format::HASH_PREFIXES.invert[:inner_node]].pack("H*")
|
85
|
+
.unpack("C*")
|
86
|
+
|
87
|
+
bytes = data.bytes
|
88
|
+
mask = bytes[0..1].pack("C*").unpack("S").first
|
89
|
+
bytes = bytes[2..-1]
|
90
|
+
|
91
|
+
raise "nodeobject codec v1: empty inner node" if mask == 0
|
92
|
+
|
93
|
+
bit = 0x8000
|
94
|
+
i = 16
|
95
|
+
while i > 0
|
96
|
+
i -= 1
|
97
|
+
|
98
|
+
if (mask & bit) != 0
|
99
|
+
raise "nodeobject codec v1: short inner node" if bytes.size < 32
|
100
|
+
|
101
|
+
out += bytes[0..31]
|
102
|
+
bytes = bytes[32..-1]
|
103
|
+
|
104
|
+
else
|
105
|
+
out += Array.new(32) { 0 }
|
106
|
+
end
|
107
|
+
|
108
|
+
bit = bit >> 1
|
109
|
+
end
|
110
|
+
|
111
|
+
out.pack("C*")
|
112
|
+
end
|
113
|
+
|
114
|
+
def decompress_compressed_v2_inner(data)
|
115
|
+
raise if data.size < 67
|
116
|
+
|
117
|
+
out = [0, 0, 0, 0,
|
118
|
+
0, 0, 0, 0,
|
119
|
+
Format::NODE_OBJ_TYPES[:unknown]] +
|
120
|
+
[Format::HASH_PREFIXES.invert[:inner_node_v2]].pack("H*")
|
121
|
+
.unpack("C*")
|
122
|
+
|
123
|
+
bytes = data.bytes
|
124
|
+
mask = bytes[0..1].pack("C*").unpack("S").first
|
125
|
+
bytes = bytes[2..-1]
|
126
|
+
|
127
|
+
raise "nodeobject codec v2: empty inner node" if mask == 0
|
128
|
+
|
129
|
+
depth = bytes[0]
|
130
|
+
bytes = bytes[1..-1]
|
131
|
+
|
132
|
+
bit = 0x8000
|
133
|
+
i = 16
|
134
|
+
while i > 0
|
135
|
+
i -= 1
|
136
|
+
|
137
|
+
if (mask & bit) != 0
|
138
|
+
raise "nodeobject codec v1: short inner node" if bytes.size < 32
|
139
|
+
|
140
|
+
out += bytes[0..31]
|
141
|
+
bytes = bytes[32..-1]
|
142
|
+
|
143
|
+
else
|
144
|
+
out += Array.new(32) { 0 }
|
145
|
+
end
|
146
|
+
|
147
|
+
bit = bit >> 1
|
148
|
+
end
|
149
|
+
|
150
|
+
out << depth
|
151
|
+
|
152
|
+
copy = (depth + 1)/2
|
153
|
+
raise "nodeobject codec v2: short inner node" if bytes.size < copy
|
154
|
+
out += bytes[0...copy]
|
155
|
+
bytes = bytes[copy..-1]
|
156
|
+
raise "nodeobject codec v2: long inner node" if bytes.size > 0
|
157
|
+
|
158
|
+
out.pack("C*")
|
159
|
+
end
|
160
|
+
|
161
|
+
###
|
162
|
+
|
163
|
+
def decompress_full_v1_inner(data)
|
164
|
+
raise if data.size != 512 # 16 32-bit hashes
|
165
|
+
|
166
|
+
out = [0, 0, 0, 0,
|
167
|
+
0, 0, 0, 0,
|
168
|
+
Format::NODE_OBJ_TYPES[:unknown]] +
|
169
|
+
[Format::HASH_PREFIXES.invert[:inner_node]].pack("H*").unpack("C*")
|
170
|
+
(out + data[0...512].bytes).pack("C*")
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def decompress_full_v2_inner(data)
|
175
|
+
bytes = data.bytes
|
176
|
+
depth = bytes[0]
|
177
|
+
bytes = bytes[1..-1]
|
178
|
+
copy = (depth + 1)/2
|
179
|
+
|
180
|
+
raise if bytes.size != 512 + copy # 16 32-bit hashes + copy
|
181
|
+
|
182
|
+
out = [0, 0, 0, 0,
|
183
|
+
0, 0, 0, 0,
|
184
|
+
Format::NODE_OBJ_TYPES[:unknown]] +
|
185
|
+
[Format::HASH_PREFIXES.invert[:inner_node_v2]].pack("H*").unpack("C*")
|
186
|
+
|
187
|
+
out += bytes[0..511]
|
188
|
+
bytes = bytes[512..-1]
|
189
|
+
out << depth
|
190
|
+
out += bytes[0...copy]
|
191
|
+
|
192
|
+
out.pack("C*")
|
193
|
+
end
|
194
|
+
end # module Decompressor
|
195
|
+
end # module Backends
|
196
|
+
end # module NodeStore
|
197
|
+
end # module XRBP
|
@@ -1 +1,78 @@
|
|
1
|
-
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
# requires rrudb gem
|
4
|
+
require "rudb"
|
5
|
+
|
6
|
+
require_relative './decompressor'
|
7
|
+
|
8
|
+
module XRBP
|
9
|
+
module NodeStore
|
10
|
+
module Backends
|
11
|
+
class NuDB < DB
|
12
|
+
include Decompressor
|
13
|
+
|
14
|
+
attr_reader :path
|
15
|
+
|
16
|
+
KEY_SIZE = 32
|
17
|
+
|
18
|
+
def initialize(path)
|
19
|
+
@path = path
|
20
|
+
create!
|
21
|
+
open
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
decompress(@store.fetch(key)[0])
|
26
|
+
end
|
27
|
+
|
28
|
+
def each
|
29
|
+
dat = File.join(path, "nudb.dat")
|
30
|
+
|
31
|
+
RuDB::each(dat) do |key, val|
|
32
|
+
val = decompress(val)
|
33
|
+
type, obj = infer_type(val)
|
34
|
+
|
35
|
+
if type
|
36
|
+
emit type, key, obj
|
37
|
+
else
|
38
|
+
emit :unknown, key, val
|
39
|
+
end
|
40
|
+
|
41
|
+
# 'mock' iterator
|
42
|
+
iterator = OpenStruct.new(:key => key,
|
43
|
+
:value => val)
|
44
|
+
yield iterator
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def create!
|
51
|
+
dat = File.join(path, "nudb.dat")
|
52
|
+
key = File.join(path, "nudb.key")
|
53
|
+
log = File.join(path, "nudb.log")
|
54
|
+
|
55
|
+
RuDB::create :dat_path => dat,
|
56
|
+
:key_path => key,
|
57
|
+
:log_path => log,
|
58
|
+
:app_num => 1,
|
59
|
+
:salt => RuDB::make_salt,
|
60
|
+
:key_size => KEY_SIZE,
|
61
|
+
:block_size => RuDB::block_size(key),
|
62
|
+
:load_factor => 0.5
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
def open
|
68
|
+
dat = File.join(path, "nudb.dat")
|
69
|
+
key = File.join(path, "nudb.key")
|
70
|
+
log = File.join(path, "nudb.log")
|
71
|
+
|
72
|
+
@store = RuDB::Store.new
|
73
|
+
@store.open(dat, key, log)
|
74
|
+
end
|
75
|
+
end # class NuDB
|
76
|
+
end # module Backends
|
77
|
+
end # module NodeStore
|
78
|
+
end # module XRBP
|
data/lib/xrbp/nodestore/db.rb
CHANGED
@@ -7,6 +7,8 @@ module XRBP
|
|
7
7
|
include Enumerable
|
8
8
|
include EventEmitter
|
9
9
|
|
10
|
+
# TODO return nil if db lookup not found
|
11
|
+
|
10
12
|
def ledger(hash)
|
11
13
|
parse_ledger(self[hash])
|
12
14
|
end
|
@@ -258,6 +260,7 @@ module XRBP
|
|
258
260
|
sha256 = OpenSSL::Digest::SHA256.new
|
259
261
|
digest = sha256.digest(sha256.digest(acct))[0..3]
|
260
262
|
acct += digest
|
263
|
+
acct.force_encoding(Encoding::BINARY) # required for Base58 gem
|
261
264
|
return Base58.binary_to_base58(acct, :ripple), data[vl..-1]
|
262
265
|
end
|
263
266
|
|
@@ -3,6 +3,13 @@ require "bistro"
|
|
3
3
|
module XRBP
|
4
4
|
module NodeStore
|
5
5
|
module Format
|
6
|
+
NODE_OBJ_TYPES = {
|
7
|
+
:unknown => 0,
|
8
|
+
:ledger => 1,
|
9
|
+
:account_node => 2,
|
10
|
+
:transaction_node => 3
|
11
|
+
}
|
12
|
+
|
6
13
|
NODE_TYPES = {
|
7
14
|
1 => :ledger,
|
8
15
|
2 => :tx,
|
@@ -15,6 +22,7 @@ module XRBP
|
|
15
22
|
"534E4400" => :tx_node,
|
16
23
|
"4D4C4E00" => :leaf_node,
|
17
24
|
"4D494E00" => :inner_node,
|
25
|
+
"494E5200" => :inner_node_v2,
|
18
26
|
"4C575200" => :ledger_master,
|
19
27
|
"53545800" => :tx_sign,
|
20
28
|
"56414C00" => :validation,
|
data/lib/xrbp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xrbp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dev Null Productions
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -196,6 +196,7 @@ files:
|
|
196
196
|
- examples/paginate.rb
|
197
197
|
- examples/prioritized.rb
|
198
198
|
- examples/round_robin.rb
|
199
|
+
- examples/sandbox.rb
|
199
200
|
- examples/username.rb
|
200
201
|
- examples/validator.rb
|
201
202
|
- examples/websocket.rb
|
@@ -228,6 +229,7 @@ files:
|
|
228
229
|
- lib/xrbp/model/parsers/validator.rb
|
229
230
|
- lib/xrbp/model/validator.rb
|
230
231
|
- lib/xrbp/nodestore.rb
|
232
|
+
- lib/xrbp/nodestore/backends/decompressor.rb
|
231
233
|
- lib/xrbp/nodestore/backends/nudb.rb
|
232
234
|
- lib/xrbp/nodestore/backends/rocksdb.rb
|
233
235
|
- lib/xrbp/nodestore/db.rb
|