Enable Compatibility with Windows (#2333)

## Issue Addressed

Windows incompatibility.

## Proposed Changes

On windows, lighthouse needs to default to STDIN as tty doesn't exist. Also Windows uses ACLs for file permissions. So to mirror chmod 600, we will remove every entry in a file's ACL and add only a single SID that is an alias for the file owner.

Beyond that, there were several changes made to different unit tests because windows has slightly different error messages as well as frustrating nuances around killing a process :/

## Additional Info

Tested on my Windows VM and it appears to work, also compiled & tested on Linux with these changes. Permissions look correct on both platforms now. Just waiting for my validator to activate on Prater so I can test running full validator client on windows.

Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com>
Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
ethDreamer
2021-05-19 23:05:16 +00:00
parent 58e52f8f40
commit ba55e140ae
43 changed files with 607 additions and 179 deletions

View File

@@ -39,6 +39,7 @@ logging = { path = "../common/logging" }
environment = { path = "../lighthouse/environment" }
parking_lot = "0.11.0"
exit-future = "0.2.0"
filesystem = { path = "../common/filesystem" }
libc = "0.2.79"
eth2_ssz_derive = "0.1.0"
hex = "0.4.2"

View File

@@ -16,6 +16,7 @@ serde = "1.0.116"
serde_derive = "1.0.116"
serde_json = "1.0.58"
serde_utils = { path = "../../consensus/serde_utils" }
filesystem = { path = "../../common/filesystem" }
[dev-dependencies]
rayon = "1.4.1"

View File

@@ -4,8 +4,21 @@ OUTPUT_DIR := interchange-tests
TARBALL := $(OUTPUT_DIR)-$(TESTS_TAG).tar.gz
ARCHIVE_URL := https://github.com/eth2-clients/slashing-protection-interchange-tests/tarball/$(TESTS_TAG)
ifeq ($(OS),Windows_NT)
ifeq (, $(shell where rm))
rmfile = if exist $(1) (del /F /Q $(1))
rmdir = if exist $(1) (rmdir /Q /S $(1))
else
rmfile = rm -f $(1)
rmdir = rm -rf $(1)
endif
else
rmfile = rm -f $(1)
rmdir = rm -rf $(1)
endif
$(OUTPUT_DIR): $(TARBALL)
rm -rf $@
$(call rmdir,$@)
mkdir $@
tar --strip-components=1 -xzf $^ -C $@
@@ -13,13 +26,13 @@ $(TARBALL):
curl --fail -L -o $@ $(ARCHIVE_URL)
clean-test-files:
rm -rf $(OUTPUT_DIR)
$(call rmdir,$(OUTPUT_DIR))
clean-archives:
rm -f $(TARBALL)
$(call rmfile,$(TARBALL))
generate:
rm -rf $(GENERATE_DIR)
$(call rmdir,$(GENERATE_DIR))
cargo run --release --bin test_generator -- $(GENERATE_DIR)
clean: clean-test-files clean-archives

View File

@@ -30,6 +30,7 @@ pub enum NotSafe {
UnregisteredValidator(PublicKeyBytes),
InvalidBlock(InvalidBlock),
InvalidAttestation(InvalidAttestation),
PermissionsError,
IOError(ErrorKind),
SQLError(String),
SQLPoolError(String),

View File

@@ -5,9 +5,10 @@ use crate::interchange::{
use crate::signed_attestation::InvalidAttestation;
use crate::signed_block::InvalidBlock;
use crate::{hash256_from_row, NotSafe, Safe, SignedAttestation, SignedBlock, SigningRoot};
use filesystem::restrict_file_permissions;
use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::{params, OptionalExtension, Transaction, TransactionBehavior};
use std::fs::{File, OpenOptions};
use std::fs::OpenOptions;
use std::path::Path;
use std::time::Duration;
use types::{AttestationData, BeaconBlockHeader, Epoch, Hash256, PublicKeyBytes, SignedRoot, Slot};
@@ -46,13 +47,13 @@ impl SlashingDatabase {
///
/// Error if a database (or any file) already exists at `path`.
pub fn create(path: &Path) -> Result<Self, NotSafe> {
let file = OpenOptions::new()
let _file = OpenOptions::new()
.write(true)
.read(true)
.create_new(true)
.open(path)?;
Self::set_db_file_permissions(&file)?;
restrict_file_permissions(path).map_err(|_| NotSafe::PermissionsError)?;
let conn_pool = Self::open_conn_pool(path)?;
let conn = conn_pool.get()?;
@@ -121,21 +122,6 @@ impl SlashingDatabase {
Ok(())
}
/// Set the database file to readable and writable only by its owner (0600).
#[cfg(unix)]
fn set_db_file_permissions(file: &File) -> Result<(), NotSafe> {
use std::os::unix::fs::PermissionsExt;
let mut perm = file.metadata()?.permissions();
perm.set_mode(0o600);
file.set_permissions(perm)?;
Ok(())
}
// TODO: add support for Windows ACLs
#[cfg(windows)]
fn set_db_file_permissions(file: &File) -> Result<(), NotSafe> {}
/// Creates an empty transaction and drops it. Used to test whether the database is locked.
pub fn test_transaction(&self) -> Result<(), NotSafe> {
let mut conn = self.conn_pool.get()?;

View File

@@ -146,7 +146,7 @@ impl KeyCache {
let bytes = serde_json::to_vec(self).map_err(Error::UnableToEncodeFile)?;
write_file_via_temporary(&cache_path, &temp_path, &bytes)
.map_err(Error::UnableToWriteFile)?;
.map_err(Error::UnableToCreateFile)?;
self.state = State::DecryptedAndSaved;
Ok(true)
@@ -245,6 +245,7 @@ pub enum Error {
UnableToEncodeFile(serde_json::Error),
/// The cache file or its temporary could not be written to the filesystem.
UnableToWriteFile(io::Error),
UnableToCreateFile(filesystem::Error),
/// Couldn't decrypt the cache file
UnableToDecrypt(KeystoreError),
UnableToEncrypt(KeystoreError),