Class: Universa::Client
- Inherits:
-
Object
- Object
- Universa::Client
- Includes:
- Universa
- Defined in:
- lib/universa/client.rb
Overview
The universa network client. Discover and connects to the universa network, provides consensus operations and all other whole-network related functions.
Constant Summary
Constants included from Universa
Instance Attribute Summary collapse
-
#private_key ⇒ Object
readonly
Client private key ised in the connection.
-
#size ⇒ Object
readonly
Discovered network size.
Instance Method Summary collapse
-
#[](index) ⇒ Connection
Get the node connection by its index (0…size).
-
#get_state(obj, trust: 0.3) ⇒ ContractState
Perform fast consensus state check with a given trust level, as the fraction of the whole network size.
-
#initialize(topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil) ⇒ Client
constructor
Construct an Universa network client.
-
#is_approved?(obj, trust: 0.3) ⇒ Boolean
Perform fast consensus state check with a given trust level, determining whether the item is approved or not.
-
#random_connection ⇒ Connection
Get the random node connection.
-
#random_connections(number) ⇒ Array(Connection)
Get several random connections.
-
#register_single(contract, timeout: 45, max_retries: 3) ⇒ ContractState
Register a single contract (on private network or if you have white key allowing free operations) on a random node.
Methods included from Universa
#derive_key, #retry_with_timeout
Constructor Details
#initialize(topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil) ⇒ Client
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).
43 44 45 46 47 48 |
# 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 |
Instance Attribute Details
#private_key ⇒ Object (readonly)
Client private key ised in the connection
24 25 26 |
# File 'lib/universa/client.rb', line 24 def private_key @private_key end |
#size ⇒ Object (readonly)
Discovered network size
21 22 23 |
# File 'lib/universa/client.rb', line 21 def size @size end |
Instance Method Details
#[](index) ⇒ Connection
Get the node connection by its index (0…size).
52 53 54 55 |
# File 'lib/universa/client.rb', line 52 def [] index raise IndexError if index < 0 || index >= @size @connections[index] ||= Connection.new(@client.getClient(index)) end |
#get_state(obj, trust: 0.3) ⇒ ContractState
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.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# 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 |
#is_approved?(obj, trust: 0.3) ⇒ Boolean
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.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# 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 |
#random_connection ⇒ Connection
Get the random node connection
59 60 61 |
# File 'lib/universa/client.rb', line 59 def random_connection self[rand(0...size)] end |
#random_connections(number) ⇒ Array(Connection)
Get several random connections
66 67 68 |
# File 'lib/universa/client.rb', line 66 def random_connections number (0...size).to_a.sample(number).map {|n| self[n]} end |
#register_single(contract, timeout: 45, max_retries: 3) ⇒ ContractState
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.
131 132 133 134 135 |
# 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 |