xrbp 0.1.5 → 0.1.6
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.
- 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
|