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, dump_bytes, #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).
42 43 44 45 46 47 |
# File 'lib/universa/client.rb', line 42 def initialize topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil @client = UmiClient.new topology, cache_dir, private_key @private_key = private_key @size = @client.size @connections = (0...@size).map { nil } end |
Instance Attribute Details
#private_key ⇒ Object (readonly)
Client private key ised in the connection
23 24 25 |
# File 'lib/universa/client.rb', line 23 def private_key @private_key end |
#size ⇒ Object (readonly)
Discovered network size
20 21 22 |
# File 'lib/universa/client.rb', line 20 def size @size end |
Instance Method Details
#[](index) ⇒ Connection
Get the node connection by its index (0…size).
51 52 53 54 |
# File 'lib/universa/client.rb', line 51 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.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/universa/client.rb', line 101 def get_state obj, trust: 0.3 raise ArgumentError, "trust 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| Thread.start { if result.incomplete? 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 } } r = result.value found_error != nil and raise found_error r 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.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/universa/client.rb', line 75 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
58 59 60 |
# File 'lib/universa/client.rb', line 58 def random_connection self[rand(0...size)] end |
#random_connections(number) ⇒ Array(Connection)
Get several random connections
65 66 67 |
# File 'lib/universa/client.rb', line 65 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.
140 141 142 143 144 |
# File 'lib/universa/client.rb', line 140 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 |