stellar_core_commander 0.0.11 → 0.0.12
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/.gitignore +1 -0
- data/CONTRIBUTING.md +60 -0
- data/bin/scc +70 -11
- data/examples/cross_host_simple_payment.rb +5 -5
- data/examples/history_generate_and_catchup.rb +26 -0
- data/examples/history_testnet_catchup.rb +15 -0
- data/examples/inflation.rb +8 -0
- data/examples/load_generation.rb +15 -0
- data/examples/load_generation_auto.rb +15 -0
- data/examples/multi_host_simple_payment.rb +12 -5
- data/examples/set_options.rb +23 -0
- data/examples/simple_payment.rb +3 -1
- data/examples/version_mix_consensus.rb +46 -0
- data/lib/stellar_core_commander.rb +1 -0
- data/lib/stellar_core_commander/commander.rb +50 -16
- data/lib/stellar_core_commander/convert.rb +1 -5
- data/lib/stellar_core_commander/docker_process.rb +220 -44
- data/lib/stellar_core_commander/local_process.rb +82 -41
- data/lib/stellar_core_commander/operation_builder.rb +128 -59
- data/lib/stellar_core_commander/process.rb +478 -49
- data/lib/stellar_core_commander/transactor.rb +222 -85
- data/lib/stellar_core_commander/version.rb +1 -1
- data/stellar_core_commander.gemspec +1 -1
- metadata +14 -6
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'set'
|
2
3
|
require 'securerandom'
|
3
4
|
|
4
5
|
module StellarCoreCommander
|
@@ -6,15 +7,41 @@ module StellarCoreCommander
|
|
6
7
|
class DockerProcess < Process
|
7
8
|
include Contracts
|
8
9
|
|
10
|
+
attr_reader :docker_core_image
|
11
|
+
attr_reader :docker_state_image
|
12
|
+
|
13
|
+
Contract({
|
14
|
+
docker_state_image: String,
|
15
|
+
docker_core_image: String,
|
16
|
+
docker_pull: Bool
|
17
|
+
} => Any)
|
18
|
+
def initialize(params)
|
19
|
+
@docker_state_image = params[:docker_state_image]
|
20
|
+
@docker_core_image = params[:docker_core_image]
|
21
|
+
@docker_pull = params[:docker_pull]
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
9
25
|
Contract None => Num
|
10
26
|
def required_ports
|
11
27
|
3
|
12
28
|
end
|
13
29
|
|
30
|
+
Contract None => Any
|
31
|
+
def launch_heka_container
|
32
|
+
$stderr.puts "launching heka container #{heka_container_name}"
|
33
|
+
docker %W(run
|
34
|
+
--name #{heka_container_name}
|
35
|
+
--net container:#{container_name}
|
36
|
+
--volumes-from #{container_name}
|
37
|
+
-d stellar/heka
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
14
41
|
Contract None => Any
|
15
42
|
def launch_state_container
|
16
|
-
$stderr.puts "launching state container #{state_container_name}"
|
17
|
-
docker %W(run --name #{state_container_name} -p #{postgres_port}:5432 --env-file stellar-core.env -d
|
43
|
+
$stderr.puts "launching state container #{state_container_name} from image #{docker_state_image}"
|
44
|
+
docker %W(run --name #{state_container_name} -p #{postgres_port}:5432 --env-file stellar-core.env -d #{docker_state_image})
|
18
45
|
raise "Could not create state container" unless $?.success?
|
19
46
|
end
|
20
47
|
|
@@ -25,6 +52,13 @@ module StellarCoreCommander
|
|
25
52
|
raise "Could not drop db: #{database_name}" unless $?.success?
|
26
53
|
end
|
27
54
|
|
55
|
+
Contract None => Any
|
56
|
+
def shutdown_heka_container
|
57
|
+
return true unless heka_container_running?
|
58
|
+
docker %W(rm -f -v #{heka_container_name})
|
59
|
+
raise "Could not stop heka container: #{heka_container_name}" unless $?.success?
|
60
|
+
end
|
61
|
+
|
28
62
|
Contract None => Any
|
29
63
|
def write_config
|
30
64
|
IO.write("#{working_dir}/stellar-core.env", config)
|
@@ -35,66 +69,75 @@ module StellarCoreCommander
|
|
35
69
|
write_config
|
36
70
|
end
|
37
71
|
|
38
|
-
Contract None =>
|
39
|
-
def
|
40
|
-
raise "already running!" if running?
|
41
|
-
setup
|
72
|
+
Contract None => Any
|
73
|
+
def launch_process
|
42
74
|
launch_state_container
|
43
75
|
launch_stellar_core
|
76
|
+
launch_heka_container if atlas
|
44
77
|
end
|
45
78
|
|
46
79
|
Contract None => Bool
|
47
80
|
def running?
|
48
|
-
|
49
|
-
|
81
|
+
container_running? container_name
|
82
|
+
end
|
83
|
+
|
84
|
+
Contract None => Bool
|
85
|
+
def heka_container_running?
|
86
|
+
container_running? heka_container_name
|
50
87
|
end
|
51
88
|
|
52
89
|
Contract None => Bool
|
53
90
|
def state_container_running?
|
54
|
-
|
55
|
-
$?.success?
|
91
|
+
container_running? state_container_name
|
56
92
|
end
|
57
93
|
|
58
94
|
Contract None => Any
|
59
95
|
def shutdown
|
60
96
|
return true unless running?
|
97
|
+
docker %W(stop #{container_name})
|
98
|
+
docker %W(exec #{container_name} rm -rf /history)
|
61
99
|
docker %W(rm -f #{container_name})
|
62
100
|
end
|
63
101
|
|
64
102
|
Contract None => Any
|
65
103
|
def cleanup
|
66
104
|
database.disconnect
|
105
|
+
dump_database
|
106
|
+
dump_logs
|
107
|
+
dump_cores
|
108
|
+
dump_scp_state
|
109
|
+
dump_info
|
110
|
+
dump_metrics
|
67
111
|
shutdown
|
68
112
|
shutdown_state_container
|
69
|
-
|
113
|
+
shutdown_heka_container if atlas
|
70
114
|
end
|
71
115
|
|
72
116
|
Contract None => Any
|
73
|
-
def
|
74
|
-
|
75
|
-
host_args = "-H tcp://#{docker_host}:#{docker_port}" if host
|
76
|
-
`docker #{host_args} exec #{state_container_name} pg_dump -U #{database_user} --clean --no-owner #{database_name}`
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
Contract None => Sequel::Database
|
81
|
-
def database
|
82
|
-
@database ||= Sequel.postgres(database_name, host: docker_host, port: postgres_port, user: database_user, password: database_password)
|
117
|
+
def dump_logs
|
118
|
+
docker ["logs", container_name]
|
83
119
|
end
|
84
120
|
|
85
|
-
Contract None =>
|
86
|
-
def
|
87
|
-
|
121
|
+
Contract None => Any
|
122
|
+
def dump_cores
|
123
|
+
docker %W(run --volumes-from #{container_name} --rm -e MODE=local #{docker_core_image} /utils/core_file_processor.py)
|
124
|
+
docker %W(cp #{container_name}:/cores .)
|
88
125
|
end
|
89
126
|
|
90
|
-
Contract None =>
|
91
|
-
def
|
92
|
-
"
|
127
|
+
Contract None => Any
|
128
|
+
def dump_database
|
129
|
+
fname = "#{working_dir}/database-#{Time.now.to_i}-#{rand 100000}.sql"
|
130
|
+
$stderr.puts "dumping database to #{fname}"
|
131
|
+
host_args = "-H tcp://#{docker_host}:#{docker_port}" if host
|
132
|
+
sql = `docker #{host_args} exec #{state_container_name} pg_dump -U #{database_user} --clean --no-owner --no-privileges #{database_name}`
|
133
|
+
File.open(fname, 'w') {|f| f.write(sql) }
|
134
|
+
fname
|
93
135
|
end
|
94
136
|
|
95
137
|
Contract None => String
|
96
|
-
def
|
138
|
+
def default_database_url
|
97
139
|
@database_password ||= SecureRandom.hex
|
140
|
+
"postgres://postgres:#{@database_password}@#{docker_host}:#{postgres_port}/stellar"
|
98
141
|
end
|
99
142
|
|
100
143
|
Contract None => Num
|
@@ -112,6 +155,11 @@ module StellarCoreCommander
|
|
112
155
|
"scc-state-#{idname}"
|
113
156
|
end
|
114
157
|
|
158
|
+
Contract None => String
|
159
|
+
def heka_container_name
|
160
|
+
"scc-heka-#{idname}"
|
161
|
+
end
|
162
|
+
|
115
163
|
Contract None => String
|
116
164
|
def docker_host
|
117
165
|
return host if host
|
@@ -124,44 +172,167 @@ module StellarCoreCommander
|
|
124
172
|
docker_host
|
125
173
|
end
|
126
174
|
|
175
|
+
Contract None => Bool
|
176
|
+
def docker_pull?
|
177
|
+
@docker_pull
|
178
|
+
end
|
179
|
+
|
180
|
+
Contract None => ArrayOf[String]
|
181
|
+
def aws_credentials_volume
|
182
|
+
if use_s3 and File.exists?("#{ENV['HOME']}/.aws")
|
183
|
+
["-v", "#{ENV['HOME']}/.aws:/root/.aws:ro"]
|
184
|
+
else
|
185
|
+
[]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
Contract None => Bool
|
190
|
+
def use_s3
|
191
|
+
if @use_s3
|
192
|
+
true
|
193
|
+
else
|
194
|
+
if host and (@quorum.size > 1)
|
195
|
+
$stderr.puts "WARNING: multi-peer with remote docker host, but no s3; history will not be shared"
|
196
|
+
end
|
197
|
+
false
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
Contract None => ArrayOf[String]
|
202
|
+
def shared_history_volume
|
203
|
+
if use_s3
|
204
|
+
[]
|
205
|
+
else
|
206
|
+
dir = File.expand_path("#{working_dir}/../history-archives")
|
207
|
+
Dir.mkdir(dir) unless File.exists?(dir)
|
208
|
+
["-v", "#{dir}:/history"]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
Contract None => String
|
213
|
+
def history_get_command
|
214
|
+
cmds = Set.new
|
215
|
+
localget = "cp /history/%s/{0} {1}"
|
216
|
+
s3get = "aws s3 --region #{@s3_history_region} cp #{@s3_history_prefix}/%s/{0} {1}"
|
217
|
+
@quorum.each do |q|
|
218
|
+
if q == @name
|
219
|
+
next
|
220
|
+
end
|
221
|
+
if SPECIAL_PEERS.has_key? q
|
222
|
+
cmds.add SPECIAL_PEERS[q][:get]
|
223
|
+
elsif use_s3
|
224
|
+
cmds.add s3get
|
225
|
+
else
|
226
|
+
cmds.add localget
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
if cmds.size == 0
|
231
|
+
if use_s3
|
232
|
+
cmds.add s3get
|
233
|
+
else
|
234
|
+
cmds.add localget
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
if cmds.size != 1
|
239
|
+
raise "Conflicting get commands: #{cmds.to_a.inspect}"
|
240
|
+
end
|
241
|
+
<<-EOS.strip_heredoc
|
242
|
+
HISTORY_GET=#{cmds.to_a.first}
|
243
|
+
EOS
|
244
|
+
end
|
245
|
+
|
246
|
+
Contract None => String
|
247
|
+
def history_put_commands
|
248
|
+
if has_special_peers?
|
249
|
+
""
|
250
|
+
else
|
251
|
+
if use_s3
|
252
|
+
<<-EOS.strip_heredoc
|
253
|
+
HISTORY_PUT=aws s3 --region #{@s3_history_region} cp {0} #{@s3_history_prefix}/%s/{1}
|
254
|
+
EOS
|
255
|
+
else
|
256
|
+
<<-EOS.strip_heredoc
|
257
|
+
HISTORY_PUT=cp {0} /history/%s/{1}
|
258
|
+
HISTORY_MKDIR=mkdir -p /history/%s/{0}
|
259
|
+
EOS
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def prepare
|
265
|
+
$stderr.puts "preparing #{idname} (dir:#{working_dir})"
|
266
|
+
return unless docker_pull?
|
267
|
+
docker %W(pull #{docker_state_image})
|
268
|
+
docker %W(pull #{docker_core_image})
|
269
|
+
docker %W(pull stellar/heka)
|
270
|
+
end
|
271
|
+
|
272
|
+
def crash
|
273
|
+
docker %W(exec #{container_name} pkill -ABRT stellar-core)
|
274
|
+
end
|
275
|
+
|
127
276
|
private
|
128
277
|
def launch_stellar_core
|
129
278
|
$stderr.puts "launching stellar-core container #{container_name}"
|
130
|
-
docker %W(run
|
279
|
+
docker (%W(run
|
131
280
|
--name #{container_name}
|
132
281
|
--net host
|
133
282
|
--volumes-from #{state_container_name}
|
283
|
+
) + aws_credentials_volume + shared_history_volume + %W(
|
134
284
|
--env-file stellar-core.env
|
135
|
-
-d
|
136
|
-
/
|
137
|
-
|
285
|
+
-d #{docker_core_image}
|
286
|
+
/start #{@name} fresh #{"forcescp" if @forcescp}
|
287
|
+
))
|
138
288
|
raise "Could not create stellar-core container" unless $?.success?
|
139
289
|
end
|
140
290
|
|
141
291
|
Contract None => String
|
142
292
|
def config
|
293
|
+
(
|
143
294
|
<<-EOS.strip_heredoc
|
144
295
|
POSTGRES_PASSWORD=#{database_password}
|
145
296
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
297
|
+
ENVIRONMENT=scc
|
298
|
+
CLUSTER_NAME=#{recipe_name}
|
299
|
+
HOSTNAME=#{idname}
|
300
|
+
|
301
|
+
#{@name}_POSTGRES_PORT=#{postgres_port}
|
302
|
+
#{@name}_PEER_PORT=#{peer_port}
|
303
|
+
#{@name}_HTTP_PORT=#{http_port}
|
304
|
+
#{@name}_PEER_SEED=#{identity.seed}
|
305
|
+
#{"#{@name}_VALIDATION_SEED=#{identity.seed}" if @validate}
|
151
306
|
|
152
307
|
#{"MANUAL_CLOSE=true" if manual_close?}
|
153
308
|
|
154
|
-
|
309
|
+
ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true
|
310
|
+
#{"ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true" if @accelerate_time}
|
311
|
+
#{"CATCHUP_COMPLETE=true" if @catchup_complete}
|
155
312
|
|
156
|
-
|
157
|
-
QUORUM_SET=#{quorum}
|
313
|
+
#{"ATLAS_ADDRESS=" + atlas if atlas}
|
158
314
|
|
159
|
-
|
315
|
+
METRICS_INTERVAL=#{atlas_interval}
|
160
316
|
|
161
|
-
|
162
|
-
|
163
|
-
|
317
|
+
#{"COMMANDS=[\"ll?level=debug\"]" if @debug}
|
318
|
+
|
319
|
+
FAILURE_SAFETY=0
|
320
|
+
UNSAFE_QUORUM=true
|
321
|
+
|
322
|
+
PREFERRED_PEERS=#{peer_connections}
|
323
|
+
VALIDATORS=#{quorum}
|
324
|
+
|
325
|
+
HISTORY_PEERS=#{peer_names}
|
326
|
+
|
327
|
+
NETWORK_PASSPHRASE="#{network_passphrase}"
|
164
328
|
EOS
|
329
|
+
) + history_get_command + history_put_commands
|
330
|
+
end
|
331
|
+
|
332
|
+
def recipe_name
|
333
|
+
File.basename($opts[:recipe], '.rb')
|
334
|
+
rescue TypeError
|
335
|
+
'recipe_name_not_found'
|
165
336
|
end
|
166
337
|
|
167
338
|
def docker_port
|
@@ -183,5 +354,10 @@ module StellarCoreCommander
|
|
183
354
|
def docker(args)
|
184
355
|
run_cmd "docker", docker_args + args
|
185
356
|
end
|
357
|
+
|
358
|
+
def container_running?(name)
|
359
|
+
docker ['inspect', '-f', '{{.Name}} running: {{.State.Running}}', name]
|
360
|
+
$?.success?
|
361
|
+
end
|
186
362
|
end
|
187
363
|
end
|
@@ -4,12 +4,15 @@ module StellarCoreCommander
|
|
4
4
|
include Contracts
|
5
5
|
|
6
6
|
attr_reader :pid
|
7
|
-
attr_reader :wait
|
8
7
|
|
9
8
|
def initialize(params)
|
9
|
+
raise "`host` param is unsupported on LocalProcess, please use `-p docker` for this recipe." if params[:host]
|
10
|
+
$stderr.puts "Warning: Ignoring `atlas` param since LocalProcess doesn't support this." if params[:atlas]
|
11
|
+
|
10
12
|
super
|
11
13
|
@stellar_core_bin = params[:stellar_core_bin]
|
12
|
-
|
14
|
+
@database_url = params[:database].try(:strip)
|
15
|
+
|
13
16
|
setup_working_dir
|
14
17
|
end
|
15
18
|
|
@@ -21,7 +24,8 @@ module StellarCoreCommander
|
|
21
24
|
|
22
25
|
Contract None => Any
|
23
26
|
def initialize_history
|
24
|
-
|
27
|
+
Dir.mkdir(history_dir) unless File.exists?(history_dir)
|
28
|
+
run_cmd "./stellar-core", ["--newhist", @name.to_s]
|
25
29
|
raise "Could not initialize history" unless $?.success?
|
26
30
|
end
|
27
31
|
|
@@ -48,19 +52,22 @@ module StellarCoreCommander
|
|
48
52
|
IO.write("#{@working_dir}/stellar-core.cfg", config)
|
49
53
|
end
|
50
54
|
|
55
|
+
Contract None => String
|
56
|
+
def history_dir
|
57
|
+
File.expand_path("#{working_dir}/../history-archives")
|
58
|
+
end
|
59
|
+
|
51
60
|
Contract None => Any
|
52
61
|
def setup
|
53
62
|
write_config
|
54
|
-
create_database
|
63
|
+
create_database unless @keep_database
|
55
64
|
initialize_history
|
56
65
|
initialize_database
|
57
66
|
end
|
58
67
|
|
59
68
|
Contract None => Num
|
60
|
-
def
|
61
|
-
|
62
|
-
setup
|
63
|
-
forcescp
|
69
|
+
def launch_process
|
70
|
+
forcescp if @forcescp
|
64
71
|
launch_stellar_core
|
65
72
|
end
|
66
73
|
|
@@ -84,52 +91,50 @@ module StellarCoreCommander
|
|
84
91
|
::Process.kill "KILL", @pid
|
85
92
|
end
|
86
93
|
|
87
|
-
@
|
94
|
+
@wait_value == 0
|
88
95
|
end
|
89
96
|
|
90
97
|
Contract None => Any
|
91
98
|
def cleanup
|
92
99
|
database.disconnect
|
100
|
+
dump_database
|
101
|
+
dump_scp_state
|
102
|
+
dump_info
|
103
|
+
dump_metrics
|
93
104
|
shutdown
|
94
|
-
drop_database
|
95
|
-
rm_working_dir
|
105
|
+
drop_database unless @keep_database
|
96
106
|
end
|
97
107
|
|
98
108
|
Contract None => Any
|
99
109
|
def dump_database
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
Contract None => Sequel::Database
|
107
|
-
def database
|
108
|
-
@database ||= Sequel.postgres(database_name)
|
110
|
+
fname = "#{working_dir}/database-#{Time.now.to_i}-#{rand 100000}.sql"
|
111
|
+
$stderr.puts "dumping database to #{fname}"
|
112
|
+
sql = `pg_dump #{database_name} --clean --no-owner --no-privileges`
|
113
|
+
File.open(fname, 'w') {|f| f.write(sql) }
|
114
|
+
fname
|
109
115
|
end
|
110
116
|
|
111
117
|
Contract None => String
|
112
|
-
def
|
113
|
-
"
|
118
|
+
def default_database_url
|
119
|
+
"postgres:///#{idname}"
|
114
120
|
end
|
115
121
|
|
116
|
-
|
117
|
-
|
118
|
-
"postgresql://dbname=#{database_name}"
|
122
|
+
def crash
|
123
|
+
`kill -ABRT #{@pid}`
|
119
124
|
end
|
120
125
|
|
121
126
|
private
|
122
127
|
def launch_stellar_core
|
123
128
|
Dir.chdir @working_dir do
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
@pid = wait.pid
|
129
|
+
@pid = ::Process.spawn("./stellar-core",
|
130
|
+
:out => "stdout.txt",
|
131
|
+
:err => "stderr.txt")
|
132
|
+
@wait = Thread.new {
|
133
|
+
@wait_value = ::Process.wait(@pid);
|
134
|
+
$stderr.puts "stellar-core process exited: #{@wait_value}"
|
135
|
+
}
|
132
136
|
end
|
137
|
+
@pid
|
133
138
|
end
|
134
139
|
|
135
140
|
Contract None => String
|
@@ -139,25 +144,61 @@ module StellarCoreCommander
|
|
139
144
|
RUN_STANDALONE=false
|
140
145
|
HTTP_PORT=#{http_port}
|
141
146
|
PUBLIC_HTTP_PORT=false
|
142
|
-
|
143
|
-
|
147
|
+
NODE_SEED="#{@identity.seed}"
|
148
|
+
#{"NODE_IS_VALIDATOR=true" if @validate}
|
149
|
+
|
150
|
+
ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true
|
151
|
+
#{"ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING=true" if @accelerate_time}
|
152
|
+
#{"CATCHUP_COMPLETE=true" if @catchup_complete}
|
144
153
|
|
145
154
|
DATABASE="#{dsn}"
|
146
|
-
PREFERRED_PEERS=#{
|
155
|
+
PREFERRED_PEERS=#{peer_connections}
|
147
156
|
|
148
157
|
#{"MANUAL_CLOSE=true" if manual_close?}
|
158
|
+
#{"COMMANDS=[\"ll?level=debug\"]" if @debug}
|
159
|
+
|
160
|
+
FAILURE_SAFETY=0
|
161
|
+
UNSAFE_QUORUM=true
|
162
|
+
|
163
|
+
NETWORK_PASSPHRASE="#{network_passphrase}"
|
149
164
|
|
150
165
|
[QUORUM_SET]
|
151
|
-
THRESHOLD=#{threshold}
|
152
166
|
VALIDATORS=#{quorum}
|
153
167
|
|
154
|
-
|
155
|
-
get="cp history/main/{0} {1}"
|
156
|
-
put="cp {0} history/main/{1}"
|
157
|
-
mkdir="mkdir -p history/main/{0}"
|
168
|
+
#{history_sources}
|
158
169
|
EOS
|
159
170
|
end
|
160
171
|
|
172
|
+
Contract Symbol => String
|
173
|
+
def one_history_source(n)
|
174
|
+
dir = "#{history_dir}/#{n}"
|
175
|
+
if n == @name
|
176
|
+
<<-EOS.strip_heredoc
|
177
|
+
[HISTORY.#{n}]
|
178
|
+
get="cp #{dir}/{0} {1}"
|
179
|
+
put="cp {0} #{dir}/{1}"
|
180
|
+
mkdir="mkdir -p #{dir}/{0}"
|
181
|
+
EOS
|
182
|
+
else
|
183
|
+
name = n.to_s
|
184
|
+
get = "cp #{history_dir}/%s/{0} {1}"
|
185
|
+
if SPECIAL_PEERS.has_key? n
|
186
|
+
name = SPECIAL_PEERS[n][:name]
|
187
|
+
get = SPECIAL_PEERS[n][:get]
|
188
|
+
end
|
189
|
+
get.sub!('%s', name)
|
190
|
+
<<-EOS.strip_heredoc
|
191
|
+
[HISTORY.#{name}]
|
192
|
+
get="#{get}"
|
193
|
+
EOS
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
Contract None => String
|
198
|
+
def history_sources
|
199
|
+
@quorum.map {|n| one_history_source n}.join("\n")
|
200
|
+
end
|
201
|
+
|
161
202
|
def setup_working_dir
|
162
203
|
if @stellar_core_bin.blank?
|
163
204
|
search = `which stellar-core`.strip
|