Skip to content

Commit 96c8196

Browse files
StealthSendStealthSend
authored andcommitted
version exchange protocol with legacy peers
1 parent 0b264d7 commit 96c8196

25 files changed

Lines changed: 1382 additions & 290 deletions

CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,4 +515,39 @@ target_link_libraries(StealthCoind
515515

516516
add_dependencies(StealthCoind generate_build_h)
517517

518+
519+
##############################################################################
520+
## download-stealth-bootstrap
521+
##############################################################################
522+
523+
set(SCRIPT_SOURCE ${CMAKE_SOURCE_DIR}/scripts/download-stealth-bootstrap)
524+
525+
set(SCRIPT_DESTINATION ${CMAKE_BINARY_DIR}/download-stealth-bootstrap)
526+
527+
add_custom_command(
528+
OUTPUT ${SCRIPT_DESTINATION}
529+
COMMAND ${CMAKE_COMMAND} -E copy ${SCRIPT_SOURCE} ${SCRIPT_DESTINATION}
530+
DEPENDS ${SCRIPT_SOURCE}
531+
)
532+
533+
add_custom_target(copy_bootstrap_script ALL DEPENDS ${SCRIPT_DESTINATION})
534+
535+
add_dependencies(copy_bootstrap_script StealthCoind)
536+
537+
538+
##############################################################################
539+
## install
540+
##############################################################################
541+
518542
install(TARGETS StealthCoind DESTINATION bin)
543+
544+
install(PROGRAMS ${CMAKE_SOURCE_DIR}/scripts/download-stealth-bootstrap
545+
DESTINATION bin
546+
RENAME download-stealth-bootstrap)
547+
548+
set(SCRIPT_INSTALL_DIR "" CACHE PATH "Custom installation directory for utility scripts")
549+
if(SCRIPT_INSTALL_DIR)
550+
install(PROGRAMS ${CMAKE_SOURCE_DIR}/scripts/download-stealth-bootstrap
551+
DESTINATION ${SCRIPT_INSTALL_DIR}
552+
RENAME download-stealth-bootstrap)
553+
endif()

doc/Stealth-Installation-Guide.adoc

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,55 @@
1-
= Stealth Daemon Installation Guide
1+
== Stealth Daemon Installation Guide
22

33
The newest version of this document is at <https://github.com/StealthSend/Stealth/wiki/Stealth-Installation-Guide>.
44

55

6-
== Overview
6+
=== BEFORE YOU START
7+
8+
**Backup your `wallet.dat`!**
9+
10+
For example:
11+
12+
[source,bash]
13+
----
14+
StealthCoind backupwallet "${HOME}/wallet.dat.$(date +%s)"
15+
----
16+
17+
If `StealthCoind` is not running, it suffices to simply make a copy:
18+
19+
[source,bash]
20+
----
21+
cp "${HOME}/.StealthCoin/wallet.dat" "${HOME}/wallet.dat.$(date +%s)"
22+
----
23+
24+
The database used for the wallet (Berkeley DB) has poor forwards-compatibility.
25+
In most cases, this incompatibility shouldn't be a problem, but be safe and create a backup before you do anything.
26+
27+
If you have problems, you may have to determine the version of Berkeley DB used to build your current instance of `StealthCoind` and build against a custom installation.
28+
29+
Also, if you previously built with a custom installation of Berkeley DB, you may have to scrape it from your system.
30+
Typically, the commands are:
31+
32+
[source,bash]
33+
----
34+
sudo rm /usr/local/lib/libdb*
35+
sudo rm /usr/local/lib/db.*h
36+
----
37+
38+
It is likely worthwhile to run these commands if you are upgrading `StealthCoind`.
739

8-
The recommended way to build the Stealth daemon, called **StealthCoind**, is in a directory called "build" created at the root of the source tree.
940

1041
=== Summary
1142

1243
In short, the steps to install are:
1344

14-
1. Upgrade your operating system and package manager to the latest version.
15-
2. Ensure that external dependencies are installed.
16-
3. Download the Stealth source bundle.
17-
4. Within a new directory called "build" at the top of the source tree, run
45+
1. Backup your `wallet.dat`! See above.
46+
2. Upgrade your operating system and package manager to the latest version.
47+
3. Ensure that external dependencies are installed.
48+
4. Download the Stealth source bundle.
49+
5. Within a new directory called "build" at the top of the source tree, run
1850
"`cmake ..`", then "`make`":
1951
+
20-
[source, bash]
52+
[source,bash]
2153
----
2254
# from the top of the downloaded source code
2355
mkdir build

scripts/download-stealth-bootstrap

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#! /usr/bin/env python3
2+
3+
import urllib.request
4+
import urllib.parse
5+
import re
6+
import os
7+
import subprocess
8+
import ssl
9+
import sys
10+
import argparse
11+
import tempfile
12+
import textwrap
13+
14+
try:
15+
from tqdm import tqdm
16+
TQDM_AVAILABLE = True
17+
except ImportError:
18+
TQDM_AVAILABLE = False
19+
20+
class DownloadProgressBar:
21+
def __init__(self, total=0, unit='iB', unit_scale=True, unit_divisor=1024):
22+
self.pbar = None
23+
self.total = total
24+
self.unit = unit
25+
self.unit_scale = unit_scale
26+
self.unit_divisor = unit_divisor
27+
28+
def __call__(self, downloaded, block_size, total_size):
29+
if not self.pbar:
30+
self.total = total_size
31+
self.pbar = tqdm(total=total_size, unit=self.unit, unit_scale=self.unit_scale, unit_divisor=self.unit_divisor)
32+
33+
self.pbar.update(downloaded - self.pbar.n)
34+
35+
if downloaded >= total_size:
36+
self.pbar.close()
37+
38+
def simple_progress_bar(downloaded, block_size, total_size):
39+
progress = min(round(downloaded / total_size * 100, 2), 100)
40+
sys.stdout.write(f"\rDownload progress: {progress:6.2f}%")
41+
sys.stdout.flush()
42+
43+
def create_ssl_context():
44+
cert_chain = textwrap.dedent("""
45+
-----BEGIN CERTIFICATE-----
46+
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
47+
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
48+
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
49+
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
50+
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
51+
A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
52+
27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
53+
Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
54+
TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
55+
qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
56+
szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
57+
Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
58+
MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
59+
wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
60+
aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
61+
VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
62+
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
63+
FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
64+
C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
65+
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
66+
h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
67+
7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
68+
ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
69+
MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
70+
Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
71+
6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
72+
0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
73+
2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
74+
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
75+
-----END CERTIFICATE-----
76+
""").strip()
77+
78+
context = ssl.create_default_context(cadata=cert_chain)
79+
80+
return context
81+
82+
def download_large_file(file_id, output_filename, ssl_context):
83+
url = f"https://drive.google.com/uc?export=download&id={file_id}"
84+
req = urllib.request.Request(url, method="GET")
85+
86+
try:
87+
with urllib.request.urlopen(req, context=ssl_context) as response:
88+
response_content = response.read().decode('utf-8')
89+
except urllib.error.URLError as e:
90+
print(f"Error accessing Google Drive: {e}")
91+
return False
92+
93+
form_action = re.search(r'<form id="download-form" action="([^"]*)"', response_content)
94+
confirm = re.search(r'name="confirm" value="([^"]*)"', response_content)
95+
uuid_value = re.search(r'name="uuid" value="([^"]*)"', response_content)
96+
97+
if not all([form_action, confirm, uuid_value]):
98+
print("Failed to extract form details. The download process might have changed.")
99+
return False
100+
101+
download_url = (f"{form_action.group(1)}?"
102+
f"id={file_id}&"
103+
f"export=download&"
104+
f"confirm={confirm.group(1)}&"
105+
f"uuid={uuid_value.group(1)}")
106+
107+
print(f"Downloading file to {output_filename}...")
108+
try:
109+
with urllib.request.urlopen(download_url, context=ssl_context) as response, open(output_filename, 'wb') as out_file:
110+
file_size = int(response.headers.get('Content-Length', 0))
111+
print(file_size)
112+
block_size = 8192
113+
114+
if TQDM_AVAILABLE:
115+
progress_bar = tqdm(total=file_size, unit='iB', unit_scale=True)
116+
else:
117+
progress_bar = simple_progress_bar
118+
119+
size = 0
120+
while True:
121+
buffer = response.read(block_size)
122+
if not buffer:
123+
break
124+
size += len(buffer)
125+
out_file.write(buffer)
126+
if TQDM_AVAILABLE:
127+
progress_bar.update(len(buffer))
128+
else:
129+
progress_bar(size, block_size, file_size)
130+
131+
if TQDM_AVAILABLE:
132+
progress_bar.close()
133+
else:
134+
print() # New line after progress bar
135+
136+
print("Download completed.")
137+
return True
138+
except urllib.error.URLError as e:
139+
print(f"\nError downloading file: {e}")
140+
return False
141+
142+
def extract_file(filename, extract_path):
143+
print(f"Extracting \033[94m{filename}\033[0m to \033[96m{extract_path}\033[0m...")
144+
try:
145+
subprocess.run(["7z", "x", filename, f"-o{extract_path}"], check=True)
146+
print("Extraction completed.")
147+
return True
148+
except subprocess.CalledProcessError:
149+
print("Extraction failed. Make sure 7z is installed and in your PATH.")
150+
return False
151+
152+
def check_writable(path):
153+
try:
154+
testfile = tempfile.TemporaryFile(dir=path)
155+
testfile.close()
156+
except OSError:
157+
return False
158+
return True
159+
160+
def print_usage():
161+
print("Usage: python3 download_script.py [--datadir PATH]")
162+
print("Options:")
163+
print(" --datadir PATH, -d PATH Specify the path to the Stealth data directory")
164+
print(" (default: ~/.StealthCoin)")
165+
166+
def main():
167+
parser = argparse.ArgumentParser(description="Download and extract Stealth bootstrap file.")
168+
parser.add_argument('--datadir', '-d', type=str, help='Path to the Stealth data directory')
169+
args = parser.parse_args()
170+
171+
if not check_writable('.'):
172+
print("Error: Current working directory is not writable.")
173+
sys.exit(1)
174+
175+
if args.datadir:
176+
data_dir = os.path.abspath(args.datadir)
177+
else:
178+
data_dir = os.path.expanduser("~/.StealthCoin")
179+
180+
if not os.path.exists(data_dir):
181+
print(f"Error: Cannot find the Stealth data directory at {data_dir}")
182+
print_usage()
183+
sys.exit(1)
184+
185+
file_id = "1WNmH1DiO4-_D-UYupoyFXM-rKMlGVTet"
186+
output_filename = "xst-bootstrap.7z"
187+
188+
print("This script will download a large file (3.0G) from Google Drive.")
189+
print("Google Drive can't scan this file for viruses due to its size.")
190+
191+
ssl_context = create_ssl_context()
192+
print("Using bundled Google Drive certificate chain for secure connection.")
193+
194+
user_input = input("\033[1mDo you want to proceed with the download? (y/n):\033[0m ").lower()
195+
196+
if user_input == 'y':
197+
if download_large_file(file_id, output_filename, ssl_context):
198+
user_input = input("\033[1mDo you want to extract the downloaded file? (y/n):\033[0m ").lower()
199+
if user_input == 'y':
200+
extract_file(output_filename, data_dir)
201+
else:
202+
print("\033[31mDownload cancelled.\033[0m")
203+
204+
if __name__ == "__main__":
205+
main()

0 commit comments

Comments
 (0)