nanook 2.1.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/nanook/block.rb CHANGED
@@ -45,8 +45,11 @@ class Nanook
45
45
  rpc(:work_cancel, :hash).empty?
46
46
  end
47
47
 
48
- # Returns an Array of block hashes in the account chain starting at
49
- # this block.
48
+ # Returns a consecutive list of block hashes in the account chain
49
+ # starting at block back to count (direction from frontier back to
50
+ # open block, from newer blocks to older). Will list all blocks back
51
+ # to the open block of this chain when count is set to "-1".
52
+ # The requested block hash is included in the answer.
50
53
  #
51
54
  # See also #successors.
52
55
  #
@@ -60,20 +63,66 @@ class Nanook
60
63
  # "36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
61
64
  # "FBF8B0E6623A31AB528EBD839EEAA91CAFD25C12294C46754E45FD017F7939EB"
62
65
  # ]
66
+ #
63
67
  # @param limit [Integer] maximum number of block hashes to return (default is 1000)
64
- def chain(limit: 1000)
65
- response = rpc(:chain, :block, count: limit)[:blocks]
68
+ # @param offset [Integer] return the account chain block hashes offset by the specified number of blocks (default is 0)
69
+ def chain(limit: 1000, offset: 0)
70
+ response = rpc(:chain, :block, count: limit, offset: offset)[:blocks]
66
71
  Nanook::Util.coerce_empty_string_to_type(response, Array)
67
72
  end
73
+ alias_method :ancestors, :chain
74
+
75
+ # Request confirmation for a block from online representative nodes.
76
+ # Will return immediately with a boolean to indicate if the request for
77
+ # confirmation was successful. Note that this boolean does not indicate
78
+ # the confirmation status of the block. If confirmed, your block should
79
+ # appear in {Nanook::Node#confirmation_history} within a short amount of
80
+ # time, or you can use the convenience method {Nanook::Block#confirmed_recently?}
81
+ #
82
+ # ==== Example:
83
+ # block.confirm # => true
84
+ #
85
+ # @return [Boolean] if the confirmation request was sent successful
86
+ def confirm
87
+ rpc(:block_confirm, :hash)[:started] == 1
88
+ end
89
+
90
+ # This call is for internal diagnostics/debug purposes only. Do not
91
+ # rely on this interface being stable and do not use in a production system.
92
+ #
93
+ # Check if the block appears in the list of recently confirmed blocks by
94
+ # online representatives. The full list of blocks can be queried for with {Nanook::Node#confirmation_history}.
95
+ #
96
+ # This method can work in conjunction with {Nanook::Block#confirm},
97
+ # whereby you can send any block (old or new) out to online representatives to
98
+ # confirm. The confirmation process can take up to a couple of minutes.
99
+ #
100
+ # The method returning +false+ can indicate that the block is still in the process of being
101
+ # confirmed and that you should call the method again soon, or that it
102
+ # was confirmed earlier than the list available in {Nanook::Node#confirmation_history},
103
+ # or that it was not confirmed.
104
+ #
105
+ # ==== Example:
106
+ # block.confirmed_recently? # => true
107
+ #
108
+ # @return [Boolean] +true+ if the block has been recently confirmed by
109
+ # online representatives.
110
+ def confirmed_recently?
111
+ @rpc.call(:confirmation_history)[:confirmations].map{|h| h[:hash]}.include?(@block)
112
+ end
113
+ alias_method :recently_confirmed?, :confirmed_recently?
68
114
 
69
115
  # Generate work for a block.
70
116
  #
71
117
  # ==== Example:
72
118
  # block.generate_work # => "2bf29ef00786a6bc"
73
119
  #
120
+ # @param use_peers [Boolean] if set to +true+, then the node will query
121
+ # its work peers (if it has any, see {Nanook::WorkPeer#list}).
122
+ # When +false+, the node will only generate work locally (default is +false+)
74
123
  # @return [String] the work id of the work completed.
75
- def generate_work
76
- rpc(:work_generate, :hash)[:work]
124
+ def generate_work(use_peers: false)
125
+ rpc(:work_generate, :hash, use_peers: use_peers)[:work]
77
126
  end
78
127
 
79
128
  # Returns Array of Hashes containing information about a chain of
@@ -87,7 +136,7 @@ class Nanook
87
136
  #
88
137
  # [
89
138
  # {
90
- # :account=>"xrb_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
139
+ # :account=>"nano_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
91
140
  # :amount=>539834279601145558517940224,
92
141
  # :hash=>"36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
93
142
  # :type=>"send"
@@ -124,7 +173,7 @@ class Nanook
124
173
  # :id=>"36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
125
174
  # :type=>"send",
126
175
  # :previous=>"FBF8B0E6623A31AB528EBD839EEAA91CAFD25C12294C46754E45FD017F7939EB",
127
- # :destination=>"xrb_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
176
+ # :destination=>"nano_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
128
177
  # :balance=>"00000000000000000000000000000000",
129
178
  # :work=>"44cc24b60705083a",
130
179
  # :signature=>"42ADFEFE7C3FFF188AE92A202F8A5734DE91779C454613E446EEC93D001D6C953E9FD16730AF32C891791BA8EDAECEB059A213E2FE1EEB7ADF9D5D0815464D06"
@@ -220,10 +269,12 @@ class Nanook
220
269
  # ["36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E"]
221
270
  #
222
271
  # @param limit [Integer] maximum number of send/receive block hashes
223
- # to return in the chain (default is 1000)
272
+ # to return in the chain (default is 1000)
273
+ # @param offset [Integer] return the account chain block hashes offset
274
+ # by the specified number of blocks (default is 0)
224
275
  # @return [Array<String>] block hashes in the account chain ending at this block
225
- def successors(limit: 1000)
226
- response = rpc(:successors, :block, count: limit)[:blocks]
276
+ def successors(limit: 1000, offset: 0)
277
+ response = rpc(:successors, :block, count: limit, offset: offset)[:blocks]
227
278
  Nanook::Util.coerce_empty_string_to_type(response, Array)
228
279
  end
229
280
 
data/lib/nanook/error.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  class Nanook
2
+ # Standard error for Nanook
2
3
  class Error < StandardError
3
4
  end
4
5
  end
data/lib/nanook/node.rb CHANGED
@@ -1,31 +1,220 @@
1
1
  class Nanook
2
+
3
+ # The <tt>Nanook::Node</tt> class contains methods to manage your nano
4
+ # node and query its data of the nano network.
5
+ #
6
+ # Your node is constantly syncing data with other nodes on the network. When
7
+ # your node first starts up after being built, its database will be empty
8
+ # and it will begin synchronizing and downloading data of the nano ledger
9
+ # to its local database. The ledger is the central record of all accounts
10
+ # and transactions. Some of the methods in this class query your node's
11
+ # database formed from the nano ledger, and so the responses are determined
12
+ # by the completeness of your node's database.
13
+ #
14
+ # You can determine how synchronized your node is with the nano ledger
15
+ # with the {#sync_progress} method.
16
+ #
17
+ # === Initializing
18
+ #
19
+ # Initialize this class through the convenient {Nanook#node} method:
20
+ #
21
+ # node = Nanook.new.node
22
+ #
23
+ # Or compose the longhand way like this:
24
+ #
25
+ # rpc_conn = Nanook::Rpc.new
26
+ # node = Nanook::Node.new(rpc_conn)
2
27
  class Node
3
28
 
4
29
  def initialize(rpc)
5
30
  @rpc = rpc
6
31
  end
7
32
 
33
+ # The number of accounts in the nano ledger--essentially all
34
+ # accounts with _open_ blocks. An _open_ block
35
+ # is the type of block written to the nano ledger when an account
36
+ # receives its first payment (see {Nanook::WalletAccount#receive}). All accounts
37
+ # that respond +true+ to {Nanook::Account#exists?} have open blocks in the ledger.
38
+ #
39
+ # @return [Integer] number of accounts with _open_ blocks.
8
40
  def account_count
9
41
  rpc(:frontier_count)[:count]
10
42
  end
11
43
  alias_method :frontier_count, :account_count
12
44
 
45
+ # The count of all blocks downloaded to the node, and
46
+ # blocks still to be synchronized by the node.
47
+ #
48
+ # ==== Example:
49
+ #
50
+ #
51
+ #
52
+ # @return [Hash{Symbol=>Integer}] number of blocks and unchecked
53
+ # synchronizing blocks
13
54
  def block_count
14
55
  rpc(:block_count)
15
56
  end
16
57
 
17
- def block_count_type
58
+ # The count of all known blocks by their type.
59
+ #
60
+ # ==== Example:
61
+ #
62
+ # node.block_count_by_type
63
+ #
64
+ # Example response:
65
+ #
66
+ # {
67
+ # send: 1000,
68
+ # receive: 900,
69
+ # open: 900,
70
+ # change: 50
71
+ # }
72
+ #
73
+ # @return [Hash{Symbol=>Integer}] number of blocks by type
74
+ def block_count_by_type
18
75
  rpc(:block_count_type)
19
76
  end
77
+ alias_method :block_count_type, :block_count_by_type
20
78
 
79
+ # Initialize bootstrap to a specific IP address and port.
80
+ #
81
+ # @return [Boolean] indicating if the action was successful
21
82
  def bootstrap(address:, port:)
22
83
  rpc(:bootstrap, address: address, port: port).has_key?(:success)
23
84
  end
24
85
 
86
+ # Initialize multi-connection bootstrap to random peers
87
+ #
88
+ # @return [Boolean] indicating if the action was successful
25
89
  def bootstrap_any
26
90
  rpc(:bootstrap_any).has_key?(:success)
27
91
  end
28
92
 
93
+ # Initialize lazy bootstrap with given block hash
94
+ #
95
+ # @param hash [String]
96
+ # @param force [Boolean] False by default. Manually force closing
97
+ # of all current bootstraps
98
+ # @return [Boolean] indicating if the action was successful
99
+ def bootstrap_lazy(hash, force: false)
100
+ rpc(:bootstrap_lazy, hash: hash, force: force)[:started] == 1
101
+ end
102
+
103
+ # Returning status of current bootstrap attempt for debug purposes only.
104
+ # This call is for internal diagnostics/debug purposes only.
105
+ # Do not rely on this interface being stable and do not use in a
106
+ # production system.
107
+ #
108
+ # ==== Example:
109
+ #
110
+ # node.bootstrap_status
111
+ #
112
+ # Example response:
113
+ #
114
+ # {
115
+ # clients: 5790,
116
+ # pulls: 141065,
117
+ # pulling: 3,
118
+ # connections: 16,
119
+ # idle: 0,
120
+ # target_connections: 64,
121
+ # total_blocks: 536820,
122
+ # lazy_mode: true,
123
+ # lazy_blocks: 423388,
124
+ # lazy_state_unknown: 2,
125
+ # lazy_balances: 0,
126
+ # lazy_pulls: 0,
127
+ # lazy_stopped: 644,
128
+ # lazy_keys: 449,
129
+ # lazy_key_1: "A86EB2B479AAF3CD531C8356A1FBE3CB500DFBF5BF292E5E6B8D1048DE199C32"
130
+ # }
131
+ #
132
+ # @return [Hash{Symbol=>String|Integer|Boolean}]
133
+ def bootstrap_status
134
+ rpc(:bootstrap_status)
135
+ end
136
+
137
+ # This call is for internal diagnostics/debug purposes only.
138
+ # Do not rely on this interface being stable and do not use in a
139
+ # production system.
140
+ #
141
+ # Returns block and tally weight (in raw) election duration (in
142
+ # milliseconds), election confirmation timestamp for recent elections
143
+ # winners.
144
+ #
145
+ # ==== Example:
146
+ #
147
+ # node.confirmation_history
148
+ #
149
+ # Example response:
150
+ #
151
+ # [
152
+ # {
153
+ # block: "EA70B32C55C193345D625F766EEA2FCA52D3F2CCE0B3A30838CC543026BB0FEA",
154
+ # tally: 80394786589602980996311817874549318248,
155
+ # duration: 4000,
156
+ # time: 1544819986,
157
+ # },
158
+ # {
159
+ # block: "F2F8DA6D2CA0A4D78EB043A7A29E12BDE5B4CE7DE1B99A93A5210428EE5B8667",
160
+ # tally: 68921714529890443063672782079965877749,
161
+ # duration: 6000,
162
+ # time: 1544819988,
163
+ # }
164
+ # ]
165
+ #
166
+ # @return [Hash{Symbol=>String|Integer}]
167
+ def confirmation_history
168
+ rpc(:confirmation_history)[:confirmations].map do |history|
169
+ # Rename hash key to block
170
+ block = history.delete(:hash)
171
+ {block: block}.merge(history)
172
+ end
173
+ end
174
+
175
+ # Returns the difficulty values (16 hexadecimal digits string, 64 bit)
176
+ # for the minimum required on the network (network_minimum) as well
177
+ # as the current active difficulty seen on the network (network_current,
178
+ # 5 minute trended average of adjusted difficulty seen on confirmed
179
+ # transactions) which can be used to perform rework for better
180
+ # prioritization of transaction processing. A multiplier of the
181
+ # network_current from the base difficulty of network_minimum is also
182
+ # provided for comparison.
183
+ #
184
+ # ==== Example:
185
+ #
186
+ # node.difficulty(include_trend: true)
187
+ #
188
+ # Example response:
189
+ #
190
+ # {
191
+ # network_minimum: "ffffffc000000000",
192
+ # network_current: "ffffffc1816766f2",
193
+ # multiplier: 1.024089858417128,
194
+ # difficulty_trend: [
195
+ # 1.156096135149775,
196
+ # 1.190133894573061,
197
+ # 1.135567138563921,
198
+ # 1.000000000000000,
199
+ # ]
200
+ # }
201
+ #
202
+ # @param include_trend [Boolean] false by default. Also returns the
203
+ # trend of difficulty seen on the network as a list of multipliers.
204
+ # Sampling occurs every 16 to 36 seconds. The list is ordered such
205
+ # that the first value is the most recent sample.
206
+ # @return [Hash{Symbol=>String|Float|Array}]
207
+ def difficulty(include_trend: false)
208
+ rpc(:active_difficulty, include_trend: include_trend).tap do |response|
209
+ response[:multiplier] = response[:multiplier].to_f
210
+
211
+ if response.key?(:difficulty_trend)
212
+ response[:difficulty_trend].map!(&:to_f)
213
+ end
214
+ end
215
+ end
216
+
217
+ # @return [String]
29
218
  def inspect
30
219
  "#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
31
220
  end
@@ -34,14 +223,60 @@ class Nanook
34
223
  rpc(:peers)[:peers]
35
224
  end
36
225
 
37
- def representatives
38
- rpc(:representatives)[:representatives]
226
+ # All representatives and their voting weight.
227
+ #
228
+ # ==== Example:
229
+ #
230
+ # node.representatives
231
+ #
232
+ # Example response:
233
+ #
234
+ # {
235
+ # nano_1111111111111111111111111111111111111111111111111117353trpda: 3822372327060170000000000000000000000,
236
+ # nano_1111111111111111111111111111111111111111111111111awsq94gtecn: 30999999999999999999999999000000,
237
+ # nano_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi: 0
238
+ # }
239
+ #
240
+ # @return [Hash{Symbol=>Integer}] known representatives and their voting weight
241
+ def representatives(unit: Nanook.default_unit)
242
+ unless Nanook::UNITS.include?(unit)
243
+ raise ArgumentError.new("Unsupported unit: #{unit}")
244
+ end
245
+
246
+ response = rpc(:representatives)[:representatives]
247
+ return response if unit == :raw
248
+
249
+ r = response.map do |account_id, balance|
250
+ balance = Nanook::Util.raw_to_NANO(balance)
251
+
252
+ [account_id, balance]
253
+ end
254
+
255
+ Hash[r].to_symbolized_hash
256
+ end
257
+
258
+ # All online representatives that have voted recently. Note, due to the
259
+ # design of the nano RPC, this method cannot return the voting weight
260
+ # of the representatives.
261
+ #
262
+ # ==== Example:
263
+ #
264
+ # node.representatives_online # => ["nano_111...", "nano_222"]
265
+ #
266
+ # @return [Array<String>] array of representative account ids
267
+ def representatives_online
268
+ rpc(:representatives_online)[:representatives].keys.map(&:to_s)
39
269
  end
40
270
 
271
+ # Safely shuts down the node.
272
+ #
273
+ # @return [Boolean] indicating if action was successful
41
274
  def stop
42
275
  rpc(:stop).has_key?(:success)
43
276
  end
44
277
 
278
+ # @param limit [Integer] number of synchronizing blocks to return
279
+ # @return [Hash{Symbol=>String}] information about the synchronizing blocks for this node
45
280
  def synchronizing_blocks(limit: 1000)
46
281
  response = rpc(:unchecked, count: limit)[:blocks]
47
282
  response = response.map do |block, info|
@@ -49,7 +284,16 @@ class Nanook
49
284
  end
50
285
  Hash[response.sort].to_symbolized_hash
51
286
  end
287
+ alias_method :unchecked, :synchronizing_blocks
52
288
 
289
+ # The percentage completeness of the synchronization process for
290
+ # your node as it downloads the nano ledger. Note, it's normal for
291
+ # your progress to not ever reach 100. The closer to 100, the more
292
+ # complete your node's data is, and so the query methods in this class
293
+ # become more reliable.
294
+ #
295
+ # @return [Float] the percentage completeness of the synchronization
296
+ # process for your node
53
297
  def sync_progress
54
298
  response = rpc(:block_count)
55
299
 
@@ -60,13 +304,27 @@ class Nanook
60
304
  count.to_f * 100 / total.to_f
61
305
  end
62
306
 
307
+ # Returns node uptime in seconds
308
+ #
309
+ # @return [Integer] seconds of uptime
310
+ def uptime
311
+ rpc(:uptime)['seconds']
312
+ end
313
+
314
+ # This method is deprecated and will be removed in 3.0, as a node never
315
+ # reaches 100% synchronization.
316
+ #
317
+ # @return [Boolean] signalling if this node ever reaches 100% synchronized
63
318
  def synced?
319
+ warn "[DEPRECATION] `synced?` is deprecated and will be removed in 3.0"
64
320
  rpc(:block_count)[:unchecked] == 0
65
321
  end
66
322
 
323
+ # @return [Hash{Symbol=>Integer|String}] version information for this node
67
324
  def version
68
325
  rpc(:version)
69
326
  end
327
+ alias_method :info, :version
70
328
 
71
329
  private
72
330