casper_network 0.2.0 → 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/CONTRIBUTING.md +1 -0
- data/LICENSE +201 -0
- data/README.md +154 -0
- data/SECURITY.md +12 -0
- data/lib/casper_network.rb +200 -180
- data/lib/entity/auction_state.rb +36 -0
- data/lib/entity/bid.rb +24 -0
- data/lib/entity/bid_info.rb +51 -0
- data/lib/entity/delegator.rb +37 -0
- data/lib/entity/deploy.rb +44 -0
- data/lib/entity/deploy_approval.rb +23 -0
- data/lib/entity/deploy_executable.rb +9 -0
- data/lib/entity/deploy_hash.rb +16 -0
- data/lib/entity/deploy_header.rb +58 -0
- data/lib/entity/era_summary.rb +44 -0
- data/lib/entity/era_validator.rb +23 -0
- data/lib/entity/peer.rb +25 -0
- data/lib/entity/validator_weight.rb +23 -0
- data/lib/rpc/rpc_client.rb +227 -0
- data/lib/rpc/rpc_error.rb +79 -0
- data/spec/client_spec.rb +25 -0
- data/spec/mainnet_spec.rb +452 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/testnet_spec.rb +498 -0
- metadata +34 -7
@@ -0,0 +1,58 @@
|
|
1
|
+
module Casper
|
2
|
+
module Entity
|
3
|
+
class DeployHeader
|
4
|
+
|
5
|
+
# @param [String] account
|
6
|
+
# @param [Integer] timestamp
|
7
|
+
# @param [Integer] ttl
|
8
|
+
# @param [Integer] gas_price
|
9
|
+
# @param [String] body_hash
|
10
|
+
# @param [Array] dependencies
|
11
|
+
# @param [String] chain_name
|
12
|
+
def initialize(account, timestamp, ttl, gas_price, body_hash, dependencies, chain_name)
|
13
|
+
@account = account
|
14
|
+
@timestamp = timestamp
|
15
|
+
@ttl = ttl
|
16
|
+
@gas_price = gas_price
|
17
|
+
@body_hash = body_hash
|
18
|
+
@dependencies = dependencies
|
19
|
+
@chain_name = chain_name
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [String] account
|
23
|
+
def get_account
|
24
|
+
@account
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Integer] timestamp
|
28
|
+
def get_timestamp
|
29
|
+
@timestamp
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Integer] ttl
|
33
|
+
def get_ttl
|
34
|
+
@ttl
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Integer] gas_price
|
38
|
+
def get_gas_price
|
39
|
+
@gas_price
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String] body_hash
|
43
|
+
def get_body_hash
|
44
|
+
@body_hash
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Array] dependencies
|
48
|
+
def get_dependencies
|
49
|
+
@dependencies
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String] chain_name
|
53
|
+
def get_chain_name
|
54
|
+
@chain_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Casper
|
2
|
+
module Entity
|
3
|
+
class EraSummary
|
4
|
+
|
5
|
+
# @param [String] block_hash_
|
6
|
+
# @param [Integer] era_id_
|
7
|
+
# @param [StoredValue] stored_value_
|
8
|
+
# @param [String] state_root_hash_
|
9
|
+
# @param [String] merkle_proof_
|
10
|
+
def initialize(block_hash_, era_id_, stored_value_, state_root_hash_, merkle_proof_)
|
11
|
+
@block_hash = block_hash_
|
12
|
+
@era_id = era_id_
|
13
|
+
@stored_value = stored_value_
|
14
|
+
@state_root_hash = state_root_hash_
|
15
|
+
@merkle_proof = merkle_proof_
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] block_hash
|
19
|
+
def get_block_hash
|
20
|
+
@block_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Integer] era_id
|
24
|
+
def get_era_id
|
25
|
+
@era_id
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [StoredValue] StoredValue
|
29
|
+
def get_stored_value
|
30
|
+
@stored_value
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String] state_root_hash
|
34
|
+
def get_state_root_hash
|
35
|
+
@state_root_hash
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [String] merkle_proof
|
39
|
+
def get_merkle_proof
|
40
|
+
@merkle_proof
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Casper
|
2
|
+
module Entity
|
3
|
+
class EraValidator
|
4
|
+
|
5
|
+
# @param [Integer] era_id
|
6
|
+
# @param [Array<ValidatorWeight>] validator_weights
|
7
|
+
def initialize(era_id, validator_weights)
|
8
|
+
@era_id = era_id
|
9
|
+
@validator_weights = validator_weights
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Integer] era_id
|
13
|
+
def get_era_id
|
14
|
+
@era_id
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array<ValidatorWeight>] validator_weights
|
18
|
+
def get_validator_weights
|
19
|
+
@validator_weights
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/entity/peer.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Casper
|
2
|
+
module Entity
|
3
|
+
class Peer
|
4
|
+
|
5
|
+
# @param [Hash] peer
|
6
|
+
# @option peer [String] :node_id
|
7
|
+
# @option peer [String] :address
|
8
|
+
def initialize(peer = {})
|
9
|
+
@node_id = peer[:node_id]
|
10
|
+
@address = peer[:address]
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String] node_id
|
14
|
+
def get_node_id
|
15
|
+
@node_id
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] address
|
19
|
+
def get_address
|
20
|
+
@address
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Casper
|
2
|
+
module Entity
|
3
|
+
class ValidatorWeight
|
4
|
+
|
5
|
+
# @param [String] public_key
|
6
|
+
# @param [String] weight
|
7
|
+
def initialize(public_key, weight)
|
8
|
+
@public_key = public_key
|
9
|
+
@weight = weight
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String] public_key
|
13
|
+
def get_public_key
|
14
|
+
@public_key
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String] weight
|
18
|
+
def get_weight
|
19
|
+
@weight
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# casper_network.rb
|
2
|
+
require 'jimson'
|
3
|
+
require 'json'
|
4
|
+
require 'rdoc/rdoc'
|
5
|
+
require "ipaddress"
|
6
|
+
require 'resolv'
|
7
|
+
require 'rest-client'
|
8
|
+
require 'active_support/core_ext/hash/keys'
|
9
|
+
require 'timeout'
|
10
|
+
require_relative '../entity/peer.rb'
|
11
|
+
module Casper
|
12
|
+
# Class for interacting with the network via RPC
|
13
|
+
class RpcClient
|
14
|
+
attr_accessor :ip_address, :port, :url, :state_root_hash
|
15
|
+
|
16
|
+
# Constructor
|
17
|
+
# @param [String] ip_address
|
18
|
+
def initialize(ip_address)
|
19
|
+
@ip_address = ip_address
|
20
|
+
@url = "http://" + @ip_address + ":7777/rpc"
|
21
|
+
@state_root_hash = ""
|
22
|
+
@peer_array = []
|
23
|
+
@block_hash = ""
|
24
|
+
@deploy = {}
|
25
|
+
@node_status = {}
|
26
|
+
@block_transfers = []
|
27
|
+
@block_info = {}
|
28
|
+
@era_summary = {}
|
29
|
+
@balance_value = ""
|
30
|
+
@auction_state = {}
|
31
|
+
|
32
|
+
@peers = []
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array<Hash>] peers array
|
36
|
+
def info_get_peers
|
37
|
+
begin
|
38
|
+
status = Timeout::timeout(20) {
|
39
|
+
client = Jimson::Client.new(@url)
|
40
|
+
response = client.info_get_peers
|
41
|
+
response.deep_symbolize_keys!
|
42
|
+
@peer_array = response[:peers]
|
43
|
+
@peer_array.map { |item| @peers << Casper::Entity::Peer.new(item) }
|
44
|
+
# @peers[0].get_node_id
|
45
|
+
# @peers[0].get_node_id
|
46
|
+
# @peers[0].get_address
|
47
|
+
@peer_array
|
48
|
+
}
|
49
|
+
rescue Timeout::Error
|
50
|
+
'Timeout expired to retrieve peers!'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String] state_root_hash value
|
55
|
+
def chain_get_StateRootHash(block_hash = "")
|
56
|
+
begin
|
57
|
+
status = Timeout::timeout(10) {
|
58
|
+
client = Jimson::Client.new(@url)
|
59
|
+
result = client.chain_get_state_root_hash
|
60
|
+
@state_root_hash = result["state_root_hash"]
|
61
|
+
}
|
62
|
+
rescue
|
63
|
+
'Timeout expired to retrieve state_root_hash value!'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get information about a single deploy by hash.
|
68
|
+
# @param [String] deploy_hash
|
69
|
+
# @return [Hash] Deploy
|
70
|
+
def info_get_deploy(deploy_hash)
|
71
|
+
begin
|
72
|
+
status = Timeout::timeout(20) {
|
73
|
+
if (deploy_hash == "" || deploy_hash == nil)
|
74
|
+
return "Server error -32602: Invalid params"
|
75
|
+
end
|
76
|
+
client = Jimson::Client.new(@url)
|
77
|
+
response = client.info_get_deploy({"deploy_hash"=> deploy_hash })
|
78
|
+
@deploy = response["deploy"]
|
79
|
+
# @deploy.keys.each do |key|
|
80
|
+
# @deploy[(key.to_sym rescue key) || key] = @deploy.delete(key)
|
81
|
+
# end
|
82
|
+
@deploy
|
83
|
+
}
|
84
|
+
rescue
|
85
|
+
'Timeout expired to retrieve Deploy!'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Receive node status information
|
91
|
+
# @return node_status
|
92
|
+
def info_get_status
|
93
|
+
begin
|
94
|
+
status = Timeout::timeout(10) {
|
95
|
+
client = Jimson::Client.new(@url)
|
96
|
+
@node_status = client.info_get_status
|
97
|
+
}
|
98
|
+
rescue
|
99
|
+
'Timeout expired to retrieve node status information'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param [String] block_hash
|
104
|
+
# @return [Array<Hash>] block_transfers
|
105
|
+
def chain_get_block_transfers(block_hash = "")
|
106
|
+
begin
|
107
|
+
status = Timeout::timeout(5) {
|
108
|
+
client = Jimson::Client.new(@url)
|
109
|
+
response = client.chain_get_block_transfers({
|
110
|
+
"block_identifier" => {"Hash" => block_hash}
|
111
|
+
})
|
112
|
+
@block_transfers = response["transfers"]
|
113
|
+
@block_transfers
|
114
|
+
}
|
115
|
+
rescue
|
116
|
+
'Timeout expired to retrieve block_transfers'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# @param [String] block_hash
|
121
|
+
# @return [Hash] block_info
|
122
|
+
def chain_get_block(block_hash)
|
123
|
+
begin
|
124
|
+
state = Timeout::timeout(10) {
|
125
|
+
client = Jimson::Client.new(@url)
|
126
|
+
result = client.chain_get_block({"block_identifier" => {"Hash" => block_hash}})
|
127
|
+
@block_info = result["block"]
|
128
|
+
if (!@block_info.empty?() && @block_info["hash"] != block_hash)
|
129
|
+
raise("Returned block does not have a matching hash.")
|
130
|
+
else
|
131
|
+
@block_info
|
132
|
+
end
|
133
|
+
}
|
134
|
+
rescue
|
135
|
+
'Timeout expired to retrieve block_info'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# @param [String] block_hash
|
140
|
+
# @return [Hash] era_summary
|
141
|
+
def chain_get_eraInfo_by_SwitchBlock(block_hash)
|
142
|
+
begin
|
143
|
+
state = Timeout::timeout(60) {
|
144
|
+
client = Jimson::Client.new(@url)
|
145
|
+
response = client.chain_get_era_info_by_switch_block("block_identifier" => {"Hash" => block_hash})
|
146
|
+
@era_summary = response["era_summary"]
|
147
|
+
@era_summary
|
148
|
+
}
|
149
|
+
rescue
|
150
|
+
'Timeout expired to retrieve era_summary'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param [String] state_root_hash
|
155
|
+
# @param [String] key
|
156
|
+
# @param [Array] path
|
157
|
+
def state_get_item(state_root_hash, key, path)
|
158
|
+
begin
|
159
|
+
state = Timeout::timeout(20) {
|
160
|
+
client = Jimson::Client.new(@url)
|
161
|
+
response = client.state_get_item({
|
162
|
+
"state_root_hash" => state_root_hash,
|
163
|
+
"key" => key,
|
164
|
+
"path" => path
|
165
|
+
})
|
166
|
+
@stored_value = response["stored_value"]
|
167
|
+
@stored_value
|
168
|
+
}
|
169
|
+
rescue
|
170
|
+
'Timeout expired to retrieve stored_value'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# @param [String] state_root_hash
|
175
|
+
# @param [String] item_key
|
176
|
+
# @param [String] uref
|
177
|
+
def state_get_dictionary_item(state_root_hash, item_key, uref)
|
178
|
+
begin
|
179
|
+
state = Timeout::timeout(5) {
|
180
|
+
client = Jimson::Client.new(@url)
|
181
|
+
response = client.state_get_dictionary_item({
|
182
|
+
"state_root_hash" => state_root_hash,
|
183
|
+
"dictionary_identifier" => {'URef' =>
|
184
|
+
{'seed_uref' => uref, 'dictionary_item_key' => item_key} }})
|
185
|
+
@stored_value = response["stored_value"]
|
186
|
+
@stored_value
|
187
|
+
}
|
188
|
+
rescue
|
189
|
+
'Timeout expired to retrieve stored_value'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# @param [String] state_root_hash
|
194
|
+
# @param [String] balance_uref
|
195
|
+
def state_get_balance(state_root_hash, balance_uref)
|
196
|
+
begin
|
197
|
+
state = Timeout::timeout(5) {
|
198
|
+
client = Jimson::Client.new(@url)
|
199
|
+
response = client.state_get_balance({
|
200
|
+
"state_root_hash" => state_root_hash,
|
201
|
+
"purse_uref" => balance_uref
|
202
|
+
})
|
203
|
+
@balance_value = response["balance_value"]
|
204
|
+
@balance_value
|
205
|
+
}
|
206
|
+
rescue
|
207
|
+
'Timeout expired to retrieve balance_value'
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns current auction system contract information.
|
212
|
+
# @return [Hash] auction_state
|
213
|
+
def state_get_AuctionInfo
|
214
|
+
begin
|
215
|
+
state = Timeout::timeout(50) {
|
216
|
+
client = Jimson::Client.new(@url)
|
217
|
+
response = client.state_get_auction_info
|
218
|
+
@auction_state = response['auction_state']
|
219
|
+
@auction_state
|
220
|
+
}
|
221
|
+
rescue
|
222
|
+
'Timeout expired to retrieve auction_state information!'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
module Casper
|
3
|
+
module RpcError
|
4
|
+
class ErrorHandle
|
5
|
+
# @param [Integer] code
|
6
|
+
# @param [String] message
|
7
|
+
# @param [String] data
|
8
|
+
def initialize(code = 0, message = "", data = "")
|
9
|
+
@code = code
|
10
|
+
@message = message
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String] err
|
15
|
+
def self.invalid_param
|
16
|
+
@code = -32602
|
17
|
+
@message = "Invalid params"
|
18
|
+
@err = "Server error #{@code}: #{@message}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] url
|
22
|
+
# @return [String]
|
23
|
+
def error_handling(url)
|
24
|
+
begin
|
25
|
+
response = RestClient.get(url)
|
26
|
+
parsed = JSON.parse(response)
|
27
|
+
# p parsed
|
28
|
+
rescue RestClient::ResourceNotFound => e
|
29
|
+
e.class.inspect
|
30
|
+
# "ResourceNotFound"
|
31
|
+
rescue Errno::ECONNREFUSED => e
|
32
|
+
e.class.inspect
|
33
|
+
# p e.class
|
34
|
+
# "Errno::ECONNREFUSED"
|
35
|
+
rescue SocketError => e
|
36
|
+
e.class.inspect
|
37
|
+
# "Socket Error"
|
38
|
+
rescue
|
39
|
+
"Timed out connecting to server"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [String]
|
44
|
+
def invalid_address
|
45
|
+
"getaddrinfo: Name or service not known (SocketError)"
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String]
|
49
|
+
def invalid_parameter
|
50
|
+
"Server error -32602: Invalid params"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class ServerError < StandardError
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def initialize(code, message)
|
58
|
+
super("Server error #{code}: #{message}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class InvalidParameter
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [String]
|
68
|
+
def self.error
|
69
|
+
"Server error -32602: Invalid params"
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String]
|
73
|
+
def self.argument_error
|
74
|
+
"ArgumentError"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# client_spec.rb
|
2
|
+
require './lib/casper_network.rb'
|
3
|
+
|
4
|
+
describe CasperClient do
|
5
|
+
client1 = CasperClient.new("185.246.84.43")
|
6
|
+
# Test info_get_peers()
|
7
|
+
describe "#info_get_peers" do
|
8
|
+
it "returns peers array." do
|
9
|
+
# Check whether ıt is an array or not
|
10
|
+
expect(client1.info_get_peers).to be_an(Array)
|
11
|
+
# Check the length of the peers array
|
12
|
+
expect(client1.info_get_peers.length).to be > 0
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# Test chain_get_StateRootHash()
|
17
|
+
describe "#chain_get_StateRootHash" do
|
18
|
+
it "returns current state_root_hash." do
|
19
|
+
# Check whether its type is string or not
|
20
|
+
expect(client1.chain_get_StateRootHash).to be_an(String)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|