universa 0.2.6 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f18252fa753d03999072354d51a5f9ef26c991ca8c31448216e754ec4c2b8ed5
4
- data.tar.gz: 94770c73bbd2ff38831590c54ffa8b78b91d2e949747daae720d6b561502547d
3
+ metadata.gz: 7752fa8898467b2d9c15b36fbd2e42714190ba243adcd83ce8998b75ffc2cb91
4
+ data.tar.gz: 45cccb4f84d884276a7d1dcb90d2ea45f7f51b5ec089588254c91dbd2cea6ae9
5
5
  SHA512:
6
- metadata.gz: be2335af7f74ae7820399d66cebe6825226f1b9fc88f66fbfb8e55008dd9e3d56fe8524d28110f318d847ff75698edbe773f7a6c3316041ec86a60e1ce143719
7
- data.tar.gz: d091f53acde7af2a9ec4e561a535b23cf63f2eb60a2c6aec07698e6612bc45620effd2d3b6a095c8790fd5f2602f5a262aa095cc02dcab59062dd8126059021d
6
+ metadata.gz: f6a88953548a26c93e2cc93ee4301185e5536f8aaa4a5801b76912a1e8b8bfb69bff4af6aa74085cbc1fef75969ccb6cb150bacb505ff30b6e62b160d4279e6f
7
+ data.tar.gz: 7b715ea9610753ffd66306a81a3d1dcc4c691b9251fc172c1d10aafe18f1bb741962b90e63cad7523e75a0215e49de5d7c12f67fb9fd3fe826e50e5895eb8dde
data/README.md CHANGED
@@ -4,10 +4,11 @@
4
4
  for direct access to remote objects.
5
5
 
6
6
  This is an under-construction official gem from [Universa][universa] to facilitate access to the
7
- Java library using Universa's UMI protocol.
7
+ Java library using Universa's UMI protocol and Universa client services.
8
8
 
9
9
  ## News
10
10
 
11
+ - rewritten Client and Connection to use new consensus-based, dns-free Universa network topology discovery protocol
11
12
  - added syntax sugar for TransactionPack
12
13
  - alfa version of the local FS-based contract store.
13
14
  - ability to edit `contract.state` and `contract.transactional` in new revisions.
@@ -63,15 +64,14 @@ puts "Contract id: #{contract.getId.toBase64String}" #=> contract id: x9Ey+q...
63
64
  contract_id = contract.get_id.to_base64_string
64
65
 
65
66
  ```
66
-
67
67
  ## Docs and resources
68
68
 
69
69
  for more information see:
70
70
 
71
- - [Universa gem page](https://kb.universa.io/universa_ruby_gem/131) in the Universa Knowledge Base.
72
- - Universa Java API: https://kb.universa.io/general_java_api/5
73
- - Universa UMI server: https://kb.universa.io/umi_protocol/98
74
- - Ruby [docs online](https://kb.universa.io/system/static/gem_universa/)
71
+ - [Universa gem page](https://kb.universablockchain.com/universa_ruby_gem/131) in the Universa Knowledge Base.
72
+ - Universa Java API: https://kb.universablockchain.com/general_java_api/5
73
+ - Universa UMI server: https://kb.universablockchain.com/umi_protocol/98
74
+ - Ruby [docs online](https://kb.universablockchain.com/system/static/gem_universa/)
75
75
  - Farcall [gem](https://github.com/sergeych/farcall) and [protocol](https://github.com/sergeych/farcall/wiki).
76
76
 
77
77
  ### Use UMI service (alfa state)
@@ -108,4 +108,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
108
108
 
109
109
  Everyone interacting in the Universa project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/universa/blob/master/CODE_OF_CONDUCT.md).
110
110
 
111
- [universa]:http://universa.io
111
+ [universa]:https://universablockchain.com
@@ -2,7 +2,7 @@
2
2
 
3
3
  rm download > /dev/null
4
4
 
5
- wget https://files.universa.io/s/ecz6fDT7ny634Xj/download
5
+ wget https://lnd.im/umi -O download
6
6
 
7
7
  rm -rd -f ./bin/umi >/dev/null 2>&1
8
8
  rm -rd -f ./bin/umi-* >/dev/null 2>&1
@@ -344,7 +344,7 @@ declare -r lib_dir="$(realpath "${app_home}/../lib")"
344
344
  declare -a app_mainclass=(com.icodici.farcallscala.Main)
345
345
 
346
346
  declare -r script_conf_file="${app_home}/../conf/application.ini"
347
- declare -r app_classpath="$lib_dir/com.icodici.umi-0.8.19.jar:$lib_dir/org.scala-lang.scala-library-2.12.7.jar:$lib_dir/com.icodici.universa_core-3.8.8.jar:$lib_dir/org.yaml.snakeyaml-1.18.jar:$lib_dir/net.sf.jopt-simple.jopt-simple-4.9.jar:$lib_dir/org.postgresql.postgresql-42.1.4.jar:$lib_dir/org.xerial.sqlite-jdbc-3.8.9.1.jar:$lib_dir/com.icodici.nanohttpd-2.1.0.jar:$lib_dir/com.icodici.common_tools-3.8.8.jar:$lib_dir/com.eclipsesource.minimal-json.minimal-json-0.9.4.jar:$lib_dir/net.java.dev.jna.jna-4.5.1.jar:$lib_dir/org.checkerframework.checker-qual-2.3.2.jar:$lib_dir/com.icodici.crypto-3.8.8.jar:$lib_dir/com.madgag.spongycastle.core-1.58.0.0.jar:$lib_dir/com.squareup.jnagmp.jnagmp-2.0.0.jar:$lib_dir/com.typesafe.play.play-json_2.12-2.6.10.jar:$lib_dir/com.typesafe.play.play-functional_2.12-2.6.10.jar:$lib_dir/org.scala-lang.scala-reflect-2.12.7.jar:$lib_dir/org.typelevel.macro-compat_2.12-1.1.1.jar:$lib_dir/joda-time.joda-time-2.9.9.jar:$lib_dir/com.fasterxml.jackson.core.jackson-core-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar:$lib_dir/org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar:$lib_dir/net.java.dev.jna.jna-platform-4.5.0.jar"
347
+ declare -r app_classpath="$lib_dir/com.icodici.umi-0.8.29.jar:$lib_dir/org.scala-lang.scala-library-2.12.7.jar:$lib_dir/com.icodici.universa_core-3.9.9.jar:$lib_dir/org.yaml.snakeyaml-1.18.jar:$lib_dir/com.icodici.nanohttpd-2.1.0.jar:$lib_dir/com.icodici.common_tools-3.9.9.jar:$lib_dir/com.eclipsesource.minimal-json.minimal-json-0.9.4.jar:$lib_dir/net.java.dev.jna.jna-4.5.1.jar:$lib_dir/org.checkerframework.checker-qual-2.3.2.jar:$lib_dir/com.icodici.crypto-3.9.9.jar:$lib_dir/com.madgag.spongycastle.core-1.58.0.0.jar:$lib_dir/com.squareup.jnagmp.jnagmp-2.0.0.jar:$lib_dir/com.typesafe.play.play-json_2.12-2.6.10.jar:$lib_dir/com.typesafe.play.play-functional_2.12-2.6.10.jar:$lib_dir/org.scala-lang.scala-reflect-2.12.7.jar:$lib_dir/org.typelevel.macro-compat_2.12-1.1.1.jar:$lib_dir/joda-time.joda-time-2.9.9.jar:$lib_dir/com.fasterxml.jackson.core.jackson-core-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar:$lib_dir/org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar:$lib_dir/net.java.dev.jna.jna-platform-4.5.0.jar:$lib_dir/net.sf.jopt-simple.jopt-simple-4.9.jar"
348
348
 
349
349
  # java_cmd is overrode in process_args when -java-home is used
350
350
  declare java_cmd=$(get_java_cmd)
@@ -80,7 +80,7 @@ rem "-J" is stripped, "-D" is left as is, and everything is appended to JAVA_OPT
80
80
  set _JAVA_PARAMS=
81
81
  set _APP_ARGS=
82
82
 
83
- set "APP_CLASSPATH=%APP_LIB_DIR%\com.icodici.umi-0.8.19.jar;%APP_LIB_DIR%\org.scala-lang.scala-library-2.12.7.jar;%APP_LIB_DIR%\com.icodici.universa_core-3.8.8.jar;%APP_LIB_DIR%\org.yaml.snakeyaml-1.18.jar;%APP_LIB_DIR%\net.sf.jopt-simple.jopt-simple-4.9.jar;%APP_LIB_DIR%\org.postgresql.postgresql-42.1.4.jar;%APP_LIB_DIR%\org.xerial.sqlite-jdbc-3.8.9.1.jar;%APP_LIB_DIR%\com.icodici.nanohttpd-2.1.0.jar;%APP_LIB_DIR%\com.icodici.common_tools-3.8.8.jar;%APP_LIB_DIR%\com.eclipsesource.minimal-json.minimal-json-0.9.4.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-4.5.1.jar;%APP_LIB_DIR%\org.checkerframework.checker-qual-2.3.2.jar;%APP_LIB_DIR%\com.icodici.crypto-3.8.8.jar;%APP_LIB_DIR%\com.madgag.spongycastle.core-1.58.0.0.jar;%APP_LIB_DIR%\com.squareup.jnagmp.jnagmp-2.0.0.jar;%APP_LIB_DIR%\com.typesafe.play.play-json_2.12-2.6.10.jar;%APP_LIB_DIR%\com.typesafe.play.play-functional_2.12-2.6.10.jar;%APP_LIB_DIR%\org.scala-lang.scala-reflect-2.12.7.jar;%APP_LIB_DIR%\org.typelevel.macro-compat_2.12-1.1.1.jar;%APP_LIB_DIR%\joda-time.joda-time-2.9.9.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-core-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar;%APP_LIB_DIR%\org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-platform-4.5.0.jar"
83
+ set "APP_CLASSPATH=%APP_LIB_DIR%\com.icodici.umi-0.8.29.jar;%APP_LIB_DIR%\org.scala-lang.scala-library-2.12.7.jar;%APP_LIB_DIR%\com.icodici.universa_core-3.9.9.jar;%APP_LIB_DIR%\org.yaml.snakeyaml-1.18.jar;%APP_LIB_DIR%\com.icodici.nanohttpd-2.1.0.jar;%APP_LIB_DIR%\com.icodici.common_tools-3.9.9.jar;%APP_LIB_DIR%\com.eclipsesource.minimal-json.minimal-json-0.9.4.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-4.5.1.jar;%APP_LIB_DIR%\org.checkerframework.checker-qual-2.3.2.jar;%APP_LIB_DIR%\com.icodici.crypto-3.9.9.jar;%APP_LIB_DIR%\com.madgag.spongycastle.core-1.58.0.0.jar;%APP_LIB_DIR%\com.squareup.jnagmp.jnagmp-2.0.0.jar;%APP_LIB_DIR%\com.typesafe.play.play-json_2.12-2.6.10.jar;%APP_LIB_DIR%\com.typesafe.play.play-functional_2.12-2.6.10.jar;%APP_LIB_DIR%\org.scala-lang.scala-reflect-2.12.7.jar;%APP_LIB_DIR%\org.typelevel.macro-compat_2.12-1.1.1.jar;%APP_LIB_DIR%\joda-time.joda-time-2.9.9.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-core-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar;%APP_LIB_DIR%\org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-platform-4.5.0.jar;%APP_LIB_DIR%\net.sf.jopt-simple.jopt-simple-4.9.jar"
84
84
  set "APP_MAIN_CLASS=com.icodici.farcallscala.Main"
85
85
  set "SCRIPT_CONF_FILE=%APP_HOME%\conf\application.ini"
86
86
 
@@ -4,7 +4,7 @@ module Universa
4
4
 
5
5
  # The storage interface capable to store contracts in chains, providing search and attributes.
6
6
  # This class is not a store itself but the base class for it, having common boilerplate and
7
- # sort of interface to implement.
7
+ # sort of interface to implement. _Under development, we might change it_
8
8
  class ChainStore
9
9
 
10
10
  # Save contract to the store. When this method returns, the contract must me already stored.
@@ -4,195 +4,148 @@ require 'concurrent'
4
4
 
5
5
  module Universa
6
6
 
7
- using Universa
7
+ # The low-level adapter for the UMI Universa client. We provide convenience wrappers for it
8
+ # {Client} and {Connection} classes, more rubyish in interface paradigm, so there is no need to use it directly.
9
+ class UmiClient < RemoteAdapter
10
+ remote_class "com.icodici.universa.node2.network.Client"
11
+ end
12
+
8
13
 
9
- # Universa network client reads current network configuration and provides access to each node independently
10
- # and also implement newtor-wide procedures.
14
+ # The universa network client. Discover and connects to the universa network, provides consensus operations
15
+ # and all other whole-network related functions.
11
16
  class Client
12
17
  using Universa::Parallel
13
18
  include Universa
14
19
 
15
- attr :connection_key
20
+ # Discovered network size
21
+ attr :size
16
22
 
17
- # Create client
18
- # @param [PrivateKey] private_key to connect with. Generates new one if omitted.
19
- def initialize private_key = nil
20
- @connection_key = private_key
21
- scan_network()
22
- end
23
+ # Client private key ised in the connection
24
+ attr :private_key
23
25
 
24
- # Number of accessible nodes
25
- def size
26
- @nodes.size
26
+ # Construct an Universa network client. Bu default, connects to the main network. Perform consensus-based
27
+ # network scanning and saves the current network topology in the cache on the file system, default is under
28
+ # +~/.universa+ but could be overriden.
29
+ #
30
+ # If the network topology file is presented but the cached topology is newer, the cached will be used.
31
+ #
32
+ # The client accepts small network topology changes as long as it still create consensus. Still, too big changes
33
+ # in the network topology might require fresh topology file (or upgrade the gem).
34
+ #
35
+ #
36
+ # @param [String] topology: could be name of known network (e.g. mainnet as by default) or path to a .json file
37
+ # containing some network topology, for example, obtained from some external source like telegram
38
+ # channel.
39
+ # @param [PrivateKey] private_key to connect with.
40
+ # @param [String] cache_dir where to store resulting topology. we recommend to leave it as nil.
41
+ #
42
+ # @raise if network topology could not be checked/obtained.
43
+ def initialize topology: "mainnet", private_key: PrivateKey.new(2048), cache_dir: nil
44
+ @client = UmiClient.new topology, cache_dir, private_key
45
+ @private_key = PrivateKey
46
+ @size = @client.size
47
+ @connections = (0...@size).map {nil}
27
48
  end
28
49
 
29
- # private key used by the connection (might be generated)
30
- def private_key
31
- @connection_key ||= PrivateKey.new(2048)
50
+ # Get the node connection by its index (0...size).
51
+ # @return [Connection] object
52
+ def [] index
53
+ raise IndexError if index < 0 || index >= @size
54
+ @connections[index] ||= Connection.new(@client.getClient(index))
32
55
  end
33
56
 
34
- # @return [Connection] random connection
57
+ # Get the random node connection
58
+ # @return [Connection] node connection
35
59
  def random_connection
36
- @nodes.sample
60
+ self[rand(0...size)]
37
61
  end
38
62
 
39
- def register_single contract
40
- random_connection.register_single contract
63
+ # Get several random connections
64
+ # @param [Numeric] number of connections to get
65
+ # @return [Array(Connection)] array of connections to random (non repeating) nodes
66
+ def random_connections number
67
+ (0...size).to_a.sample(number).map {|n| self[n]}
41
68
  end
42
69
 
43
- # Perform fats consensus state check. E.g. it scans up to 2/3 of the network until
44
- # the positive or negative consensus will be found. So far you can only rely on
45
- # result.approved? as it returns some last node result which, though, match the
46
- # consensus. Aggregation of parameters is under way.
70
+ # Perform fast consensus state check with a given trust level, as the fraction of the whole network size.
71
+ # It checks the network nodes randomly until get enough positive or negative states. The lover the required
72
+ # trust level is, the faster the answer will be found.
47
73
  #
48
- # @param [Contract | HashId] obj to check
49
- # @return [ContractState] of some final node check It does not aggregates (yet)
50
- def get_state obj
74
+ # @param [Contract | HashId] obj contract to check
75
+ # @param [Object] trust level, should be between 0.1 (10% of network) and 0.9 (90% of the network)
76
+ # @return [ContractState] of some final node check It does not calculates average time (yet)
77
+ def get_state obj, trust: 0.3
78
+ raise ArgumentError, "trusst must be in 0.1..0.9 range" if trust < 0.1 || trust > 0.9
51
79
  result = Concurrent::IVar.new
52
- negative_votes = Concurrent::AtomicFixnum.new(@nodes.size * 11 / 100)
53
- positive_votes = Concurrent::AtomicFixnum.new(@nodes.size * 30 / 100)
54
- retry_with_timeout(20, 3) {
55
- random_connections(@nodes.size).par.each {|conn|
80
+ negative_votes = Concurrent::AtomicFixnum.new((size * 0.1).round + 1)
81
+ positive_votes = Concurrent::AtomicFixnum.new((size * trust).round)
82
+
83
+ # consensus-finding conveyor: we chek connections in batches in parallel until get
84
+ # some consensus. We do not wait until all of them will answer
85
+ (0...size).to_a.shuffle.each {|index|
86
+ Thread.start {
56
87
  if result.incomplete?
57
- if (state = conn.get_state(obj)).approved?
88
+ if (state = self[index].get_state(obj)).approved?
58
89
  result.try_set(state) if positive_votes.decrement < 0
59
90
  else
60
91
  result.try_set(state) if negative_votes.decrement < 0
61
92
  end
62
93
  end
63
94
  }
64
- result.value
65
95
  }
96
+ result.value
66
97
  end
67
98
 
68
- # @return [Array(Connection)] array of count randomly selected connections
69
- def random_connections count = 1
70
- @nodes.sample(count)
71
- end
72
-
73
- def [] name
74
- @nodes.find {|x| x.url =~ /#{name}/}
75
- end
76
-
77
- private
78
-
79
- # Rescan the network collecting the networ map comparing results from random 70% of nodes.
80
- def scan_network
81
- # Todo: cache known nodes
82
- root_nodes = (1..30).map {|n| "http://node-#{n}-com.utoken.io:8080/network"}
83
-
84
- # We scan random 70% for consensus
85
- n = root_nodes.size * 0.7
86
-
87
- candidates = {}
88
- root_nodes.sample(n).par.each {|path|
89
- retry_with_timeout(5, 3) {
90
- SmartHash.new(Boss.unpack open(path).read).response.nodes.each {|data|
91
- ni = NodeInfo.new(data)
92
- (candidates[ni] ||= ni).increment_rate
93
- }
94
- }
99
+ # Register a single contract (on private network or if you have white key allowing free operations)
100
+ # on a random node. Client must check returned contract state. It requires "open" network or special
101
+ # key that has a right to register contracts without payment.
102
+ #
103
+ # When retrying, randpm nodes are selected.
104
+ #
105
+ # @param [Contract] contract must be sealed ({Contract#seal})
106
+ #
107
+ # @return [ContractState] of the result. Could contain errors.
108
+ def register_single(contract, timeout: 45, max_retries: 3)
109
+ retry_with_timeout(timeout, max_retries) {
110
+ ContractState.new(random_connection.register_single(contract, timeout / max_retries * 1000 - 100))
95
111
  }
96
- nodes = candidates.values.group_by(&:url)
97
- .transform_values!(&:sort)
98
- # We roughly assume the full network size as:
99
- network_max_size = nodes.size
100
- # Refine result: takes most voted nodes and only these with 80% consensus
101
- # and map it to Connection objects
102
- min_rate = n * 0.8
103
- @nodes = nodes.values.map {|v| v[-1]}.delete_if {|v| v.rate < min_rate}
104
- .map {|ni| Connection.new(self, ni)}
105
- raise NetworkError, "network is not ready" if @nodes.size < network_max_size * 0.9
106
- end
107
- end
108
-
109
- # The node information
110
- class NodeInfo
111
- attr :number, :packed_key, :url
112
-
113
- # constructs from binary packed data
114
- def initialize(data)
115
- @data, @number, @url, @packed_key = data, data.number, data.url, data.packed_key
116
- @rate = Concurrent::AtomicFixnum.new
117
112
  end
118
113
 
119
- # currently collected approval rate
120
- def rate
121
- @rate.value
122
- end
123
-
124
- # increase approval rate
125
- def increment_rate
126
- @rate.increment
127
- end
128
-
129
- # check information euqlity
130
- def == other
131
- # number == other.number && packed_key == other.packed_key && url == other.url
132
- url == other&.url && packed_key == other&.packed_key && url == other&.url
133
- end
134
-
135
- # allows to use as hash key
136
- def hash
137
- @url.hash + @packed_key.hash
138
- end
114
+ end
139
115
 
140
- # to use as hash key
141
- def eql?(other)
142
- self == other
143
- end
116
+ class Connection
144
117
 
145
- # ordered by approval rate
146
- def < other
147
- rate < other.rate
118
+ def initialize umi_client
119
+ @client = umi_client
148
120
  end
149
121
 
150
- def name
151
- @name ||= begin
152
- url =~ /^https{0,1}:\/\/([^:]*)/
153
- $1
154
- end
122
+ # Check the connected node is alive. It is adivesd to call {restart} on nodes that return false on pings
123
+ # to reestablish connection.
124
+ #
125
+ # @return true if it is ok
126
+ def ping
127
+ @client.ping
155
128
  end
156
- end
157
-
158
-
159
- # Access to the single node using universa client protocol.
160
- #
161
- class Connection
162
- include Universa
163
129
 
164
- # create connection for a given clietn. Don't call it direcly, use
165
- # {Client.random_connection} or {Client.random_connections} instead. The client implements
166
- # lazy initialization so time-consuming actual connection will be postponed until
167
- # needed.
168
- #
169
- # @param [Client] client instance to be bound to
170
- # @param [NodeInfo] node_info to connect to
171
- def initialize(client, node_info)
172
- @client, @node_info = client, node_info
130
+ # Attempt to reestablish connection to the node
131
+ def restart
132
+ @client.restart
173
133
  end
174
134
 
175
- # executes ping. Just to ensure connection is alive. Node answers 'sping' => 'spong' hash.
176
- # 's' states that secure layer of client protocol is used, e.g. with mutual identification and
177
- # ciphering.
178
- def ping
179
- execute(:sping)
135
+ # node url (IP-based)
136
+ def url
137
+ @url ||= @client.get_url
180
138
  end
181
139
 
182
140
  # Register a single contract (on private network or if you have white key allowing free operations)
183
- # on a single node.
141
+ # with the current node. Client must check returned contract state. It requires "open" network or special
142
+ # key that has a right to register contracts without payment.
184
143
  #
185
144
  # @param [Contract] contract must be sealed ({Contract#seal})
145
+ #
186
146
  # @return [ContractState] of the result. Could contain errors.
187
- def register_single(contract)
188
- retry_with_timeout(15, 3) {
189
- result = ContractState.new(execute "approve", packedItem: contract.packed)
190
- while result.is_pending
191
- sleep(0.1)
192
- result = get_state contract
193
- end
194
- result
195
- }
147
+ def register_single(contract, timeout = 25)
148
+ ContractState.new(@client.register(contract.packed, timeout * 1000))
196
149
  end
197
150
 
198
151
  # Get contract or hashId state from this single node
@@ -207,79 +160,51 @@ module Universa
207
160
  else
208
161
  raise ArgumentError, "bad argument, want Contract or HashId"
209
162
  end
210
- ContractState.new(execute "getState", itemId: id)
211
- end
212
-
213
-
214
- # Execute Universa Node client protocol command with optional keyword arguments that will be passed
215
- # to the node.
216
- #
217
- # @param [String|Symbol] name of the command
218
- # @param kwargs arguments to call
219
- # @return [SmartHash] with the command result
220
- def execute(name, **kwargs)
221
- connection.command name.to_s, *kwargs.to_a.flatten
222
- end
223
-
224
- # def stats days=0
225
- # connection.getStats(days.to_i)
226
- # end
227
-
228
- def url
229
- @node_info.url
230
- end
231
-
232
- def name
233
- @node_info.name
234
- end
235
-
236
- def number
237
- @node_info.number
238
- end
239
-
240
- def to_s
241
- "Conn<#{@node_info.url}>"
163
+ ContractState.new(@client.getState(id))
242
164
  end
243
165
 
244
166
  def inspect
245
- to_s
167
+ "<Universa::Connection:#{url}"
246
168
  end
247
169
 
248
- protected
249
-
250
- def connection
251
- @connection ||= retry_with_timeout(15, 3) {
252
- conn = Service.umi.instantiate("com.icodici.universa.node2.network.Client",
253
- @node_info.url,
254
- @client.private_key,
255
- nil,
256
- false)
257
- .getClient(@node_info.number - 1)
258
- conn
259
- }
170
+ def to_s
171
+ inspect
260
172
  end
261
173
 
262
174
  end
263
175
 
176
+ # The state of some contract reported by thee network. It is a convenience wrapper around Universa
177
+ # ItemState structure.
264
178
  class ContractState
265
179
  def initialize(universa_contract_state)
266
180
  @source = universa_contract_state
267
181
  end
268
182
 
183
+ # get errors reported by the network
184
+ # @return [Array(String)] possibly empty array
269
185
  def errors
270
- @source.errors&.map &:to_s
186
+ @_errors ||= @source.errors&.map(&:to_s) || []
271
187
  rescue
272
188
  "failed to extract errors: #$!"
273
189
  end
274
190
 
191
+ # @return true if the state contain errors
192
+ def errors?
193
+ !errors.empty?
194
+ end
195
+
196
+ # @return ItemState structure reported by the UMI
275
197
  def state
276
- @source.itemResult.state
198
+ @source.state
277
199
  end
278
200
 
201
+ # Check that state us +PENDING+. Pending state is neither approved nor rejected.
202
+ # @return true if this state is one of the +PENDING+ states
279
203
  def is_pending
280
204
  state.start_with?('PENDING')
281
205
  end
282
206
 
207
+ # @return true if the contract state was approved
283
208
  def is_approved
284
209
  case state
285
210
  when 'APPROVED', 'LOCKED'
@@ -289,16 +214,18 @@ module Universa
289
214
  end
290
215
  end
291
216
 
217
+ # same as {is_approved}
292
218
  def approved?
293
219
  is_approved
294
220
  end
295
221
 
222
+ # same as {pending}
296
223
  def pending?
297
224
  is_pending
298
225
  end
299
226
 
300
227
  def to_s
301
- "ContractState:#{state}"
228
+ "<ContractState:#{state}>"
302
229
  end
303
230
 
304
231
  def inspect
@@ -1,7 +1,7 @@
1
1
  require 'forwardable'
2
2
  require_relative './entry'
3
3
 
4
- # Filesystem-based storage. See {FileStore}.
4
+ # Filesystem-based storage. See {FileStore}. Under reconsidering, please do not use it yet.
5
5
  module Universa::FSStore
6
6
 
7
7
  # Simple file-based store that could be efficiently user with per-file cloud storages like Dropbox,
@@ -15,7 +15,7 @@ module Universa
15
15
  @config = SmartHash.new path: nil
16
16
  @known_proxies = {}
17
17
  [Contract, PrivateKey, PublicKey, KeyAddress, HashId, Binder, Role, ChangeOwnerPermission, RevokePermission,
18
- SplitJoinPermission].each {|klass| register_proxy klass}
18
+ SplitJoinPermission, UmiClient].each {|klass| register_proxy klass}
19
19
  end
20
20
 
21
21
  # Implementation of {Service.configure}
@@ -82,8 +82,8 @@ module Universa
82
82
  # the remote to create remote instance.
83
83
  class RemoteAdapter < Delegator
84
84
 
85
- # Instantiate new proxy object passing arguments to the remote constructor. The UMO host will try
86
- # ot find overloaded constructor that matches the arguments.
85
+ # Instantiate new proxy object passing arguments to the remote constructor. The UMI host will try
86
+ # to find overloaded constructor that matches the arguments.
87
87
  #
88
88
  # @param [*Any] args any arguments that remote constructor may accept.
89
89
  def initialize(*args)
@@ -0,0 +1,6 @@
1
+ class USettings
2
+
3
+ include Singleton
4
+
5
+
6
+ end
@@ -90,6 +90,13 @@ module Universa
90
90
  @version.version
91
91
  end
92
92
 
93
+ # @return Universa network library core version
94
+ def core_version
95
+ @core_version ||= begin
96
+ invoke_static "Core", "VERSION"
97
+ end
98
+ end
99
+
93
100
  # Create instance of some Universa Java API class, for example 'Contract', passing any arguments
94
101
  # to its constructor. The returned reference could be used much like local instance, nu the actual
95
102
  # work will happen in the child process. Use references as much as possible as they take all the
@@ -235,7 +242,7 @@ module Universa
235
242
  # convert ruby arguments array to corresponding UMI values
236
243
  def prepare_args args
237
244
  raise "pp bug" if args == [:pretty_print] # this often happens whilte tracing
238
- args.map {|x| prepare x }
245
+ args.map {|x| prepare x}
239
246
  end
240
247
 
241
248
  # convert single argument to UMI value to pass
@@ -246,7 +253,7 @@ module Universa
246
253
  case x
247
254
  when Array
248
255
  # deep convert all array items
249
- x.map{|a| prepare a }
256
+ x.map {|a| prepare a}
250
257
  when Set
251
258
  # Make a Java Set
252
259
  r = call("instantiate", "Set", x.to_a.map {|i| i._as_umi_arg(self)})
@@ -1,4 +1,4 @@
1
1
  module Universa
2
2
  # Current gem version
3
- VERSION = "0.2.6"
3
+ VERSION = "0.3.1"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: universa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergeych
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-26 00:00:00.000000000 Z
11
+ date: 2019-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: farcall
@@ -130,20 +130,22 @@ files:
130
130
  - bin/setup
131
131
  - bin/umi/bin/umi
132
132
  - bin/umi/bin/umi.bat
133
+ - bin/umi/lib/com.eclipsesource.minimal-json.minimal-json-0.9.4.jar
133
134
  - bin/umi/lib/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar
134
135
  - bin/umi/lib/com.fasterxml.jackson.core.jackson-core-2.8.11.jar
135
136
  - bin/umi/lib/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar
136
137
  - bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar
137
138
  - bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar
138
- - bin/umi/lib/com.icodici.common_tools-3.8.8.jar
139
- - bin/umi/lib/com.icodici.crypto-3.8.8.jar
139
+ - bin/umi/lib/com.icodici.common_tools-3.9.9.jar
140
+ - bin/umi/lib/com.icodici.crypto-3.9.9.jar
140
141
  - bin/umi/lib/com.icodici.nanohttpd-2.1.0.jar
141
- - bin/umi/lib/com.icodici.umi-0.8.19.jar
142
- - bin/umi/lib/com.icodici.universa_core-3.8.8.jar
142
+ - bin/umi/lib/com.icodici.umi-0.8.29.jar
143
+ - bin/umi/lib/com.icodici.universa_core-3.9.9.jar
143
144
  - bin/umi/lib/com.madgag.spongycastle.core-1.58.0.0.jar
144
145
  - bin/umi/lib/com.squareup.jnagmp.jnagmp-2.0.0.jar
145
146
  - bin/umi/lib/com.typesafe.play.play-functional_2.12-2.6.10.jar
146
147
  - bin/umi/lib/com.typesafe.play.play-json_2.12-2.6.10.jar
148
+ - bin/umi/lib/joda-time.joda-time-2.9.9.jar
147
149
  - bin/umi/lib/net.java.dev.jna.jna-4.5.1.jar
148
150
  - bin/umi/lib/net.java.dev.jna.jna-platform-4.5.0.jar
149
151
  - bin/umi/lib/net.sf.jopt-simple.jopt-simple-4.9.jar
@@ -167,6 +169,7 @@ files:
167
169
  - lib/universa/stored_contract.rb
168
170
  - lib/universa/string_utils.rb
169
171
  - lib/universa/tools.rb
172
+ - lib/universa/u_settings.rb
170
173
  - lib/universa/umi.rb
171
174
  - lib/universa/version.rb
172
175
  - lib/universa/weak_reference.rb