universa 0.2.6 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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