universa 0.1.9 → 0.2.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 +4 -4
- data/README.md +12 -0
- data/lib/universa.rb +3 -0
- data/lib/universa/binder.rb +8 -2
- data/lib/universa/chain_store.rb +54 -0
- data/lib/universa/client.rb +4 -3
- data/lib/universa/contract.rb +56 -12
- data/lib/universa/errors.rb +10 -0
- data/lib/universa/fs_store/entry.rb +118 -0
- data/lib/universa/fs_store/file_store.rb +63 -0
- data/lib/universa/stored_contract.rb +76 -0
- data/lib/universa/tools.rb +11 -9
- data/lib/universa/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff86a735f983f4cb94e6ca82be229c8c47749d975483fe52d11972a8664853d8
|
4
|
+
data.tar.gz: f1625ae689ba6bd1ff017c2a3926e16e3b6efcc71f90f7896b60ccce19839413
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd4b45a562f5340511e659fb1019642599b74d431cdb5c8277a168e014ac1c085518798232d6c156de43377a3bdb3eec819ff935518bd107aef65726515f60db
|
7
|
+
data.tar.gz: 00a4544555433540ca9317ee4ce3bb7a090c649b5489809b364e79a36d784d4905f2af5b42534ade5b79b809ba19fe1d98a63ea784aff4cb19bf0aeb3af514ca
|
data/README.md
CHANGED
@@ -6,6 +6,18 @@ for direct access to remote objects.
|
|
6
6
|
This is an under-construction official gem from [Universa][universa] to facilitate access to the
|
7
7
|
Java library using Universa's UMI protocol.
|
8
8
|
|
9
|
+
## News
|
10
|
+
|
11
|
+
- alfa version of the local FS-based contract store.
|
12
|
+
- ability to edit `contract.state` and `contract.transactional` in new revisions.
|
13
|
+
- fixed errors with interchange builder and set based objects
|
14
|
+
- ruby sugar for Universa native classes: Role, Adapter, Contract, Binder, HashId.
|
15
|
+
- Contract creation, revocation, changing owner in ruby way
|
16
|
+
- Network operation for white keys/private networks: parallel state check, contract recistration.
|
17
|
+
|
18
|
+
This gem is already used in new Universa projects and is being actively tested.
|
19
|
+
|
20
|
+
|
9
21
|
## Installation
|
10
22
|
|
11
23
|
### Prerequisites
|
data/lib/universa.rb
CHANGED
data/lib/universa/binder.rb
CHANGED
@@ -68,8 +68,8 @@ module Universa
|
|
68
68
|
end
|
69
69
|
|
70
70
|
# @return an array of values returned by the block
|
71
|
-
# @
|
72
|
-
def map
|
71
|
+
# @yield [key,value] pairs.
|
72
|
+
def map(&block)
|
73
73
|
keys.map {|k| block.call [k, __getobj__.get(k)]}
|
74
74
|
end
|
75
75
|
|
@@ -86,7 +86,13 @@ module Universa
|
|
86
86
|
|
87
87
|
end
|
88
88
|
|
89
|
+
# enhance Hash with UMI access convenience methods.
|
89
90
|
class Hash
|
91
|
+
# Convert the hash to the {}Binder} stored in the remote side and suitable for
|
92
|
+
# Universa UMI calls.
|
93
|
+
#
|
94
|
+
# @return [Binder] constructed reference to the remotely created Binder.
|
95
|
+
#
|
90
96
|
def to_binder
|
91
97
|
Binder.of self
|
92
98
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Universa
|
4
|
+
|
5
|
+
# The storage interface capable to store contracts in chains, providing search and attributes.
|
6
|
+
# This class is not a store itself but the base class for it, having common boilerplate and
|
7
|
+
# sort of interface to implement.
|
8
|
+
class ChainStore
|
9
|
+
|
10
|
+
# Save contract to the store. When this method returns, the contract must me already stored.
|
11
|
+
# If the contract with such hasId is already stored, just returns it.
|
12
|
+
#
|
13
|
+
# @param [Object] contract to store
|
14
|
+
# @return [StoredContract] for this contract
|
15
|
+
def store_contract(contract)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
# Same as {#store_contract} but returns store
|
20
|
+
# @param [Contract] contract to add
|
21
|
+
# @return [ChainStore] self
|
22
|
+
def <<(contract)
|
23
|
+
store_contract(contract)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Contract] with the corresponding id or nil
|
28
|
+
# @param [HashId] hash_id instance to look for
|
29
|
+
def find_by_id(hash_id)
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
|
33
|
+
# Count contracts in the store. This operation could be slow.
|
34
|
+
def count
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [Contract] with the corresponding id or raise.
|
39
|
+
# @param [HashId] hash_id instance to look for
|
40
|
+
# @raise [NotFoundError]
|
41
|
+
def find_by_id! hash_id
|
42
|
+
find_by_id(hash_id) or raise NotFoundError
|
43
|
+
end
|
44
|
+
|
45
|
+
# Find all contracts with this parent id.
|
46
|
+
# @param [HashId] hash_id of the parent contract
|
47
|
+
# @return [Array] all the contracts that match this criterion
|
48
|
+
def find_by_parent(hash_id)
|
49
|
+
raise NotImplementedError
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/lib/universa/client.rb
CHANGED
@@ -172,9 +172,9 @@ module Universa
|
|
172
172
|
# Register a single contract (on private network or if you have white key allowing free operations)
|
173
173
|
# on a single node.
|
174
174
|
#
|
175
|
-
# @param [Contract] contract
|
175
|
+
# @param [Contract] contract must be sealed ({Contract#seal})
|
176
176
|
# @return [ContractState] of the result. Could contain errors.
|
177
|
-
def register_single
|
177
|
+
def register_single(contract)
|
178
178
|
retry_with_timeout(15, 3) {
|
179
179
|
result = ContractState.new(execute "approve", packedItem: contract.packed)
|
180
180
|
while result.is_pending
|
@@ -205,8 +205,9 @@ module Universa
|
|
205
205
|
# to the node.
|
206
206
|
#
|
207
207
|
# @param [String|Symbol] name of the command
|
208
|
+
# @param kwargs arguments to call
|
208
209
|
# @return [SmartHash] with the command result
|
209
|
-
def execute
|
210
|
+
def execute(name, **kwargs)
|
210
211
|
connection.command name.to_s, *kwargs.to_a.flatten
|
211
212
|
end
|
212
213
|
|
data/lib/universa/contract.rb
CHANGED
@@ -34,11 +34,12 @@ module Universa
|
|
34
34
|
invoke_static 'with_digest', digest_bytes
|
35
35
|
end
|
36
36
|
|
37
|
-
# Construct from string representation of the ID, not to confuse with binary one.
|
37
|
+
# Construct from string representation of the ID, not to confuse with binary one. This method takes both
|
38
|
+
# regular base64 representation and RFC3548 url-safe modification, as from {#to_url_safe_string}.
|
38
39
|
#
|
39
40
|
# @param [String] string_id id string representation, like from +hash_id_instance.to_s+. See {#to_s}.
|
40
41
|
def self.from_string(string_id)
|
41
|
-
string_id.force_encoding
|
42
|
+
string_id.force_encoding('utf-8').gsub('-','+').gsub('_','/')
|
42
43
|
invoke_static 'with_digest', string_id
|
43
44
|
end
|
44
45
|
|
@@ -57,6 +58,28 @@ module Universa
|
|
57
58
|
def to_s
|
58
59
|
Base64.encode64(get_digest).gsub(/\s/, '')
|
59
60
|
end
|
61
|
+
|
62
|
+
# Converts to URL-safe varianot of base64, as RFC 3548 suggests:
|
63
|
+
# the 63:nd / character with the underscore _
|
64
|
+
# the 62:nd + character with the minus -
|
65
|
+
#
|
66
|
+
# Could be decoded safely back with {HashId.from_string} but not (most likely) with JAVA API itself
|
67
|
+
# @return [String] RFC3548 modified base64
|
68
|
+
def to_url_safe_string
|
69
|
+
Base64.encode64(get_digest).gsub(/\s/, '').gsub('/','_').gsub('+', '-')
|
70
|
+
end
|
71
|
+
|
72
|
+
# To use it as a hash key_address.
|
73
|
+
# @return hash calculated over the digest bytes
|
74
|
+
def hash
|
75
|
+
bytes.hash
|
76
|
+
end
|
77
|
+
|
78
|
+
# To use it as a hash key_address. Same as this == other.
|
79
|
+
def eql? other
|
80
|
+
self == other
|
81
|
+
end
|
82
|
+
|
60
83
|
end
|
61
84
|
|
62
85
|
# Universa contract adapter.
|
@@ -66,17 +89,17 @@ module Universa
|
|
66
89
|
# Create simple contract with preset critical parts:
|
67
90
|
#
|
68
91
|
# - expiration set to 90 days unless specified else
|
69
|
-
# - issuer role is set to the address of the issuer
|
92
|
+
# - issuer role is set to the address of the issuer key_address, short ot long
|
70
93
|
# - creator role is set as link to issuer
|
71
94
|
# - owner role is set as link to issuer
|
72
95
|
# - change owner permission is set to link to owner
|
73
96
|
#
|
74
|
-
# The while contract is then signed by the issuer
|
97
|
+
# The while contract is then signed by the issuer key_address. Not that it will not seal it: caller almost always
|
75
98
|
# will add more data before it, then must call #seal().
|
76
99
|
#
|
77
100
|
# @param [PrivateKey] issuer_key also will be used to sign it
|
78
101
|
# @param [Time] expires_at defaults to 90 days
|
79
|
-
# @param [Boolean] use_short_address set to true to use short address of the issuer
|
102
|
+
# @param [Boolean] use_short_address set to true to use short address of the issuer key_address in the role
|
80
103
|
# @return [Contract] simple contact, not sealed
|
81
104
|
def self.create issuer_key, expires_at: (Time.now + 90 * 24 * 60 * 60), use_short_address: false
|
82
105
|
contract = Contract.new
|
@@ -92,6 +115,7 @@ module Universa
|
|
92
115
|
|
93
116
|
# Load from transaction pack
|
94
117
|
def self.from_packed packed
|
118
|
+
packed.nil? and raise ArgumentError, "packed contract required"
|
95
119
|
packed.force_encoding 'binary'
|
96
120
|
self.invoke_static "fromPackedTransaction", packed
|
97
121
|
end
|
@@ -124,8 +148,10 @@ module Universa
|
|
124
148
|
get_owner
|
125
149
|
end
|
126
150
|
|
127
|
-
|
128
|
-
|
151
|
+
# Set owner to the key_address, usable only in the simplest case where owner is the single address.
|
152
|
+
# @param [KeyAddress | PublicKey] key_address
|
153
|
+
def owner=(key_address)
|
154
|
+
set_owner_key key_address
|
129
155
|
end
|
130
156
|
|
131
157
|
# Shortcut for is_ok
|
@@ -134,16 +160,29 @@ module Universa
|
|
134
160
|
end
|
135
161
|
|
136
162
|
# shortcut for getHashId
|
163
|
+
# @return [HashId] of the contracr
|
137
164
|
def hash_id
|
138
|
-
|
165
|
+
getId()
|
166
|
+
end
|
167
|
+
|
168
|
+
# @return [HashId] of the origin contract
|
169
|
+
def origin
|
170
|
+
getOrigin()
|
139
171
|
end
|
140
172
|
|
141
|
-
#
|
173
|
+
# @return [HashId] pf the parent contracr
|
174
|
+
def parent
|
175
|
+
getParent()
|
176
|
+
end
|
177
|
+
|
178
|
+
# shortcut for get_expires_at. Get the contract expiration time.
|
142
179
|
def expires_at
|
143
180
|
get_expires_at
|
144
181
|
end
|
145
182
|
|
146
|
-
|
183
|
+
# set +expires_at+ field
|
184
|
+
# @param [Time] time when this contract will be expired, if yet +APPROVED+.
|
185
|
+
def expires_at=(time)
|
147
186
|
set_expires_at time
|
148
187
|
end
|
149
188
|
|
@@ -152,6 +191,7 @@ module Universa
|
|
152
191
|
@definition ||= get_definition.get_data
|
153
192
|
end
|
154
193
|
|
194
|
+
# Return +state+ binder. Shortcut for Java API +getStateData()+
|
155
195
|
def state
|
156
196
|
@state ||= getStateData()
|
157
197
|
end
|
@@ -175,7 +215,7 @@ module Universa
|
|
175
215
|
# Write helper for many token-like contracts containing state.data.amount. Saves value
|
176
216
|
# in state.data.anomount and properly encodes it so it will be preserved on packing.
|
177
217
|
#
|
178
|
-
# @param [Object] value
|
218
|
+
# @param [Object] value should be some representation of a number (also string)
|
179
219
|
def amount= (value)
|
180
220
|
state[:amount] = value.to_s.force_encoding('utf-8')
|
181
221
|
end
|
@@ -203,7 +243,11 @@ module Universa
|
|
203
243
|
getErrors.map {|e| "(#{e.object || ''}): #{e.error}"}.join(', ').strip
|
204
244
|
end
|
205
245
|
|
206
|
-
|
246
|
+
# Test that some set of keys could be used to perform some role.
|
247
|
+
#
|
248
|
+
# @param [String] name of the role to check
|
249
|
+
# @param [PublicKey] keys instances to check against
|
250
|
+
def can_perform_role(name, *keys)
|
207
251
|
getRole(name.to_s).isAllowedForKeys(Set.new keys.map {|x|
|
208
252
|
x.is_a?(PrivateKey) ? x.public_key : x
|
209
253
|
})
|
data/lib/universa/errors.rb
CHANGED
@@ -0,0 +1,118 @@
|
|
1
|
+
module Universa::FSStore
|
2
|
+
|
3
|
+
# The {StoredContract} implementation to work with {FileStore}.
|
4
|
+
#
|
5
|
+
# @!method name
|
6
|
+
# @return [String] the +contract.definition.data.name+ value or nil.
|
7
|
+
#
|
8
|
+
# @!method currency
|
9
|
+
# @return [String] the +contract.definition.data.currency+ value or nil.
|
10
|
+
#
|
11
|
+
# @!method amount
|
12
|
+
# @return [BigDecimal] +contract.state.data.amount+ or nil. See {Contract#amount} for more.
|
13
|
+
#
|
14
|
+
class Entry < Universa::StoredContract
|
15
|
+
|
16
|
+
extend Forwardable
|
17
|
+
|
18
|
+
# (see StoredContract#load)
|
19
|
+
def load(hash_id)
|
20
|
+
init_with_hash_id hash_id
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# initialize new instance with an existing contract
|
25
|
+
# @param [Contract] contract to store
|
26
|
+
def init_with_contract(contract)
|
27
|
+
self.contract = contract
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# initialize new instance with attributes YAML file
|
32
|
+
# @param [String] file_name of the +.unicon.yaml+ file
|
33
|
+
def load_from_yaml_file(file_name)
|
34
|
+
init_with_yaml_file_name file_name
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# (see StoredContract#hash_id)
|
39
|
+
def hash_id
|
40
|
+
@id
|
41
|
+
end
|
42
|
+
|
43
|
+
# (see StoredContract#contract=)
|
44
|
+
def contract= new_contract
|
45
|
+
@id = new_contract.hash_id
|
46
|
+
prepare_file_names
|
47
|
+
super
|
48
|
+
# we will always rewrite existing file to be sure it is correct
|
49
|
+
open(@file_name, 'wb') {|f| f << contract.packed}
|
50
|
+
# now we are to extract and rewrite attributes
|
51
|
+
load_attributes_from_contract # it will save them too
|
52
|
+
end
|
53
|
+
|
54
|
+
# Implement lazy load logic
|
55
|
+
# @return [Contract] instance loaded at first call only
|
56
|
+
def contract
|
57
|
+
# load it if it is not
|
58
|
+
self.packed_contract = open(@file_name, 'rb') {|f| f.read} unless has_contract?
|
59
|
+
# @attributes must already be set
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
def_delegators :@attributes, :name, :currency, :amount
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
# initialize instance for an existing file. Should be a contract already stored in the connected store.
|
68
|
+
# @param [Object] hash_id to construct from
|
69
|
+
def init_with_hash_id(hash_id)
|
70
|
+
raise IllegalStateError, "already initialized" if @id
|
71
|
+
@id = hash_id
|
72
|
+
prepare_file_names
|
73
|
+
load_attributes_from_file
|
74
|
+
# attrs are already in the file so we need not to save them
|
75
|
+
end
|
76
|
+
|
77
|
+
# Load from attributes file name
|
78
|
+
def init_with_yaml_file_name file_name
|
79
|
+
@attr_file_name = file_name
|
80
|
+
load_attributes_from_file
|
81
|
+
prepare_file_names
|
82
|
+
end
|
83
|
+
|
84
|
+
# save attributes to .yaml file
|
85
|
+
def save_attributes
|
86
|
+
open(@attr_file_name, 'w') {|f| YAML.dump(@attributes, f)}
|
87
|
+
end
|
88
|
+
|
89
|
+
# load attributes from a contract (already assigned) and store them in the .yaml file
|
90
|
+
def load_attributes_from_contract
|
91
|
+
state = contract.state
|
92
|
+
definition = contract.definition
|
93
|
+
@attributes = SmartHash.new({
|
94
|
+
id: hash_id.to_s,
|
95
|
+
parent: parent&.to_s,
|
96
|
+
origin: origin.to_s,
|
97
|
+
name: definition.name,
|
98
|
+
currency: definition.currency,
|
99
|
+
amount: state.amount
|
100
|
+
})
|
101
|
+
save_attributes
|
102
|
+
end
|
103
|
+
|
104
|
+
# load attributes from the .yaml file
|
105
|
+
def load_attributes_from_file
|
106
|
+
@attributes = SmartHash.new(YAML.load_file(@attr_file_name))
|
107
|
+
@id = HashId.from_string @attributes.id
|
108
|
+
end
|
109
|
+
|
110
|
+
# prepare file name fields (@file_name and @attr_file_name)
|
111
|
+
# @param [HashId] hash_id or ni to use one already set in @id
|
112
|
+
def prepare_file_names(hash_id = nil)
|
113
|
+
@file_name = "#{chain_store.root}/#{@id.to_url_safe_string[0..27]}.unicon"
|
114
|
+
@attr_file_name = "#@file_name.yaml"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require_relative './entry'
|
3
|
+
|
4
|
+
# Filesystem-based storage. See {FileStore}.
|
5
|
+
module Universa::FSStore
|
6
|
+
|
7
|
+
# Simple file-based store that could be efficiently user with per-file cloud storages like Dropbox,
|
8
|
+
# Google Disk, NextCloud and like.
|
9
|
+
#
|
10
|
+
# Notes to developers:
|
11
|
+
#
|
12
|
+
# - attributes are eager loaded: should always be contructed from contract or from file
|
13
|
+
# - contract is lazy loaded
|
14
|
+
class FileStore < Universa::ChainStore
|
15
|
+
|
16
|
+
# [String] The file store root path
|
17
|
+
attr :root
|
18
|
+
|
19
|
+
# Construct store in the path supplied. If the path is not empty, it will be scanned for stored contracts.
|
20
|
+
# @param [String] root_path of the store, must exist.
|
21
|
+
def initialize(root_path)
|
22
|
+
@root = root_path
|
23
|
+
@root = @root[0...-1] while (@root[-1] == '/')
|
24
|
+
init_cache
|
25
|
+
end
|
26
|
+
|
27
|
+
# (see ChainStore#store_contract)
|
28
|
+
def store_contract contract
|
29
|
+
entry = FSStore::Entry.new(self)
|
30
|
+
entry = entry.init_with_contract(contract)
|
31
|
+
add_to_cache entry
|
32
|
+
end
|
33
|
+
|
34
|
+
# (see ChainStore#find_by_id)
|
35
|
+
def find_by_id hash_id
|
36
|
+
@cache[hash_id]
|
37
|
+
end
|
38
|
+
|
39
|
+
# (see ChainStore#count)
|
40
|
+
def count
|
41
|
+
@cache.size
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
# scan the root folder for attribute files and store them in the cache
|
47
|
+
def init_cache
|
48
|
+
@cache = {}
|
49
|
+
Dir[@root + "/*.unicon.yaml"].each {|name|
|
50
|
+
add_to_cache Entry.new(self).load_from_yaml_file(name)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# add single entry to the cache
|
55
|
+
# @param [Entry] entry to add. Could have contract not yet loaded but should be configured with attributes.
|
56
|
+
def add_to_cache(entry)
|
57
|
+
raise ArgumentError, "entry can't be nil" unless entry
|
58
|
+
@cache[entry.hash_id] = entry
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Universa
|
2
|
+
|
3
|
+
# this is a base class for a contract stored in some contract chain. The implementation
|
4
|
+
# must inherit and implement its {#load} and {#save} methods at least. To do it,
|
5
|
+
# inherit and implement {ChainStore} to work with it.
|
6
|
+
#
|
7
|
+
# Notable features:
|
8
|
+
#
|
9
|
+
# - contract could be assigned only once, no matter how, so its fields could be cached.
|
10
|
+
# - origin, hash_id and parent are cached. So other contract parameters should be.
|
11
|
+
#
|
12
|
+
class StoredContract
|
13
|
+
|
14
|
+
# {ChainStore} instance to which it is connected
|
15
|
+
attr :chain_store
|
16
|
+
# {Contract} instance stored in it. Can be lazy-loaded
|
17
|
+
attr :contract
|
18
|
+
# {HashId} of the {#contract}
|
19
|
+
attr :hash_id
|
20
|
+
|
21
|
+
# @return [HashId] {#contract}.origin. See {Contract#origin}
|
22
|
+
def origin
|
23
|
+
@origin ||= @contract.origin
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [HashId] {#contract}.origin. See {Contract#parent}
|
27
|
+
def parent
|
28
|
+
@parent ||= @contract.parent
|
29
|
+
end
|
30
|
+
|
31
|
+
# Construct implementation connected to a given store
|
32
|
+
# @param [ChainStore] chain_store descendant class
|
33
|
+
def initialize(chain_store)
|
34
|
+
@chain_store = chain_store
|
35
|
+
@chain_store.is_a?(ChainStore) or raise ArgumentError, "ChainStore instance required"
|
36
|
+
@chain_store = chain_store
|
37
|
+
end
|
38
|
+
|
39
|
+
# For implementation logic, in particular, to make lazy loads.
|
40
|
+
# @return true if the stored contract is loaded into this instance
|
41
|
+
def has_contract?
|
42
|
+
!@contract.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Shortcut for `contract.packed`. See {Contract#packed}
|
46
|
+
# @return [String] binary string with contained contract packed transaction.
|
47
|
+
def packed_contract
|
48
|
+
@contract.packed
|
49
|
+
end
|
50
|
+
|
51
|
+
# override it to save the contract in the connected contract chain.
|
52
|
+
def save
|
53
|
+
raise NotFoundError
|
54
|
+
end
|
55
|
+
|
56
|
+
# override it to load the contract from the connected contract chain.
|
57
|
+
def load hash_id
|
58
|
+
raise NotFoundError
|
59
|
+
end
|
60
|
+
|
61
|
+
# Assign contract to the instance.
|
62
|
+
# @param [Contracy] new_contract to store
|
63
|
+
def contract=(new_contract)
|
64
|
+
raise IllegalStateError, "contract can't be reassigned" if has_contract?
|
65
|
+
@contract = new_contract
|
66
|
+
@hash_id = @contract.hash_id
|
67
|
+
@origin = @parent = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# Convenience method. Unoacks and stores the contract.
|
71
|
+
def packed_contract=(new_packed_contract)
|
72
|
+
self.contract = Contract.from_packed(new_packed_contract)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
data/lib/universa/tools.rb
CHANGED
@@ -7,14 +7,16 @@ module Universa
|
|
7
7
|
class SmartHash < Farcall::SmartHash
|
8
8
|
end
|
9
9
|
|
10
|
-
def retry_with_timeout(max_timeout =
|
10
|
+
def retry_with_timeout(max_timeout = 25, max_times = 3, &block)
|
11
11
|
attempt = 0
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
begin
|
13
|
+
Timeout::timeout(max_timeout, &block)
|
14
|
+
rescue
|
15
|
+
attempt += 1
|
16
|
+
puts "timeout: retry (#$!): #{attempt}"
|
17
|
+
retry if attempt < max_times
|
18
|
+
raise
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
module Parallel
|
@@ -26,7 +28,7 @@ module Universa
|
|
26
28
|
|
27
29
|
@@pool = CachedThreadPool.new
|
28
30
|
|
29
|
-
# Enumerates in parallel all items. Like
|
31
|
+
# Enumerates in parallel all items. Like +Enumerable#each_with_index+, but requires block.
|
30
32
|
# Blocks until all items are processed.
|
31
33
|
#
|
32
34
|
# @param [Proc] block to call with (object, index) parameters
|
@@ -55,7 +57,7 @@ module Universa
|
|
55
57
|
each_with_index {|x, i| block.call(x)}
|
56
58
|
end
|
57
59
|
|
58
|
-
# Parallel version of the
|
60
|
+
# Parallel version of the +Enumerable#map+. Creates a new array containing the values returned by the block,
|
59
61
|
# using parallel execution in threads.
|
60
62
|
#
|
61
63
|
# @return new array containing the values returned by the block.
|
data/lib/universa/version.rb
CHANGED
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.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sergeych
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: farcall
|
@@ -154,11 +154,15 @@ files:
|
|
154
154
|
- exe/universa
|
155
155
|
- lib/universa.rb
|
156
156
|
- lib/universa/binder.rb
|
157
|
+
- lib/universa/chain_store.rb
|
157
158
|
- lib/universa/client.rb
|
158
159
|
- lib/universa/contract.rb
|
159
160
|
- lib/universa/errors.rb
|
161
|
+
- lib/universa/fs_store/entry.rb
|
162
|
+
- lib/universa/fs_store/file_store.rb
|
160
163
|
- lib/universa/keys.rb
|
161
164
|
- lib/universa/service.rb
|
165
|
+
- lib/universa/stored_contract.rb
|
162
166
|
- lib/universa/string_utils.rb
|
163
167
|
- lib/universa/tools.rb
|
164
168
|
- lib/universa/umi.rb
|
@@ -185,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
189
|
version: '0'
|
186
190
|
requirements: []
|
187
191
|
rubyforge_project:
|
188
|
-
rubygems_version: 2.7.
|
192
|
+
rubygems_version: 2.7.6
|
189
193
|
signing_key:
|
190
194
|
specification_version: 4
|
191
195
|
summary: Expose Universa Java API to ruby
|