diff --git a/guide/SOURCES.html b/guide/SOURCES.html
deleted file mode 100644
index 123cfa8..0000000
--- a/guide/SOURCES.html
+++ /dev/null
@@ -1,680 +0,0 @@
-
-
-
-
-
Tornado Cash decentralized sources
This is an entrypoint page to source code and minified versions of all Tornado Cash services and packages.
Basic users guide
If you want to use trusted local versions of Tornado sites, you can download it directly from IPFS:
Classic UI (main site) - classic-ui.minified.sources.tornadocash.eth, actual IPFS hash - bafybeia4x75bn74prpmi6jqa6gbgmsfovunnke5s6oyrddxyopnz6kw5le
Nova UI - nova.minified.sources.tornadocash.eth, actual IPFS hash - bafybeihr5h2tfonjn2gybd4yhvchdwt4eyo25lf5twhhn6bnasdv2wwz7i
Tornado CLI - cli.minified.sources.tornadocash.eth, actual IPFS hash - bafybeicxxyqjgx5ggvujij4fnjdcwkep4nj5662yrxftb7y3pzwl77qntq
Just click on contenthash
field by link or copy IPFS hash and paste in any IPFS gateway, and then file start downloading.
Developers guide
Download all Tornado Cash git repositories is easy via special tool located on download.sources.tornadocash.eth.
Clone repo with tool via any IPFS resolver by CID on ENS domain above and follow tool readme (located in repo), for example:
or
-
-
\ No newline at end of file
diff --git a/guide/SOURCES.md b/guide/SOURCES.md
deleted file mode 100644
index 186966b..0000000
--- a/guide/SOURCES.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Tornado Cash decentralized sources
-
-This is an entrypoint page to source code and minified versions of all Tornado Cash services and packages.
-
-### Basic users guide
-
-If you want to use trusted local versions of Tornado sites, you can download it directly from IPFS:
-
-1. Classic UI (main site) - [classic-ui.minified.sources.tornadocash.eth](https://app.ens.domains/classic-ui.minified.sources.tornadocash.eth), actual IPFS hash - `bafybeia4x75bn74prpmi6jqa6gbgmsfovunnke5s6oyrddxyopnz6kw5le`
-2. Nova UI - [nova.minified.sources.tornadocash.eth](https://app.ens.domains/nova.minified.sources.tornadocash.eth), actual IPFS hash - `bafybeihr5h2tfonjn2gybd4yhvchdwt4eyo25lf5twhhn6bnasdv2wwz7i`
-3. Tornado CLI - [cli.minified.sources.tornadocash.eth](https://app.ens.domains/cli.minified.sources.tornadocash.eth), actual IPFS hash - `bafybeicxxyqjgx5ggvujij4fnjdcwkep4nj5662yrxftb7y3pzwl77qntq`
-
-Just click on `contenthash` field by link or copy IPFS hash and paste in [any IPFS gateway](https://ipfs.github.io/public-gateway-checker/), and then file start downloading.
-
-### Developers guide
-
-Download all Tornado Cash git repositories is easy via special tool located on [download.sources.tornadocash.eth](https://app.ens.domains/download.sources.tornadocash.eth).
-
-Clone repo with tool via any IPFS resolver by CID on ENS domain above and follow tool readme (located in repo), for example:
-
-````
-git clone https://ipfs.io/ipfs/bafybeienn6huru6cxs3ovl5ogeik2wnvviqtoainqj4zn2q3q7zzezvu6u downloader-tool
-````
-
-or
-
-```
-git clone https://cloudflare-ipfs.com/ipfs/bafybeienn6huru6cxs3ovl5ogeik2wnvviqtoainqj4zn2q3q7zzezvu6u
-```
-
diff --git a/scripts/hostIPFS.sh b/scripts/hostIPFS.sh
new file mode 100644
index 0000000..d14ea50
--- /dev/null
+++ b/scripts/hostIPFS.sh
@@ -0,0 +1,128 @@
+#!/bin/bash
+# Script must be running from root
+if [ "$EUID" -ne 0 ];
+ then echo "Please run as root";
+ exit 1;
+fi;
+
+this_repo_ipfs_cid="bafybeienn6huru6cxs3ovl5ogeik2wnvviqtoainqj4zn2q3q7zzezvu6u";
+user_home_dir=$(eval echo ~$USER);
+tornado_folder="$user_home_dir/tornado-ipfs";
+script_log_file="/tmp/tornado-ipfs-installation.log";
+cron_script_path="$tornado_folder/cronfile.cron";
+
+function echo_log_err(){
+ echo $1 1>&2;
+ echo -e "$1\n" &>> $script_log_file;
+}
+
+function echo_log_err_and_exit(){
+ echo_log_err "$1";
+ exit 1;
+}
+
+function delete_if_exists(){
+ if test -d $1; then rm -rf $1; fi;
+ if test -f $1; then rm $1; fi;
+}
+
+function is_package_installed(){
+ if [ $(dpkg-query -W -f='${Status}' $1 2>/dev/null | grep -c "ok installed") -eq 0 ]; then return 1; else return 0; fi;
+}
+
+function install_requred_packages(){
+ apt update &>> $script_log_file;
+
+ requred_packages=("curl" "git" "ufw" "cron");
+ local package;
+ for package in ${requred_packages[@]}; do
+ if ! is_package_installed $package; then
+ # Kill apache process, because Debian configuring nginx package right during installation
+ if [ $package = "nginx" ]; then systemctl stop apache2; fi;
+ apt install --yes --force-yes -o DPkg::Options::="--force-confold" $package &>> $script_log_file;
+ if ! is_package_installed $package; then
+ echo_log_err_and_exit "Error: cannot install \"$package\" package";
+ fi;
+ fi;
+ done;
+
+ echo -e "\nAll required packages installed successfully";
+}
+
+function install_node(){
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash &>> $script_log_file;
+ . ~/.nvm/nvm.sh;
+ . ~/.profile;
+ . ~/.bashrc;
+ nvm install 16.20.2 &>> $script_log_file;
+}
+
+function download_repo(){
+ ipfs_gateways=("https://ipfs.io/ipfs" "https://dweb.link/ipfs" "https://cloudflare-ipfs.com/ipfs" "https://gateway.pinata.cloud/ipfs" "https://hardbin.com/ipfs");
+ for gateway in ${ipfs_gateways[@]}; do
+ delete_if_exists $tornado_folder;
+ if git clone $gateway/$this_repo_ipfs_cid $tornado_folder; then break; fi;
+ done;
+ if [ ! -d $tornado_folder ]; then echo_log_err_and_exit "Cannot download repository from IPFS"; fi;
+}
+
+function install_node_dependencies(){
+ npm i -g yarn &>> $script_log_file;
+ cd $tornado_folder;
+ yarn &>> $script_log_file;
+}
+
+function run_ipfs_daemon(){
+ cd $tornado_folder;
+ wget https://dist.ipfs.tech/kubo/v0.22.0/kubo_v0.22.0_linux-amd64.tar.gz;
+ tar -xvzf kubo_v0.22.0_linux-amd64.tar.gz;
+ cd kubo;
+ sudo bash install.sh;
+ ipfs init --profile server;
+ sudo -b ipfs daemon;
+}
+
+function configure_firewall(){
+ ufw allow 8080;
+ ufw allow 4001;
+ ufw deny 5000;
+ ufw deny 5001;
+ ufw insert 1 allow OpenSSH;
+ echo "y" | ufw enable;
+ ufw reload;
+}
+
+function add_to_cron(){
+ delete_if_exists $cron_script_path;
+
+ # Add startup script to cron (job sheduler) to up IPFS daemon after restart
+ echo "@reboot ipfs daemon &" > $cron_script_path;
+
+ # Add existing cron rules (not related to this ipfs) to cron script, so that they are not removed
+ # https://unix.stackexchange.com/questions/21297/how-do-i-add-an-entry-to-my-crontab
+ crontab -l | grep -v "ipfs daemon" >> $cron_script_path;
+
+ crontab $cron_script_path;
+ systemctl restart cron;
+
+ if crontab -l | grep -q "ipfs daemon"; then
+ echo "IPFS daemon added to cron autorun successfully";
+ else
+ echo_log_err "Warning: adding script to cron autorun failed.";
+ fi;
+}
+
+function run_pinner(){
+ cd $tornado_folder;
+ yarn pin;
+}
+
+
+install_requred_packages;
+install_node;
+download_repo;
+install_node_dependencies;
+run_ipfs_daemon;
+configure_firewall;
+add_to_cron;
+run_pinner;
\ No newline at end of file
diff --git a/scripts/pinIPFS.ts b/scripts/pinIPFS.ts
new file mode 100644
index 0000000..3528207
--- /dev/null
+++ b/scripts/pinIPFS.ts
@@ -0,0 +1,15 @@
+import { getV1Cids } from "../src/downloader.ts";
+import { mainRepos, packageRepos, sitesENS, sourcesDomain } from "../src/contstants.ts";
+import { execSync } from "child_process";
+
+const ensDomains = [...Object.values(mainRepos), ...Object.values(packageRepos), ...sitesENS, sourcesDomain];
+const ipfsCids = await getV1Cids(ensDomains.reduce((acc, dom) => Object.assign(acc, { [dom]: dom }), {}));
+for (const [domain, cid] of Object.entries(ipfsCids)) {
+ try {
+ execSync(`ipfs pin add ${cid}`);
+ } catch (e) {
+ console.error(`Cannot pin ipfs content by cid ${cid} for domain ${domain}`);
+ }
+}
+
+console.log("IPFS cids successfully added");
diff --git a/src/contstants.ts b/src/contstants.ts
index 60d1fd6..1193ba1 100644
--- a/src/contstants.ts
+++ b/src/contstants.ts
@@ -1,7 +1,7 @@
import "dotenv/config";
const rootTornadoDomain = process.env.ENS_ROOT_DOMAIN || "tornadocash.eth";
-const sourcesDomain = "sources." + rootTornadoDomain;
+export const sourcesDomain = "sources." + rootTornadoDomain;
const packagesDomain = "packages." + sourcesDomain;
export const mainRepos = {
@@ -30,6 +30,8 @@ export const packageRepos = {
"merkle-root-updater": "merkle-root-updater." + packagesDomain,
} as const;
+export const sitesENS = ["tornadocash.eth", "nova.tornadocash.eth", "relayers-ui.tornadocash.eth", "docs.tornadocash.eth"] as const;
+
export const knownIpfsResources = [
`https://ipfs.io/ipfs/`,
`https://dweb.link/ipfs/`,
diff --git a/src/downloader.ts b/src/downloader.ts
index a8fa82f..609b3ea 100644
--- a/src/downloader.ts
+++ b/src/downloader.ts
@@ -10,7 +10,7 @@ import { Domains, IPFSCids, RepoName } from "./types.ts";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL || "https://rpc.mevblocker.io");
const git: SimpleGit = simpleGit();
-async function getENSDomainContenthash(repoName: RepoName, domain: string): Promise<[RepoName, string]> {
+async function getENSDomainContenthash(domain: string): Promise