class Universa::Client
The universa network client. Discover and connects to the universa network, provides consensus operations and all other whole-network related functions.
Attributes
Client
private key ised in the connection
Discovered network size
Public Class Methods
Construct an Universa
network client. Bu default, connects to the main network. Perform consensus-based network scanning and saves the current network topology in the cache on the file system, default is under +~/.universa+ but could be overriden.
If the network topology file is presented but the cached topology is newer, the cached will be used.
The client accepts small network topology changes as long as it still create consensus. Still, too big changes in the network topology might require fresh topology file (or upgrade the gem).
@param [String] topology could be name of known network (e.g. mainnet as by default) or path to a .json file
containing some network topology, for example, obtained from some external source like telegram channel.
@param [PrivateKey] private_key
to connect with. @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.
# File lib/universa/client.rb, line 43 def initialize topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil @client = UmiClient.new topology, cache_dir, private_key @private_key = PrivateKey @size = @client.size @connections = (0...@size).map {nil} end
Public Instance Methods
Get the node connection by its index (0…size). @return [Connection] object
# File lib/universa/client.rb, line 52 def [] index raise IndexError if index < 0 || index >= @size @connections[index] ||= Connection.new(@client.getClient(index)) 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)
# File lib/universa/client.rb, line 100 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 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| 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 end end } } result.value 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.
@param [Contract | HashId
| String | Binary] obj contract to check @param [Object] trust level, should be between 0.1 (10% of network) and 0.9 (90% of the network) @return true if the contract state is approved by the network with a given trust level, false otherwise.
# File lib/universa/client.rb, line 76 def is_approved? obj, trust: 0.3 hash_id = case obj when HashId obj when Contract obj.hash_id when String if obj.encoding == Encoding::ASCII_8BIT HashId.from_digest(obj) else HashId.from_string(obj) end else raise ArgumentError "wrong type of object to check approval" end @client.isApprovedByNetwork(hash_id, trust.to_f, 60000) end
Get the random node connection @return [Connection] node connection
# File lib/universa/client.rb, line 59 def random_connection self[rand(0...size)] end
Get several random connections @param [Numeric] number of connections to get @return [Array(Connection
)] array of connections to random (non repeating) nodes
# File lib/universa/client.rb, line 66 def random_connections number (0...size).to_a.sample(number).map {|n| self[n]} 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.
When retrying, randpm nodes are selected.
@param [Contract] contract must be sealed ({Contract#seal})
@return [ContractState] of the result. Could contain errors.
# File lib/universa/client.rb, line 131 def register_single(contract, timeout: 45, max_retries: 3) retry_with_timeout(timeout, max_retries) { ContractState.new(random_connection.register_single(contract, timeout / max_retries * 1000 - 100)) } end