mirror of
				https://github.com/0glabs/0g-storage-node.git
				synced 2025-11-04 08:37:27 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			265 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import os
 | 
						|
import time
 | 
						|
import shutil
 | 
						|
import stat
 | 
						|
import requests
 | 
						|
import platform
 | 
						|
from enum import Enum, unique
 | 
						|
 | 
						|
from utility.utils import is_windows_platform, wait_until
 | 
						|
 | 
						|
# v1.0.0-ci release
 | 
						|
GITHUB_DOWNLOAD_URL = (
 | 
						|
    "https://api.github.com/repos/0glabs/0g-storage-node/releases/152560136"
 | 
						|
)
 | 
						|
 | 
						|
CONFLUX_BINARY = "conflux.exe" if is_windows_platform() else "conflux"
 | 
						|
BSC_BINARY = "geth.exe" if is_windows_platform() else "geth"
 | 
						|
ZG_BINARY = "0gchaind.exe" if is_windows_platform() else "0gchaind"
 | 
						|
CLIENT_BINARY = (
 | 
						|
    "0g-storage-client.exe" if is_windows_platform() else "0g-storage-client"
 | 
						|
)
 | 
						|
 | 
						|
CLI_GIT_REV = "98d74b7e7e6084fc986cb43ce2c66692dac094a6"
 | 
						|
 | 
						|
 | 
						|
@unique
 | 
						|
class BuildBinaryResult(Enum):
 | 
						|
    AlreadyExists = 0
 | 
						|
    Installed = 1
 | 
						|
    NotInstalled = 2
 | 
						|
 | 
						|
 | 
						|
def build_conflux(dir: str) -> BuildBinaryResult:
 | 
						|
    # Download or build conflux binary if absent
 | 
						|
    result = __download_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=CONFLUX_BINARY,
 | 
						|
        github_url=GITHUB_DOWNLOAD_URL,
 | 
						|
        asset_name=__asset_name(CONFLUX_BINARY, zip=True),
 | 
						|
    )
 | 
						|
 | 
						|
    if (
 | 
						|
        result == BuildBinaryResult.AlreadyExists
 | 
						|
        or result == BuildBinaryResult.Installed
 | 
						|
    ):
 | 
						|
        return result
 | 
						|
 | 
						|
    return __build_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=CONFLUX_BINARY,
 | 
						|
        github_url="https://github.com/Conflux-Chain/conflux-rust.git",
 | 
						|
        build_cmd="cargo build --release --bin conflux",
 | 
						|
        compiled_relative_path=["target", "release"],
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def build_bsc(dir: str) -> BuildBinaryResult:
 | 
						|
    # Download bsc binary if absent
 | 
						|
    result = __download_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=BSC_BINARY,
 | 
						|
        github_url="https://api.github.com/repos/bnb-chain/bsc/releases/79485895",
 | 
						|
        asset_name=__asset_name(BSC_BINARY),
 | 
						|
    )
 | 
						|
 | 
						|
    # Requires to download binary successfully, since it is not ready to build
 | 
						|
    # binary from source code.
 | 
						|
    assert result != BuildBinaryResult.NotInstalled, (
 | 
						|
        "Cannot download binary from github [%s]" % BSC_BINARY
 | 
						|
    )
 | 
						|
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def build_zg(dir: str) -> BuildBinaryResult:
 | 
						|
    # Download or build 0gchain binary if absent
 | 
						|
    result = __download_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=ZG_BINARY,
 | 
						|
        github_url=GITHUB_DOWNLOAD_URL,
 | 
						|
        asset_name=__asset_name(ZG_BINARY, zip=True),
 | 
						|
    )
 | 
						|
 | 
						|
    if (
 | 
						|
        result == BuildBinaryResult.AlreadyExists
 | 
						|
        or result == BuildBinaryResult.Installed
 | 
						|
    ):
 | 
						|
        return result
 | 
						|
 | 
						|
    return __build_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=ZG_BINARY,
 | 
						|
        github_url="https://github.com/0glabs/0g-chain.git",
 | 
						|
        build_cmd="git fetch origin pull/74/head:pr-74; git checkout pr-74; make install; cp $(go env GOPATH)/bin/0gchaind .",
 | 
						|
        compiled_relative_path=[],
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def build_cli(dir: str) -> BuildBinaryResult:
 | 
						|
    # Build 0g-storage-client binary if absent
 | 
						|
    return __build_from_github(
 | 
						|
        dir=dir,
 | 
						|
        binary_name=CLIENT_BINARY,
 | 
						|
        github_url="https://github.com/0glabs/0g-storage-client.git",
 | 
						|
        build_cmd="go build",
 | 
						|
        compiled_relative_path=[],
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def __asset_name(binary_name: str, zip: bool = False) -> str:
 | 
						|
    sys = platform.system().lower()
 | 
						|
    if sys == "linux":
 | 
						|
        return f"{binary_name}_linux.zip" if zip else f"{binary_name}_linux"
 | 
						|
    elif sys == "windows":
 | 
						|
        binary_name = binary_name.removesuffix(".exe")
 | 
						|
        return f"{binary_name}_windows.zip" if zip else f"{binary_name}_windows.exe"
 | 
						|
    elif sys == "darwin":
 | 
						|
        return f"{binary_name}_mac.zip" if zip else f"{binary_name}_mac"
 | 
						|
    else:
 | 
						|
        raise RuntimeError("Unable to recognize platform")
 | 
						|
 | 
						|
 | 
						|
def __build_from_github(
 | 
						|
    dir: str,
 | 
						|
    binary_name: str,
 | 
						|
    github_url: str,
 | 
						|
    build_cmd: str,
 | 
						|
    compiled_relative_path: list[str],
 | 
						|
    git_rev=None,
 | 
						|
) -> BuildBinaryResult:
 | 
						|
    if git_rev is None:
 | 
						|
        versioned_binary_name = binary_name
 | 
						|
    elif binary_name.endswith(".exe"):
 | 
						|
        versioned_binary_name = binary_name.removesuffix(".exe") + f"_{git_rev}.exe"
 | 
						|
    else:
 | 
						|
        versioned_binary_name = f"{binary_name}_{git_rev}"
 | 
						|
 | 
						|
    binary_path = os.path.join(dir, binary_name)
 | 
						|
    versioned_binary_path = os.path.join(dir, versioned_binary_name)
 | 
						|
    if os.path.exists(versioned_binary_path):
 | 
						|
        __create_sym_link(versioned_binary_name, binary_name, dir)
 | 
						|
        return BuildBinaryResult.AlreadyExists
 | 
						|
 | 
						|
    start_time = time.time()
 | 
						|
 | 
						|
    # clone code from github to a temp folder
 | 
						|
    code_tmp_dir_name = (
 | 
						|
        binary_name[:-4] if is_windows_platform() else binary_name
 | 
						|
    ) + "_tmp"
 | 
						|
    code_tmp_dir = os.path.join(dir, code_tmp_dir_name)
 | 
						|
    if os.path.exists(code_tmp_dir):
 | 
						|
        shutil.rmtree(code_tmp_dir)
 | 
						|
    os.system(f"git clone {github_url} {code_tmp_dir}")
 | 
						|
 | 
						|
    # build binary
 | 
						|
    origin_path = os.getcwd()
 | 
						|
    os.chdir(code_tmp_dir)
 | 
						|
    if git_rev is not None:
 | 
						|
        os.system(f"git checkout {git_rev}")
 | 
						|
    os.system(build_cmd)
 | 
						|
 | 
						|
    # copy compiled binary to right place
 | 
						|
    compiled_binary = os.path.join(code_tmp_dir, *compiled_relative_path, binary_name)
 | 
						|
    shutil.copyfile(compiled_binary, versioned_binary_path)
 | 
						|
    __create_sym_link(versioned_binary_name, binary_name, dir)
 | 
						|
 | 
						|
    if not is_windows_platform():
 | 
						|
        st = os.stat(binary_path)
 | 
						|
        os.chmod(binary_path, st.st_mode | stat.S_IEXEC)
 | 
						|
 | 
						|
    os.chdir(origin_path)
 | 
						|
 | 
						|
    shutil.rmtree(code_tmp_dir, ignore_errors=True)
 | 
						|
 | 
						|
    print(
 | 
						|
        "Completed to build binary "
 | 
						|
        + binary_name
 | 
						|
        + ", Elapsed: "
 | 
						|
        + str(int(time.time() - start_time))
 | 
						|
        + " seconds",
 | 
						|
        flush=True,
 | 
						|
    )
 | 
						|
 | 
						|
    return BuildBinaryResult.Installed
 | 
						|
 | 
						|
 | 
						|
def __create_sym_link(src, dst, path=None):
 | 
						|
    if src == dst:
 | 
						|
        return
 | 
						|
 | 
						|
    origin_path = os.getcwd()
 | 
						|
    if path is not None:
 | 
						|
        os.chdir(path)
 | 
						|
 | 
						|
    if os.path.exists(dst):
 | 
						|
        if os.path.isdir(dst):
 | 
						|
            shutil.rmtree(dst)
 | 
						|
        else:
 | 
						|
            os.remove(dst)
 | 
						|
 | 
						|
    # Windows requires admin priviledge, use copy instead.
 | 
						|
    if is_windows_platform():
 | 
						|
        shutil.copy(src, dst)
 | 
						|
    else:
 | 
						|
        os.symlink(src, dst)
 | 
						|
 | 
						|
    os.chdir(origin_path)
 | 
						|
 | 
						|
 | 
						|
def __download_from_github(
 | 
						|
    dir: str, binary_name: str, github_url: str, asset_name: str
 | 
						|
) -> BuildBinaryResult:
 | 
						|
    if not os.path.exists(dir):
 | 
						|
        os.makedirs(dir, exist_ok=True)
 | 
						|
 | 
						|
    binary_path = os.path.join(dir, binary_name)
 | 
						|
    if os.path.exists(binary_path):
 | 
						|
        return BuildBinaryResult.AlreadyExists
 | 
						|
 | 
						|
    print("Begin to download binary from github: %s" % binary_name, flush=True)
 | 
						|
 | 
						|
    start_time = time.time()
 | 
						|
 | 
						|
    req = requests.get(github_url)
 | 
						|
    assert req.ok, "Failed to request: %s" % github_url
 | 
						|
    download_url = None
 | 
						|
    for asset in req.json()["assets"]:
 | 
						|
        if asset["name"].lower() == asset_name:
 | 
						|
            download_url = asset["browser_download_url"]
 | 
						|
            break
 | 
						|
 | 
						|
    if download_url is None:
 | 
						|
        print(f"Cannot find asset by name {asset_name}", flush=True)
 | 
						|
        return BuildBinaryResult.NotInstalled
 | 
						|
 | 
						|
    content = requests.get(download_url).content
 | 
						|
 | 
						|
    # Supports to read from zipped binary
 | 
						|
    if asset_name.endswith(".zip"):
 | 
						|
        asset_path = os.path.join(dir, asset_name)
 | 
						|
        with open(asset_path, "xb") as f:
 | 
						|
            f.write(content)
 | 
						|
        shutil.unpack_archive(asset_path, dir)
 | 
						|
        assert os.path.exists(
 | 
						|
            binary_path
 | 
						|
        ), f"Cannot find binary after unzip, binary = {binary_name}, asset = {asset_name}"
 | 
						|
    else:
 | 
						|
        with open(binary_path, "xb") as f:
 | 
						|
            f.write(content)
 | 
						|
 | 
						|
    if not is_windows_platform():
 | 
						|
        st = os.stat(binary_path)
 | 
						|
        os.chmod(binary_path, st.st_mode | stat.S_IEXEC)
 | 
						|
 | 
						|
    wait_until(lambda: os.access(binary_path, os.X_OK), timeout=120)
 | 
						|
 | 
						|
    print(
 | 
						|
        "Completed to download binary, Elapsed: "
 | 
						|
        + str(int(time.time() - start_time))
 | 
						|
        + " seconds",
 | 
						|
        flush=True,
 | 
						|
    )
 | 
						|
 | 
						|
    return BuildBinaryResult.Installed
 |