xrbp 0.2.2 → 0.2.3
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 +3 -1
- data/lib/xrbp/common.rb +6 -0
- data/lib/xrbp/core_ext.rb +21 -0
- data/lib/xrbp/nodestore/format.rb +76 -26
- data/lib/xrbp/nodestore/ledger.rb +46 -14
- data/lib/xrbp/nodestore/parser.rb +47 -14
- data/lib/xrbp/nodestore/protocol/indexes.rb +11 -8
- data/lib/xrbp/nodestore/protocol/issue.rb +15 -0
- data/lib/xrbp/nodestore/protocol/rate.rb +13 -1
- data/lib/xrbp/nodestore/shamap/node_factory.rb +6 -1
- data/lib/xrbp/nodestore/shamap/node_id.rb +2 -2
- data/lib/xrbp/nodestore/sle/st_amount.rb +46 -181
- data/lib/xrbp/nodestore/sle/st_amount_arithmatic.rb +126 -0
- data/lib/xrbp/nodestore/sle/st_amount_comparison.rb +49 -0
- data/lib/xrbp/nodestore/sle/st_amount_conversion.rb +203 -0
- data/lib/xrbp/nodestore/sqldb.rb +69 -4
- data/lib/xrbp/overlay/handshake.rb +1 -1
- data/lib/xrbp/version.rb +1 -1
- data/spec/xrbp/crypto/account_spec.rb +7 -2
- data/spec/xrbp/nodestore/amendments_spec.rb +11 -0
- data/spec/xrbp/nodestore/db_parser.rb +64 -1
- data/spec/xrbp/nodestore/fees_spec.rb +3 -0
- data/spec/xrbp/nodestore/ledger_access.rb +87 -2
- data/spec/xrbp/nodestore/protocol/indexes_spec.rb +43 -0
- data/spec/xrbp/nodestore/protocol/rate_spec.rb +12 -0
- data/spec/xrbp/nodestore/shamap/inner_node_spec.rb +44 -0
- data/spec/xrbp/nodestore/shamap/node_factory_spec.rb +9 -0
- data/spec/xrbp/nodestore/shamap/node_id_spec.rb +6 -0
- data/spec/xrbp/nodestore/shamap/node_spec.rb +25 -0
- data/spec/xrbp/nodestore/shamap_spec.rb +144 -0
- data/spec/xrbp/nodestore/sle/st_amount_arithmatic_spec.rb +7 -0
- data/spec/xrbp/nodestore/sle/st_amount_comparison_spec.rb +11 -0
- data/spec/xrbp/nodestore/sle/st_amount_conversion_spec.rb +64 -0
- data/spec/xrbp/nodestore/sle/st_amount_spec.rb +47 -0
- data/spec/xrbp/nodestore/sle/st_ledger_entry_spec.rb +5 -0
- data/spec/xrbp/nodestore/sle/st_object_spec.rb +29 -0
- metadata +20 -2
@@ -8,9 +8,24 @@ module XRBP
|
|
8
8
|
@account = account
|
9
9
|
end
|
10
10
|
|
11
|
+
def to_h
|
12
|
+
{:currency => currency, :account => account}
|
13
|
+
end
|
14
|
+
|
11
15
|
def xrp?
|
12
16
|
self == NodeStore.xrp_issue
|
13
17
|
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
c = currency == NodeStore.no_currency ? '' :
|
21
|
+
currency == NodeStore.xrp_currency ? 'XRP' :
|
22
|
+
"#{currency}"
|
23
|
+
|
24
|
+
a = account == Crypto.no_account ? '' :
|
25
|
+
account == Crypto.xrp_account ? '' :
|
26
|
+
"@#{account}"
|
27
|
+
"#{c}#{a}"
|
28
|
+
end
|
14
29
|
end # class Issue
|
15
30
|
|
16
31
|
def self.xrp_issue
|
@@ -1,5 +1,16 @@
|
|
1
1
|
module XRBP
|
2
2
|
module NodeStore
|
3
|
+
# Represents a transfer rate.
|
4
|
+
#
|
5
|
+
# The percent of an amount sent that is charged
|
6
|
+
# to the sender and paid to the issuer.
|
7
|
+
#
|
8
|
+
# https://xrpl.org/transfer-fees.html
|
9
|
+
#
|
10
|
+
# From rippled docs:
|
11
|
+
# Transfer rates are specified as fractions of 1 billion.
|
12
|
+
# For example, a transfer rate of 1% is represented as
|
13
|
+
# 1,010,000,000.
|
3
14
|
class Rate
|
4
15
|
attr_reader :rate
|
5
16
|
|
@@ -7,12 +18,13 @@ module XRBP
|
|
7
18
|
@rate = rate
|
8
19
|
end
|
9
20
|
|
21
|
+
# Rate signifying a 1:1 exchange
|
10
22
|
def self.parity
|
11
23
|
@parity ||= Rate.new(QUALITY_ONE)
|
12
24
|
end
|
13
25
|
|
14
26
|
def to_amount
|
15
|
-
STAmount.new :issue =>
|
27
|
+
STAmount.new :issue => NodeStore.no_issue,
|
16
28
|
:mantissa => rate,
|
17
29
|
:exponent => -9
|
18
30
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module XRBP
|
2
2
|
class SHAMap
|
3
3
|
module NodeFactory
|
4
|
+
# Create a new node whose type is specified in the binary prefix.
|
5
|
+
#
|
4
6
|
# See rippled::SHAMapAbstractNode::make
|
5
7
|
def make(node, seq, format, hash, hash_valid)
|
6
8
|
node_id = NodeID.new
|
@@ -22,6 +24,7 @@ module XRBP
|
|
22
24
|
|
23
25
|
s = node[4..-1]
|
24
26
|
|
27
|
+
# Transaction node (no metadata)
|
25
28
|
if prefix == NodeStore::Format::HASH_PREFIXES[:tx_id]
|
26
29
|
sha512 = OpenSSL::Digest::SHA512.new
|
27
30
|
sha512 << NodeStore::Format::HASH_PREFIXES[:tx_id]
|
@@ -38,6 +41,7 @@ module XRBP
|
|
38
41
|
|
39
42
|
return TreeNode.new(tree_node)
|
40
43
|
|
44
|
+
# Leaf node in state tree containing data (account info, order, etc)
|
41
45
|
elsif prefix == NodeStore::Format::HASH_PREFIXES[:leaf_node]
|
42
46
|
raise "short PLN node" if s.size < 32
|
43
47
|
|
@@ -55,6 +59,7 @@ module XRBP
|
|
55
59
|
|
56
60
|
return TreeNode.new(tree_node)
|
57
61
|
|
62
|
+
# Inner tree node referencing other nodes
|
58
63
|
elsif (prefix == NodeStore::Format::HASH_PREFIXES[:inner_node]) ||
|
59
64
|
(prefix == NodeStore::Format::HASH_PREFIXES[:inner_node_v2])
|
60
65
|
len = s.size
|
@@ -89,8 +94,8 @@ module XRBP
|
|
89
94
|
|
90
95
|
return ret
|
91
96
|
|
97
|
+
# Transaction node (with metadata)
|
92
98
|
elsif prefix == NodeStore::Format::HASH_PREFIXES[:tx_node]
|
93
|
-
# transaction with metadata
|
94
99
|
raise "short TXN node" if s.size < 32
|
95
100
|
|
96
101
|
tx_id = s[-32..-1]
|
@@ -20,7 +20,7 @@ module XRBP
|
|
20
20
|
# Used to calculate inner node hash for
|
21
21
|
# tree level:
|
22
22
|
# inner node = lookup key & mask
|
23
|
-
def masks
|
23
|
+
def self.masks
|
24
24
|
@masks ||= begin
|
25
25
|
masks = Array.new(MASK_SIZE)
|
26
26
|
|
@@ -41,7 +41,7 @@ module XRBP
|
|
41
41
|
|
42
42
|
# Return mask for current tree depth
|
43
43
|
def mask
|
44
|
-
@mask ||= masks[depth]
|
44
|
+
@mask ||= self.class.masks[depth]
|
45
45
|
end
|
46
46
|
|
47
47
|
# Return branch number of specified hash.
|
@@ -1,9 +1,37 @@
|
|
1
|
+
require_relative './st_amount_arithmatic'
|
2
|
+
require_relative './st_amount_comparison'
|
3
|
+
require_relative './st_amount_conversion'
|
4
|
+
|
1
5
|
module XRBP
|
2
6
|
module NodeStore
|
3
|
-
# Serialized Amount Representation
|
7
|
+
# Serialized Amount Representation.
|
8
|
+
#
|
9
|
+
# From rippled docs:
|
10
|
+
# Internal form:
|
11
|
+
# 1: If amount is zero, then value is zero and offset is -100
|
12
|
+
# 2: Otherwise:
|
13
|
+
# legal offset range is -96 to +80 inclusive
|
14
|
+
# value range is 10^15 to (10^16 - 1) inclusive
|
15
|
+
# amount = value * [10 ^ offset]
|
16
|
+
#
|
17
|
+
# Wire form:
|
18
|
+
# High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
|
19
|
+
# Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
|
4
20
|
class STAmount
|
5
|
-
|
6
|
-
|
21
|
+
include Arithmatic
|
22
|
+
include Comparison
|
23
|
+
include Conversion
|
24
|
+
|
25
|
+
# DEFINES FROM STAmount.h
|
26
|
+
|
27
|
+
MIN_OFFSET = -96
|
28
|
+
MAX_OFFSET = 80
|
29
|
+
|
30
|
+
MIN_VAL = 1000000000000000
|
31
|
+
MAX_VAL = 9999999999999999
|
32
|
+
NOT_NATIVE = 0x8000000000000000
|
33
|
+
POS_NATIVE = 0x4000000000000000
|
34
|
+
MAX_NATIVE = 100000000000000000
|
7
35
|
|
8
36
|
attr_reader :mantissa, :exponent, :neg
|
9
37
|
attr_accessor :issue
|
@@ -19,7 +47,8 @@ module XRBP
|
|
19
47
|
return STAmount.new(:issue => NodeStore.no_issue) if rate == 0
|
20
48
|
|
21
49
|
mantissa = rate & ~(255 << (64 - 8))
|
22
|
-
|
50
|
+
|
51
|
+
exponent = (rate >> (64 - 8)).to_int32 - 100
|
23
52
|
|
24
53
|
return STAmount.new(:issue => NodeStore.no_issue,
|
25
54
|
:mantissa => mantissa,
|
@@ -31,195 +60,31 @@ module XRBP
|
|
31
60
|
@mantissa = args[:mantissa] || 0
|
32
61
|
@exponent = args[:exponent] || 0
|
33
62
|
@neg = !!args[:neg]
|
34
|
-
end
|
35
63
|
|
36
|
-
|
37
|
-
@issue.xrp?
|
38
|
-
end
|
39
|
-
|
40
|
-
def zero?
|
41
|
-
@mantissa == 0
|
42
|
-
end
|
43
|
-
|
44
|
-
def clear
|
45
|
-
# see: https://github.com/ripple/rippled/blob/b53fda1e1a7f4d09b766724274329df1c29988ab/src/ripple/protocol/STAmount.h#L224
|
46
|
-
@exponent = native? ? 0 : -100
|
47
|
-
|
48
|
-
@neg = false
|
49
|
-
@mantissa = 0
|
50
|
-
end
|
51
|
-
|
52
|
-
def negate!
|
53
|
-
return if zero?
|
54
|
-
@neg = !@neg
|
55
|
-
end
|
56
|
-
|
57
|
-
def sn_value
|
58
|
-
neg ? (-mantissa) : mantissa
|
64
|
+
canonicalize
|
59
65
|
end
|
60
66
|
|
61
67
|
###
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
neg ? (-value) : value
|
66
|
-
end
|
67
|
-
|
68
|
-
alias :drops :xrp_amount
|
69
|
-
|
70
|
-
def iou_amount
|
71
|
-
(neg ? -1 : 1) * mantissa * 10 ** (exponent-97)
|
72
|
-
end
|
73
|
-
|
74
|
-
###
|
75
|
-
|
76
|
-
def +(v)
|
77
|
-
e1 = exponent
|
78
|
-
e2 = v.exponent
|
79
|
-
|
80
|
-
m1 = mantissa
|
81
|
-
m2 = v.mantissa
|
82
|
-
|
83
|
-
m1 *= -1 if neg
|
84
|
-
m2 *= -1 if v.neg
|
85
|
-
|
86
|
-
while e1 < e2
|
87
|
-
m1 /= 10
|
88
|
-
e1 += 1
|
89
|
-
end
|
90
|
-
|
91
|
-
while e2 < e1
|
92
|
-
m2 /= 10
|
93
|
-
e2 += 1
|
94
|
-
end
|
95
|
-
|
96
|
-
m = m1 + m2
|
97
|
-
return STAmount.new :issue => issue if m >= -10 && m <= 10
|
98
|
-
return STAmount.new :mantissa => m,
|
99
|
-
:exponent => e1,
|
100
|
-
:issue => issue if m >= 0
|
101
|
-
return STAmount.new :mantissa => -m,
|
102
|
-
:exponent => e1,
|
103
|
-
:issue => issue
|
104
|
-
end
|
105
|
-
|
106
|
-
def -(v)
|
107
|
-
self + (-v)
|
108
|
-
end
|
109
|
-
|
110
|
-
def /(v)
|
111
|
-
if v.is_a?(Rate)
|
112
|
-
return self if v == Rate.parity
|
113
|
-
return self / v.to_amount
|
114
|
-
end
|
115
|
-
|
116
|
-
raise "divide by zero" if v.zero?
|
117
|
-
return STAmount.new :issue => issue
|
118
|
-
|
119
|
-
nm = mantissa
|
120
|
-
dm = v.mantissa
|
121
|
-
|
122
|
-
ne = exponent
|
123
|
-
de = v.exponent
|
124
|
-
|
125
|
-
if native?
|
126
|
-
while nm < MIN_VAL
|
127
|
-
nm *= 10
|
128
|
-
ne -= 1
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
if v.native?
|
133
|
-
while dm < MIN_VAL
|
134
|
-
dm *= 10
|
135
|
-
de -= 1
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# see note: https://github.com/ripple/rippled/blob/b53fda1e1a7f4d09b766724274329df1c29988ab/src/ripple/protocol/impl/STAmount.cpp#L1075
|
140
|
-
STAmount.new :issue => issue,
|
141
|
-
:mantissa => (nm * 10**17)/dm,
|
142
|
-
:exponent => (ne - de - 17),
|
143
|
-
:neg => (neg != v.neg)
|
144
|
-
end
|
145
|
-
|
146
|
-
def *(o)
|
147
|
-
return STAmount.new :issue => issue if zero? || o.zero?
|
148
|
-
|
149
|
-
if native?
|
150
|
-
min = sn_value < o.sn_value ? sn_value : o.sn_value
|
151
|
-
max = sn_value < o.sn_value ? o.sn_value : sn_value
|
152
|
-
|
153
|
-
return STAmount.new :mantissa => min * max
|
154
|
-
end
|
155
|
-
|
156
|
-
m1 = mantissa
|
157
|
-
m2 = o.mantissa
|
158
|
-
e1 = exponent
|
159
|
-
e2 = o.exponent
|
160
|
-
|
161
|
-
if native?
|
162
|
-
while nm < MIN_VAL
|
163
|
-
m1 *= 10
|
164
|
-
e1 -= 1
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
if o.native?
|
169
|
-
while dm < MIN_VAL
|
170
|
-
m2 *= 10
|
171
|
-
e2 -= 1
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
# see note: https://github.com/ripple/rippled/blob/b53fda1e1a7f4d09b766724274329df1c29988ab/src/ripple/protocol/impl/STAmount.cpp#L1131
|
176
|
-
STAmount.new :issue => issue,
|
177
|
-
:mantissa => (m1 * m2)/(10**14),
|
178
|
-
:exponent => (e1 + e2 + 14),
|
179
|
-
:neg => (neg != o.neg)
|
180
|
-
end
|
181
|
-
|
182
|
-
def -@
|
183
|
-
STAmount.new(:mantissa => mantissa,
|
184
|
-
:exponent => exponent,
|
185
|
-
:issue => issue,
|
186
|
-
:neg => !neg)
|
187
|
-
end
|
188
|
-
|
189
|
-
def <(o)
|
190
|
-
return neg if neg && !o.neg
|
191
|
-
if mantissa == 0
|
192
|
-
return false if o.neg
|
193
|
-
return o.mantissa != 0
|
194
|
-
end
|
195
|
-
|
196
|
-
return false if o.mantissa == 0
|
197
|
-
return neg if exponent > o.exponent
|
198
|
-
return !neg if exponent < o.exponent
|
199
|
-
return neg if mantissa > o.mantissa
|
200
|
-
return !neg if mantissa < o.mantissa
|
201
|
-
|
202
|
-
return false
|
69
|
+
def native?
|
70
|
+
@issue && @issue.xrp?
|
203
71
|
end
|
204
72
|
|
205
|
-
def
|
206
|
-
|
73
|
+
def zero?
|
74
|
+
@mantissa == 0
|
207
75
|
end
|
208
76
|
|
209
|
-
def
|
210
|
-
|
211
|
-
end
|
77
|
+
def inspect
|
78
|
+
return "0" if zero?
|
212
79
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
80
|
+
i = issue.inspect
|
81
|
+
i = i == '' ? '' : "(#{i})"
|
82
|
+
(native? ? xrp_amount : iou_amount.to_f).to_s +
|
83
|
+
(native? ? "" : i)
|
217
84
|
end
|
218
85
|
|
219
|
-
def
|
220
|
-
|
221
|
-
return -1 if self < o
|
222
|
-
return 1 if self > o
|
86
|
+
def to_s
|
87
|
+
inspect
|
223
88
|
end
|
224
89
|
end # class STAmount
|
225
90
|
end # module NodeStore
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module XRBP
|
2
|
+
module NodeStore
|
3
|
+
class STAmount
|
4
|
+
module Arithmatic
|
5
|
+
def +(v)
|
6
|
+
return self + STAmount.new(:mantissa => v) if v.kind_of?(Numeric)
|
7
|
+
|
8
|
+
e1 = exponent
|
9
|
+
e2 = v.exponent
|
10
|
+
|
11
|
+
m1 = mantissa
|
12
|
+
m2 = v.mantissa
|
13
|
+
|
14
|
+
m1 *= -1 if neg
|
15
|
+
m2 *= -1 if v.neg
|
16
|
+
|
17
|
+
while e1 < e2
|
18
|
+
m1 /= 10
|
19
|
+
e1 += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
while e2 < e1
|
23
|
+
m2 /= 10
|
24
|
+
e2 += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
m = m1 + m2
|
28
|
+
return STAmount.new :issue => issue if m >= -10 && m <= 10
|
29
|
+
return STAmount.new :mantissa => m,
|
30
|
+
:exponent => e1,
|
31
|
+
:issue => issue if m >= 0
|
32
|
+
return STAmount.new :mantissa => -m,
|
33
|
+
:exponent => e1,
|
34
|
+
:issue => issue
|
35
|
+
end
|
36
|
+
|
37
|
+
def -(v)
|
38
|
+
self + (-v)
|
39
|
+
end
|
40
|
+
|
41
|
+
def /(v)
|
42
|
+
return self / STAmount.new(:mantissa => v) if v.kind_of?(Numeric)
|
43
|
+
|
44
|
+
if v.is_a?(Rate)
|
45
|
+
return self if v == Rate.parity
|
46
|
+
return self / v.to_amount
|
47
|
+
end
|
48
|
+
|
49
|
+
raise "divide by zero" if v.zero?
|
50
|
+
return STAmount.new :issue => issue if zero?
|
51
|
+
|
52
|
+
nm = mantissa
|
53
|
+
dm = v.mantissa
|
54
|
+
|
55
|
+
ne = exponent
|
56
|
+
de = v.exponent
|
57
|
+
|
58
|
+
if native?
|
59
|
+
while nm < MIN_VAL
|
60
|
+
nm *= 10
|
61
|
+
ne -= 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if v.native?
|
66
|
+
while dm < MIN_VAL
|
67
|
+
dm *= 10
|
68
|
+
de -= 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# see note: https://github.com/ripple/rippled/blob/b53fda1e1a7f4d09b766724274329df1c29988ab/src/ripple/protocol/impl/STAmount.cpp#L1075
|
73
|
+
STAmount.new :issue => issue,
|
74
|
+
:mantissa => (nm * 10**17)/dm + 5,
|
75
|
+
:exponent => (ne - de - 17),
|
76
|
+
:neg => (neg != v.neg)
|
77
|
+
end
|
78
|
+
|
79
|
+
def *(o)
|
80
|
+
return self * STAmount.new(:mantissa => o) if o.kind_of?(Numeric)
|
81
|
+
|
82
|
+
return STAmount.new :issue => issue if zero? || o.zero?
|
83
|
+
|
84
|
+
if native? && o.native?
|
85
|
+
min = sn_value < o.sn_value ? sn_value : o.sn_value
|
86
|
+
max = sn_value < o.sn_value ? o.sn_value : sn_value
|
87
|
+
|
88
|
+
return STAmount.new :mantissa => min * max
|
89
|
+
end
|
90
|
+
|
91
|
+
m1 = mantissa
|
92
|
+
m2 = o.mantissa
|
93
|
+
e1 = exponent
|
94
|
+
e2 = o.exponent
|
95
|
+
|
96
|
+
if native?
|
97
|
+
while nm < MIN_VAL
|
98
|
+
m1 *= 10
|
99
|
+
e1 -= 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if o.native?
|
104
|
+
while dm < MIN_VAL
|
105
|
+
m2 *= 10
|
106
|
+
e2 -= 1
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# see note: https://github.com/ripple/rippled/blob/b53fda1e1a7f4d09b766724274329df1c29988ab/src/ripple/protocol/impl/STAmount.cpp#L1131
|
111
|
+
STAmount.new :issue => issue,
|
112
|
+
:mantissa => (m1 * m2)/(10**14) + 7,
|
113
|
+
:exponent => (e1 + e2 + 14),
|
114
|
+
:neg => (neg != o.neg)
|
115
|
+
end
|
116
|
+
|
117
|
+
def -@
|
118
|
+
STAmount.new(:mantissa => mantissa,
|
119
|
+
:exponent => exponent,
|
120
|
+
:issue => issue,
|
121
|
+
:neg => !neg)
|
122
|
+
end
|
123
|
+
end # module Arithmatic
|
124
|
+
end # class STAmount
|
125
|
+
end # module NodeStore
|
126
|
+
end # module XRBP
|