XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

namespace XFESystem.DriverOracle;

internal static class Program
{
    private static readonly JsonSerializerOptions Json = new() { WriteIndented = true };

    public static int Main(string[] args)
    {
        if (args.Length > 1 || (args.Length == 1 && args[0] is not ("--execute" or "--self-test")))
        {
            Console.Error.WriteLine("Usage: DriverOracle [--execute | --self-test]. Default: query only. No external PTX or output paths are accepted.");
            return 2;
        }
        bool execute = args is ["--execute"], selfTest = args is ["--self-test"];
        string root = FindRoot(), output = Path.Combine(root, "build", "Gpu", "HostOracle-" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + "-" + Guid.NewGuid().ToString("N")[..8]);
        if (Directory.Exists(output) || File.Exists(output)) throw new IOException("Refusing to reuse oracle evidence.");
        Directory.CreateDirectory(output);
        var sourceHashes = Sources(root);
        var proof = new Dictionary<string, object?>
        {
            ["Kind"] = "XfeWindowsHostCudaOracle.V1", ["Scope"] = "WindowsHostOnly",
            ["Mode"] = execute ? "ExecuteFixedVectorKernel" : selfTest ? "OfflineVerifierTests" : "QueryOnly",
            ["GuestCudaVerified"] = false, ["GpuRasterizationVerified"] = false, ["GuestGpuExecutionPassed"] = false,
            ["FullReleaseQualified"] = false, ["PhysicalXfeBootVerified"] = false,
            ["Passed"] = false, ["ActualHostExecutionPassed"] = false, ["QueryPassed"] = false,
            ["ExplicitExecutionRequested"] = execute, ["StartedUtc"] = DateTime.UtcNow.ToString("O"),
            ["SourceSha256"] = sourceHashes, ["OutputDirectory"] = output,
            ["ManagedAssemblySha256"] = HashFile(Assembly.GetExecutingAssembly().Location),
            ["Framework"] = RuntimeInformation.FrameworkDescription,
            ["HostOS"] = RuntimeInformation.OSDescription, ["ProcessArchitecture"] = RuntimeInformation.ProcessArchitecture.ToString(),
            ["MaximumDeviceAllocationBytes"] = VectorCase.MaximumDeviceBytes,
            ["HostDriverInstallResetRebindOrReboot"] = false,
            ["Meaning"] = "Host reference-program/cubin portability oracle only. No XFESystem guest, renderer, presentation, or standalone CUDA claim."
        };
        CudaDriver? driver = null; string? beforeDll = null;
        using var trace = new StreamWriter(new FileStream(Path.Combine(output, "Calls.jsonl"), FileMode.CreateNew, FileAccess.Write, FileShare.Read), new UTF8Encoding(false)) { AutoFlush = true };
        try
        {
            if (!BitConverter.IsLittleEndian) throw new PlatformNotSupportedException("The fixed vector/cubin proof requires little endian.");
            Save(output, "Attempt.json", JsonSerializer.SerializeToUtf8Bytes(proof, Json));
            byte[] ptx = ReadFixedPtx(root);
            proof["PtxSha256"] = Hash(ptx); proof["PtxBytes"] = ptx.Length;
            if (selfTest)
            {
                proof["VerifierChecksPassed"] = VectorCase.SelfTest();
                proof["CpuOnlyVerifierTests"] = true; proof["Passed"] = true;
            }
            else
            {
                if (!OperatingSystem.IsWindows() || !Environment.Is64BitProcess || RuntimeInformation.ProcessArchitecture != Architecture.X64)
                    throw new PlatformNotSupportedException("This oracle requires a Windows x64 process.");
                // Process-local opt-out: the fixed proof writes its own generated
                // cubin only inside its fresh evidence directory.
                Environment.SetEnvironmentVariable("CUDA_CACHE_DISABLE", "1", EnvironmentVariableTarget.Process);
                proof["CudaDiskCacheDisabledInThisProcess"] = true;
                string dll = Path.Combine(Environment.SystemDirectory, "nvcuda.dll");
                beforeDll = HashFile(dll); proof["DriverDllPath"] = dll; proof["DriverDllSha256"] = beforeDll;
                driver = new CudaDriver(trace);
                CudaDevice[] devices = driver.Query(); proof["Devices"] = devices;
                proof["DriverApiVersion"] = driver.Version;
                proof["DriverSupportedCudaVersion"] = $"{driver.Version / 1000}.{driver.Version % 1000 / 10}";
                proof["DriverVersionMeaning"] = "Maximum CUDA API version supported by this driver; not an installed Toolkit version.";
                proof["QueryPassed"] = true;
                if (execute)
                {
                    var exact = devices.Where(device => device.Name == "NVIDIA GeForce RTX 5090" && device.Major == 12 && device.Minor == 0 && device.WindowsPciIdentity is not null).ToArray();
                    if (exact.Length != 1) throw new InvalidOperationException("Execution requires exactly one PCI-bus-matched 10DE:2B85 RTX 5090 with compute capability 12.0.");
                    proof["SelectedDevice"] = exact[0];
                    var execution = new HostExecution(); execution.Run(driver, exact[0], ptx, output); proof["Execution"] = execution;
                    proof["ActualHostExecutionPassed"] = execution.ActualHostExecutionPassed;
                    proof["Passed"] = execution.ActualHostExecutionPassed && driver.Calls.All(call => call.ReturnCode == 0);
                    if (!execution.ActualHostExecutionPassed) proof["Error"] = execution.Error ?? "Host CUDA execution or cleanup did not pass.";
                }
                else
                {
                    proof["ContextCreated"] = false; proof["DeviceMemoryAllocated"] = false; proof["KernelSubmitted"] = false;
                    proof["Passed"] = true;
                }
            }
        }
        catch (Exception error) { proof["Passed"] = false; proof["ActualHostExecutionPassed"] = false; proof["Error"] = error.ToString(); }
        finally
        {
            if (driver is not null)
            {
                proof["ReturnCodes"] = driver.Calls; driver.Dispose(); proof["DriverLibraryReleased"] = driver.LibraryReleased;
            }
            try
            {
                bool unchanged = sourceHashes.OrderBy(item => item.Key).SequenceEqual(Sources(root).OrderBy(item => item.Key));
                proof["SourceUnchanged"] = unchanged;
                bool driverUnchanged = beforeDll is null || HashFile(Path.Combine(Environment.SystemDirectory, "nvcuda.dll")) == beforeDll;
                proof["DriverDllUnchanged"] = driverUnchanged;
                if (!unchanged || !driverUnchanged) { proof["Passed"] = false; proof["ActualHostExecutionPassed"] = false; proof["Error"] = "Source or pinned driver DLL changed during the oracle."; }
            }
            catch (Exception error) { proof["Passed"] = false; proof["ActualHostExecutionPassed"] = false; proof["FinalBindingError"] = error.ToString(); }
            trace.Flush(); trace.Dispose(); proof["CallsTraceSha256"] = HashFile(Path.Combine(output, "Calls.jsonl"));
            proof["FinishedUtc"] = DateTime.UtcNow.ToString("O");
            Save(output, "Result.json", JsonSerializer.SerializeToUtf8Bytes(proof, Json));
        }
        Console.WriteLine(JsonSerializer.Serialize(new { Result = Path.Combine(output, "Result.json"), Scope = "WindowsHostOnly", Passed = proof["Passed"], ActualHostExecutionPassed = proof["ActualHostExecutionPassed"], GuestCudaVerified = false, GpuRasterizationVerified = false }, Json));
        return proof["Passed"] is true ? 0 : 1;
    }

    private static byte[] ReadFixedPtx(string root)
    {
        using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("XfeVectorAdd.ptx") ?? throw new InvalidOperationException("The fixed kernel is absent from the tool.");
        if (resource.Length is < 64 or > 8192) throw new InvalidOperationException("The fixed PTX exceeds its size bound.");
        using var memory = new MemoryStream(); resource.CopyTo(memory); byte[] ptx = memory.ToArray();
        byte[] source = File.ReadAllBytes(Path.Combine(root, "Tools", "Gpu", "Kernels", "XfeVectorAdd.ptx"));
        if (!ptx.AsSpan().SequenceEqual(source)) throw new InvalidOperationException("The current PTX differs from the compiled, embedded fixed kernel.");
        string text = Encoding.ASCII.GetString(ptx);
        if (!text.Contains(".version 8.7", StringComparison.Ordinal) || !text.Contains(".target sm_120", StringComparison.Ordinal) || !text.Contains(".visible .entry XfeVectorAdd(", StringComparison.Ordinal) || ptx.Contains((byte)0))
            throw new InvalidOperationException("The embedded PTX is not the fixed SM120 vector program.");
        return ptx;
    }

    private static string FindRoot()
    {
        for (var directory = new DirectoryInfo(AppContext.BaseDirectory); directory is not null; directory = directory.Parent)
            if (File.Exists(Path.Combine(directory.FullName, "Tools", "Gpu", "DriverOracle", "DriverOracle.csproj"))) return directory.FullName;
        throw new DirectoryNotFoundException("Run the source-built oracle from an artifacts directory within its repository.");
    }
    private static SortedDictionary<string, string> Sources(string root)
    {
        var hashes = new SortedDictionary<string, string>(StringComparer.Ordinal);
        foreach (string file in Directory.GetFiles(Path.Combine(root, "Tools", "Gpu", "DriverOracle"), "*", SearchOption.TopDirectoryOnly).Order())
            hashes[Path.GetRelativePath(root, file).Replace('\\', '/')] = HashFile(file);
        const string kernel = "Tools/Gpu/Kernels/XfeVectorAdd.ptx"; hashes[kernel] = HashFile(Path.Combine(root, kernel));
        return hashes;
    }
    internal static string Hash(ReadOnlySpan<byte> data) => Convert.ToHexStringLower(SHA256.HashData(data));
    internal static string HashFile(string path) { using var file = File.OpenRead(path); return Convert.ToHexStringLower(SHA256.HashData(file)); }
    internal static void Save(string output, string name, ReadOnlySpan<byte> bytes)
    {
        if (Path.GetFileName(name) != name) throw new ArgumentException("Oracle output must be a fixed leaf name.");
        using var stream = new FileStream(Path.Combine(output, name), FileMode.CreateNew, FileAccess.Write, FileShare.Read);
        stream.Write(bytes); stream.Flush(true);
    }
}