diff --git a/README.md b/README.md index 8b77c2e69..a58515e43 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Erigon is an implementation of Ethereum (aka "Ethereum client"), on the efficien + [Reporting security issues/concerns](#reporting-security-issues-concerns) + [Team](#team) - [Known issues](#known-issues) - + [`htop` shows incorrect memory usage](#-htop--shows-incorrect-memory-usage) + + [`htop` shows incorrect memory usage on LMDB](#htop-shows-incorrect-memory-usage-when-using-lmdb) @@ -91,15 +91,23 @@ Support only remote-miners. ### Windows -Windows users may run erigon in 2 possible ways: +Windows users may run erigon in 3 possible ways: * Build executable binaries natively for Windows using provided `win-build.ps1` PowerShell script which has to be run with local Administrator privileges. The script creates `libmdbx.dll` (MDBX is current default database for Erigon) and copies it into Windows's `system32` folder (generally `C:\Windows\system32`). - Though is still possible to run erigon with LMDB database there's a caveat which might cause your experience with LMDB on Windows uncomfortable: data file allocation is fixed so you need to know in advance how much space you want to allocate for database file using the command line option `--lmdb.mapSize` + There are some requirements for a successful native build on windows : + * [Git](https://git-scm.com/downloads) for Windows must be installed. If you're cloning this repository is very likely you already have it + * [GO Programming Language](https://golang.org/dl/) must be installed. Minimum required version is 1.16 + * [Chocolatey package manager](https://chocolatey.org/) for Windows must be installed. By Chocolatey you need to install the following components : `cmake`, `make`, `mingw` by `choco install cmake make mingw`. + + Though is still possible to run erigon with LMDB database there's a caveat which might cause your experience with LMDB on Windows uncomfortable: data file allocation is fixed so you need to know in advance how much space you want to allocate for database file using the command line option `--lmdb.mapSize`. + Please be advised Erigon will completely remove LMDB support in future releases thus we warmly suggest to resync using the default MDBX database. * Use Docker : see [docker-compose.yml](./docker-compose.yml) -Note that we used to have documentation about using WSL to build Erigon on Windows, which is now removed. This is because we do not consider WSL builds safe when interacting with our database backend - there is a chance of losing data and corrupting database. +* Use WSL (Windows Subsystem for Linux) **strictly on version 2**. Under this option you can build Erigon just as you would on a regular Linux distribution. You can point your data also to any of the mounted Windows partitions (eg. `/mnt/c/[...]`, `/mnt/d/[...]` etc) but in such case be advised performance is impacted: this is due to the fact those mount points use `DrvFS` which is a [network file system](#blocks-execution-is-slow-on-cloud-network-drives) and, additionally, MDBX locks the db for exclusive access which implies only one process at a time can access data. This has consequences on the running of `rpcdaemon` which has to be configured as [Remote DB](#for-remote-db) even if it is executed on the very same computer. +If instead your data is hosted on the native Linux filesystem non limitations apply. +**Please also note the default WSL2 environment has its own IP address which does not match the one of the network interface of Windows host: take this into account when configuring NAT for port 30303 on your router.** Key features ============ @@ -164,7 +172,7 @@ it can run from a snapshot of a database for read-only calls. 🔬 See [RPC-Daemon docs](./cmd/rpcdaemon/README.md) -**For local DB** +#### **For local DB** This is only possible if RPC daemon runs on the same computer as Erigon. This mode of operation uses shared memory access to the database of Erigon, which is reported to have better performance than accessing via TPC socket (see "For remote DB" section below) ``` @@ -174,7 +182,7 @@ This is only possible if RPC daemon runs on the same computer as Erigon. This mo In this mode, some RPC API methods do not work. Please see "For dual mode" section below on how to fix that. -**For remote DB** +#### **For remote DB** This works regardless of whether RPC daemon is on the same computer with Erigon, or on a different one. They use TPC socket connection to pass data between them. To use this mode, run Erigon in one terminal window @@ -260,7 +268,7 @@ Happy testing! 🥤 Known issues ============ -### `htop` shows incorrect memory usage +### `htop` shows incorrect memory usage when using LMDB Erigon's internal DB (LMDB) using `MemoryMap` - when OS does manage all `read, write, cache` operations instead of Application ([linux](https://linux-kernel-labs.github.io/refs/heads/master/labs/memory_mapping.html), [windows](https://docs.microsoft.com/en-us/windows/win32/memory/file-mapping)) @@ -277,7 +285,7 @@ Next tools show correct memory usage of Erigon: - `Prometheus` dashboard shows memory of Go app without OS pages cache (`make prometheus`, open in browser `localhost:3000`, credentials `admin/admin`) - `cat /proc//smaps` -Erigon uses ~4Gb of RAM during genesis sync and < 1Gb during normal work. OS pages cache can utilize unlimited amount of memory. +Erigon uses ~4Gb of RAM during genesis sync and ~1Gb during normal work. OS pages cache can utilize unlimited amount of memory. **Warning:** Multiple instances of Erigon on same machine will touch Disk concurrently, it impacts performance - one of main Erigon optimisations: "reduce Disk random access". diff --git a/ethdb/mdbx/dist/ChangeLog.md b/ethdb/mdbx/dist/ChangeLog.md index 0750143bb..87f4f0c7c 100644 --- a/ethdb/mdbx/dist/ChangeLog.md +++ b/ethdb/mdbx/dist/ChangeLog.md @@ -13,16 +13,20 @@ ChangeLog - [Engage new terminology](https://github.com/erthink/libmdbx/issues/137). - Packages for [Astra Linux](https://astralinux.ru/), [ALT Linux](https://www.altlinux.org/), [ROSA Linux](https://www.rosalinux.ru/), Fedora/RHEL, Debian/Ubuntu. -## v0.10.1 (in development) +## v0.10.1 (scheduled for 2020-06-01) Acknowledgements: - [Alexey Akhunov](https://github.com/AlexeyAkhunov) and [Alex Sharov](https://github.com/AskAlexSharov) for bug reporting and testing. + - [Andrea Lanfranchi](https://github.com/AndreaLanfranchi) for bug reporting and testing related to WSL2. New features: - Added `-p` option to `mdbx_stat` utility for printing page operations statistic. - Added explicit checking for and warning about using unfit github's archives. + - Added fallback from [OFD locking](https://bit.ly/3yFRtYC) to legacy non-OFD POSIX file locks on an `EINVAL` error. + - Added [Plan 9](https://en.wikipedia.org/wiki/9P_(protocol)) network file system to the whitelist for an ability to open a DB in exclusive mode. + - Support for opening from WSL2 environment a DB hosted on Windows drive and mounted via [DrvFs](https://docs.microsoft.com/it-it/archive/blogs/wsl/wsl-file-system-support#drvfs) (i.e by Plan 9 noted above). Fixes: @@ -30,6 +34,7 @@ Fixes: - Fixed confusing/messy errors when build library from unfit github's archives (https://github.com/erthink/libmdbx/issues/197). - Fixed `#​e​l​s​i​f` typo. - Fixed rare unexpected `MDBX_PROBLEM` error during altering data in huge transactions due to wrong spilling/oust of dirty pages (https://github.com/erthink/libmdbx/issues/195). + - Re-Fixed WSL1/WSL2 detection with distinguishing (https://github.com/erthink/libmdbx/issues/97). ## v0.10.0 at 2021-05-09 @@ -182,7 +187,7 @@ Acknowledgements: - Jens Alfke (Mobile Architect at [Couchbase](https://www.couchbase.com/)) for [NimDBX](https://github.com/snej/nimdbx). - Clément Renault (CTO at [MeiliSearch](https://www.meilisearch.com/)) for [mdbx-rs](https://github.com/Kerollmops/mdbx-rs). - - Alex Sharov (Go-Lang Teach Lead at [Erigon/Ethereum](https://ethereum.org/)) for an extreme test cases and bug reporting. + - Alex Sharov (Go-Lang Teach Lead at [TurboGeth/Ethereum](https://ethereum.org/)) for an extreme test cases and bug reporting. - George Hazan (CTO at [Miranda NG](https://www.miranda-ng.org/)) for bug reporting. - [Positive Technologies](https://www.ptsecurity.com/) for funding and [The Standoff](https://standoff365.com/). diff --git a/ethdb/mdbx/dist/VERSION b/ethdb/mdbx/dist/VERSION index 24f56257d..07c3827d9 100644 --- a/ethdb/mdbx/dist/VERSION +++ b/ethdb/mdbx/dist/VERSION @@ -1 +1 @@ -0.10.0.27 +0.10.0.34 diff --git a/ethdb/mdbx/dist/mdbx.c b/ethdb/mdbx/dist/mdbx.c index d1633f651..f9a0cd0e0 100644 --- a/ethdb/mdbx/dist/mdbx.c +++ b/ethdb/mdbx/dist/mdbx.c @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -7565,7 +7565,7 @@ static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) { static void mdbx_dpage_free(MDBX_env *env, MDBX_page *dp, unsigned npages) { VALGRIND_MAKE_MEM_UNDEFINED(dp, pgno2bytes(env, npages)); ASAN_UNPOISON_MEMORY_REGION(dp, pgno2bytes(env, npages)); - if (MDBX_DEBUG || unlikely(env->me_flags & MDBX_PAGEPERTURB)) + if (MDBX_DEBUG != 0 || unlikely(env->me_flags & MDBX_PAGEPERTURB)) memset(dp, -1, pgno2bytes(env, npages)); if (npages == 1 && env->me_dp_reserve_len < env->me_options.dp_reserve_limit) { @@ -8152,7 +8152,7 @@ status_done: ? pgno + 2 : txn->tw.loose_refund_wl; #endif /* MDBX_ENABLE_REFUND */ - if (MDBX_DEBUG || unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) + if (MDBX_DEBUG != 0 || unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) memset(page_data(mp), -1, txn->mt_env->me_psize - PAGEHDRSZ); VALGRIND_MAKE_MEM_NOACCESS(page_data(mp), txn->mt_env->me_psize - PAGEHDRSZ); @@ -8180,7 +8180,7 @@ status_done: } #if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - if (MDBX_DEBUG || unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) + if (MDBX_DEBUG != 0 || unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) #endif mdbx_kill_page(txn, mp, pgno, npages); if (!(txn->mt_flags & MDBX_WRITEMAP)) { @@ -26950,6 +26950,7 @@ static int mdbx_check_fs_local(mdbx_filehandle_t handle, int flags) { strncasecmp("cifs", name, name_len) == 0 || strncasecmp("ncpfs", name, name_len) == 0 || strncasecmp("smbfs", name, name_len) == 0 || + strcasecmp("9P" /* WSL2 */, name) == 0 || ((name_len > 3 && strncasecmp("fuse", name, 4) == 0) && strncasecmp("fuseblk", name, name_len) != 0)) && !(flags & MDBX_EXCLUSIVE)) @@ -28169,9 +28170,9 @@ __dll_export 0, 10, 0, - 27, - {"2021-05-21T00:12:55+03:00", "41721da296c828dd3f7116a97f2ead5ccc38a107", "2b161db6d8acf3fd5112972b09d5a1988a59ad8c", - "v0.10.0-27-g2b161db6"}, + 34, + {"2021-05-28T01:46:24+03:00", "da23506440bf341f805ee4ff2dc69320b7a40e48", "a6c8c20bd96a9ddb0f6594e8098392e8833eeeb5", + "v0.10.0-34-ga6c8c20b"}, sourcery}; __dll_export @@ -29036,7 +29037,11 @@ static __cold uint8_t probe_for_WSL(const char *tag) { const char *const wsl = strstr(tag, "wsl"); if (wsl && wsl[3] >= '2' && wsl[3] <= '9') return wsl[3] - '0'; - return (WSL || wsl || strcasestr(tag, "Microsoft")) ? 1 : 0; + if (WSL || wsl || strcasestr(tag, "Microsoft")) + /* Expecting no new kernel within WSL1, either it will explicitly + * marked by an appropriate WSL-version hint. */ + return (mdbx_linux_kernel_version < /* 4.19.x */ 0x04130000) ? 1 : 2; + return 0; } #endif /* Linux */ @@ -29046,16 +29051,6 @@ mdbx_global_constructor(void) { #if defined(__linux__) || defined(__gnu_linux__) struct utsname buffer; if (uname(&buffer) == 0) { - /* "Official" way of detecting WSL1 but not WSL2 - * https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364 - * - * WARNING: False negative detection of WSL1 will result in DATA LOSS! - * So, the REQUIREMENTS for this code: - * 1. MUST detect WSL1 without false-negatives. - * 2. DESIRABLE detect WSL2 but without the risk of violating the first. */ - mdbx_RunningOnWSL1 = probe_for_WSL(buffer.version) == 1 || - probe_for_WSL(buffer.sysname) == 1 || - probe_for_WSL(buffer.release) == 1; int i = 0; char *p = buffer.release; while (*p && i < 4) { @@ -29071,6 +29066,16 @@ mdbx_global_constructor(void) { ++p; } } + /* "Official" way of detecting WSL1 but not WSL2 + * https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364 + * + * WARNING: False negative detection of WSL1 will result in DATA LOSS! + * So, the REQUIREMENTS for this code: + * 1. MUST detect WSL1 without false-negatives. + * 2. DESIRABLE detect WSL2 but without the risk of violating the first. */ + mdbx_RunningOnWSL1 = probe_for_WSL(buffer.version) == 1 || + probe_for_WSL(buffer.sysname) == 1 || + probe_for_WSL(buffer.release) == 1; } #endif /* Linux */ @@ -29194,6 +29199,22 @@ static int lck_op(mdbx_filehandle_t fd, int cmd, int lck, off_t offset, return MDBX_SUCCESS; } rc = errno; +#if MDBX_USE_OFDLOCKS + if (rc == EINVAL && + (cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK)) { + /* fallback to non-OFD locks */ + if (cmd == F_OFD_SETLK) + cmd = F_SETLK; + else if (cmd == F_OFD_SETLKW) + cmd = F_SETLKW; + else + cmd = F_GETLK; + op_setlk = F_SETLK; + op_setlkw = F_SETLKW; + op_getlk = F_GETLK; + continue; + } +#endif /* MDBX_USE_OFDLOCKS */ if (rc != EINTR || cmd == op_setlkw) { mdbx_assert(nullptr, MDBX_IS_ERROR(rc)); return rc; diff --git a/ethdb/mdbx/dist/mdbx.c++ b/ethdb/mdbx/dist/mdbx.c++ index 4da861c14..07908195a 100644 --- a/ethdb/mdbx/dist/mdbx.c++ +++ b/ethdb/mdbx/dist/mdbx.c++ @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif diff --git a/ethdb/mdbx/dist/mdbx_chk.c b/ethdb/mdbx/dist/mdbx_chk.c index c498255a1..cc1759522 100644 --- a/ethdb/mdbx/dist/mdbx_chk.c +++ b/ethdb/mdbx/dist/mdbx_chk.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -4609,7 +4609,6 @@ int main(int argc, char *argv[]) { quiet = true; break; case 'n': - envflags |= MDBX_NOSUBDIR; break; case 'w': envflags &= ~MDBX_RDONLY; diff --git a/ethdb/mdbx/dist/mdbx_copy.c b/ethdb/mdbx/dist/mdbx_copy.c index 850836822..4a3841177 100644 --- a/ethdb/mdbx/dist/mdbx_copy.c +++ b/ethdb/mdbx/dist/mdbx_copy.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif diff --git a/ethdb/mdbx/dist/mdbx_drop.c b/ethdb/mdbx/dist/mdbx_drop.c index ffe10000a..60176000a 100644 --- a/ethdb/mdbx/dist/mdbx_drop.c +++ b/ethdb/mdbx/dist/mdbx_drop.c @@ -36,7 +36,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -3604,7 +3604,6 @@ int main(int argc, char *argv[]) { delete = true; break; case 'n': - envflags |= MDBX_NOSUBDIR; break; case 's': subname = optarg; diff --git a/ethdb/mdbx/dist/mdbx_dump.c b/ethdb/mdbx/dist/mdbx_dump.c index 8a897bbae..0efd0e428 100644 --- a/ethdb/mdbx/dist/mdbx_dump.c +++ b/ethdb/mdbx/dist/mdbx_dump.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -3791,7 +3791,6 @@ int main(int argc, char *argv[]) { } break; case 'n': - envflags |= MDBX_NOSUBDIR; break; case 'p': mode |= PRINT; diff --git a/ethdb/mdbx/dist/mdbx_load.c b/ethdb/mdbx/dist/mdbx_load.c index 1dce90ee6..6fa843abd 100644 --- a/ethdb/mdbx/dist/mdbx_load.c +++ b/ethdb/mdbx/dist/mdbx_load.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif diff --git a/ethdb/mdbx/dist/mdbx_stat.c b/ethdb/mdbx/dist/mdbx_stat.c index 454eab38d..405a2daac 100644 --- a/ethdb/mdbx/dist/mdbx_stat.c +++ b/ethdb/mdbx/dist/mdbx_stat.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY dfe0671435fed2948a861ec25f1adbf99a470c88be69bcc27b32ca9a7ffc6787_v0_10_0_27_g2b161db6 +#define MDBX_BUILD_SOURCERY 70a2b520f39efb5ffb11dd97c2eef3750a14f311a08a4382f87dd6e307ed6105_v0_10_0_34_ga6c8c20b #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -3601,7 +3601,7 @@ int main(int argc, char *argv[]) { prog = argv[0]; char *envname; char *subname = nullptr; - bool alldbs = false, envinfo = false, envflags = false, pgop = false; + bool alldbs = false, envinfo = false, pgop = false; int freinfo = 0, rdrinfo = 0; if (argc < 2) @@ -3650,7 +3650,6 @@ int main(int argc, char *argv[]) { freinfo += 1; break; case 'n': - envflags |= MDBX_NOSUBDIR; break; case 'r': rdrinfo += 1; @@ -3704,7 +3703,7 @@ int main(int argc, char *argv[]) { } } - rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0); + rc = mdbx_env_open(env, envname, MDBX_RDONLY, 0); if (unlikely(rc != MDBX_SUCCESS)) { error("mdbx_env_open", rc); goto env_close; diff --git a/win-build.ps1 b/win-build.ps1 index 1b65374cb..c26d633ce 100644 --- a/win-build.ps1 +++ b/win-build.ps1 @@ -14,6 +14,16 @@ limitations under the License. #> +$gitErrorText = @" + + Requirement Error. + You need to have Git installed + Please visit https://git-scm.com/downloads and download the appropriate + installer. + +"@ + + $goErrorText = @" Requirement Error. @@ -66,36 +76,153 @@ $MyContext.StartDir = (Get-Location -PSProvider FileSystem).ProviderPath $MyContext.WinVer = (Get-WmiObject Win32_OperatingSystem).Version.Split(".") $MyContext.PSVer = [int]$PSVersionTable.PSVersion.Major -# Test we have ADMIN Privileges -$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent(); -$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID); -$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator; -if (!($myWindowsPrincipal.IsInRole($adminRole))) { - Write-Host $privilegeErrorText - return +# ----------------------------------------------------------------------------- +# Function : Test-Administrator +# ----------------------------------------------------------------------------- +# Description : Checks the script is running with Administrator privileges +# Returns : $true / $false +# ----------------------------------------------------------------------------- +function Test-Administrator { + + $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent(); + $myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID); + $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator; + Write-Output ($myWindowsPrincipal.IsInRole($adminRole)) +} + +# ----------------------------------------------------------------------------- +# Function : Test-Valid-Env +# ----------------------------------------------------------------------------- +# Description : Checks the named variable provided is present in env: +# Returns : $true / $false +# ----------------------------------------------------------------------------- +function Get-Env { + param ([string]$varName = $(throw "A variable name must be provided")) + $result = Get-ChildItem env: | Where-Object {$_.Name -ieq $varName} + if (-not $result) { + Write-Output $null + } else { + Write-Output $result.Value + } } +# ----------------------------------------------------------------------------- +# Function : Get-Uninstall-Item +# ----------------------------------------------------------------------------- +# Description : Try get uninstall key for given item pattern +# Returns : object +# ----------------------------------------------------------------------------- +function Get-Uninstall-Item { + param ([string]$pattern = $(throw "A search pattern must be provided")) + + # Trying to get the enumerable of all installed programs using Get-ItemProperty may cause + # exceptions due to possible garbage values insterted into the registry by installers. + # Specifically an invalid cast exception throws when registry keys contain invalid DWORD data. + # See https://github.com/PowerShell/PowerShell/issues/9552 + # Due to this all items must be parsed one by one -# Test GO is installed and is at least 1.16 -$goInstalled = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -imatch "^Go\ Programming\ Language"}) -if(!$goInstalled) { - Write-Host $goErrorText + $Private:regUninstallPath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $Private:result = $null + Get-ChildItem -Path $regUninstallPath | ForEach-Object { + if(-not $result) { + $item = Get-ItemProperty -Path $_.pspath + if ($item.DisplayName -imatch $pattern) { + $result = $item + # DO NOT use break + } + } + } + Write-Output $result +} + +# ----------------------------------------------------------------------------- +# Function : Test-GO-Installed +# ----------------------------------------------------------------------------- +# Description : Checks whether or not GO language is installed +# Returns : $true / $false +# ----------------------------------------------------------------------------- +function Test-GO-Installed { + + $Private:item = Get-Uninstall-Item "^Go\ Programming\ Language" + $Private:result = $false + + if ($Private:item) { + $Private:versionMajor = [int]$item.VersionMajor + $Private:versionMinor = [int]$item.VersionMinor + if ($Private:versionMajor -ge 1 -and $Private:versionMinor -ge 16) { + Write-Host " Found GO version $($Private:item.DisplayVersion)" + $Private:result = $true + } + } + + Write-Output $Private:result +} + +# ----------------------------------------------------------------------------- +# Function : Test-Git-Installed +# ----------------------------------------------------------------------------- +# Description : Checks whether or not Git is installed +# Returns : $true / $false +# ----------------------------------------------------------------------------- +function Test-Git-Installed { + + $Private:item = Get-Uninstall-Item "^Git\ " + $Private:result = $false + + if ($Private:item) { + Write-Host " Found Git version $($Private:item.DisplayVersion)" + $Private:result = $true + } + + Write-Output $Private:result +} + +# Test requirements + +## Test Git is installed +if(!(Test-Git-Installed)) { + Write-Host $gitErrorText return } -Write-Host " Found GO version $($goInstalled.DisplayVersion)" -$goVersionMajor = [int]$goInstalled.VersionMajor -$goVersionMinor = [int]$goInstalled.VersionMinor -if($goVersionMajor -lt 1 -or $goVersionMinor -lt 16) { - Write-Host $goErrorText +Get-Command git.exe | Out-Null +if (!($?)) { + Write-Host @" + + Error ! + Though Git installation is found I could not get + the Git binary executable. Ensure Git installation + directory is properly inserted into your PATH + environment variable. + +"@ return } -# Test Chocolatey Install -if(!(Test-Path env:chocolateyInstall)) { +## GO language is installed +if(!(Test-GO-Installed)) { + Write-Host $goErrorText + return +} +Get-Command go.exe | Out-Null +if (!($?)) { + Write-Host @" + + Error ! + Though GO installation is found I could not get + the GO binary executable. Ensure GO installation + directory is properly inserted into your PATH + environment variable. + +"@ + return +} + +## Test Chocolatey Install +$chocolateyPath = Get-Env "chocolateyInstall" +if(-not $chocolateyPath) { Write-Host $chocolateyErrorText return } -$chocolateyPath = $env:ChocolateyInstall # Test Chocolatey bin directory is actually in %PATH% $chocolateyBinPath = (Join-Path $chocolateyPath "bin") @@ -114,7 +241,7 @@ if(!$chocolateyBinPathInPath) { return } -# Test Chocolatey Components +## Test Chocolatey Components $chocolateyHasCmake = $false $chocolateyHasMake = $false $chocolateyHasMingw = $false @@ -139,6 +266,27 @@ If(!$chocolateyHasCmake -or !$chocolateyHasMake -or !$chocolateyHasMingw) { return } +Get-Command cmake.exe | Out-Null +if (!($?)) { + Write-Host @" + + Error ! + Though chocolatey cmake installation is found I could not get + the cmake binary executable. Ensure cmake installation + directory is properly inserted into your PATH + environment variable. + (Usually $(Join-Path $env:ProgramFiles "Cmake\bin")) + +"@ + return +} + +## Administrator Privileges +if (!(Test-Administrator)) { + Write-Host $privilegeErrorText + return +} + # Enter MDBX directory and build libmdbx.dll Write-Host " Building libmdbx.dll ..." Set-Location (Join-Path $MyContext.Directory "ethdb\mdbx\dist")