lib/universa/client.rb in universa-3.14.3 vs lib/universa/client.rb in universa-3.14.4

- old
+ new

@@ -8,11 +8,10 @@ # {Client} and {Connection} classes, more rubyish in interface paradigm, so there is no need to use it directly. class UmiClient < RemoteAdapter remote_class "com.icodici.universa.node2.network.Client" end - # The universa network client. Discover and connects to the universa network, provides consensus operations # and all other whole-network related functions. class Client using Universa::Parallel include Universa @@ -40,13 +39,13 @@ # @param [String] cache_dir where to store resulting topology. we recommend to leave it as nil. # # @raise if network topology could not be checked/obtained. def initialize topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil @client = UmiClient.new topology, cache_dir, private_key - @private_key = PrivateKey + @private_key = private_key @size = @client.size - @connections = (0...@size).map {nil} + @connections = (0...@size).map { nil } end # Get the node connection by its index (0...size). # @return [Connection] object def [] index @@ -62,11 +61,11 @@ # Get several random connections # @param [Numeric] number of connections to get # @return [Array(Connection)] array of connections to random (non repeating) nodes def random_connections number - (0...size).to_a.sample(number).map {|n| self[n]} + (0...size).to_a.sample(number).map { |n| self[n] } end # Perform fast consensus state check with a given trust level, determining whether the item is approved or not. # Blocks for 1 minute or until the network solution will be collected for a given trust level. # @@ -88,37 +87,46 @@ else raise ArgumentError "wrong type of object to check approval" end @client.isApprovedByNetwork(hash_id, trust.to_f, 60000) end - # Perform fast consensus state check with a given trust level, as the fraction of the whole network size. - # It checks the network nodes randomly until get enough positive or negative states. The lover the required - # trust level is, the faster the answer will be found. - # - # @param [Contract | HashId] obj contract to check - # @param [Object] trust level, should be between 0.1 (10% of network) and 0.9 (90% of the network) - # @return [ContractState] of some final node check It does not calculates average time (yet) - def get_state obj, trust: 0.3 + + # Perform fast consensus state check with a given trust level, as the fraction of the whole network size. + # It checks the network nodes randomly until get enough positive or negative states. The lover the required + # trust level is, the faster the answer will be found. + # + # @param [Contract | HashId] obj contract to check + # @param [Object] trust level, should be between 0.1 (10% of network) and 0.9 (90% of the network) + # @return [ContractState] of some final node check It does not calculates average time (yet) + def get_state obj, trust: 0.3 raise ArgumentError, "trusst must be in 0.1..0.9 range" if trust < 0.1 || trust > 0.9 result = Concurrent::IVar.new + found_error = nil negative_votes = Concurrent::AtomicFixnum.new((size * 0.1).round + 1) positive_votes = Concurrent::AtomicFixnum.new((size * trust).round) # consensus-finding conveyor: we chek connections in batches in parallel until get # some consensus. We do not wait until all of them will answer - (0...size).to_a.shuffle.each {|index| + (0...size).to_a.shuffle.each { |index| Thread.start { if result.incomplete? - if (state = self[index].get_state(obj)).approved? - result.try_set(state) if positive_votes.decrement < 0 - else - result.try_set(state) if negative_votes.decrement < 0 + begin + if (state = self[index].get_state(obj)).approved? + result.try_set(state) if positive_votes.decrement < 0 + else + result.try_set(state) if negative_votes.decrement < 0 + end + rescue + found_error = $! + result.try_set(nil) end end } } - result.value + r = result.value + found_error != nil and raise found_error + r end # Register a single contract (on private network or if you have white key allowing free operations) # on a random node. Client must check returned contract state. It requires "open" network or special # key that has a right to register contracts without payment. @@ -137,10 +145,10 @@ end # The connection to a single Universa node. class Connection - # Do not create it direcly, use {Client#random_connection}, {Client#random_connections} or {Client#[]} instead + # Do not create it directly, use {Client#random_connection}, {Client#random_connections} or {Client#[]} instead def initialize umi_client @client = umi_client end def umi_client